瀏覽代碼

Extract response object, create uploaded file struct

timvisee 7 年之前
父節點
當前提交
c92ab109f6
共有 6 個文件被更改,包括 122 次插入35 次删除
  1. 1 0
      src/action/mod.rs
  2. 37 0
      src/action/upload.rs
  3. 5 0
      src/cmd/cmd_upload.rs
  4. 12 35
      src/main.rs
  5. 66 0
      src/send/file.rs
  6. 1 0
      src/send/mod.rs

+ 1 - 0
src/action/mod.rs

@@ -0,0 +1 @@
+pub mod upload;

+ 37 - 0
src/action/upload.rs

@@ -0,0 +1,37 @@
+use super::super::send::file::File;
+
+/// The response from the server after a file has been uploaded.
+/// This response contains the file ID and owner key, to manage the file.
+///
+/// It also contains the download URL, although an additional secret is
+/// required.
+///
+/// The download URL can be generated using `download_url()` which will
+/// include the required secret in the URL.
+#[derive(Debug, Deserialize)]
+pub struct UploadResponse {
+    /// The file ID.
+    id: String,
+
+    /// The URL the file is reachable at.
+    /// This includes the file ID, but does not include the secret.
+    url: String,
+
+    /// The owner key, used to do further file modifications.
+    owner: String,
+}
+
+impl UploadResponse {
+    /// Convert this response into a file object.
+    ///
+    /// The `host` and `secret` must be given.
+    pub fn into_file(self, host: String, secret: Vec<u8>) -> File {
+        File::new_now(
+            self.id,
+            host,
+            self.url,
+            secret,
+            self.owner,
+        )
+    }
+}

+ 5 - 0
src/cmd/cmd_upload.rs

@@ -46,4 +46,9 @@ impl<'a: 'b, 'b> CmdUpload<'a> {
         self.matches.value_of("FILE")
         self.matches.value_of("FILE")
             .expect("no file specified to upload")
             .expect("no file specified to upload")
     }
     }
+
+    /// Get the host to upload to.
+    pub fn host(&'a self) -> &'a str {
+        self.matches.value_of("host").unwrap()
+    }
 }
 }

+ 12 - 35
src/main.rs

@@ -8,12 +8,14 @@ extern crate reqwest;
 #[macro_use]
 #[macro_use]
 extern crate serde_derive;
 extern crate serde_derive;
 
 
+mod action;
 mod app;
 mod app;
-mod cmd;
 mod b64;
 mod b64;
+mod cmd;
 mod crypto;
 mod crypto;
 mod metadata;
 mod metadata;
 mod reader;
 mod reader;
+mod send;
 
 
 use std::fs::File;
 use std::fs::File;
 use std::io::BufReader;
 use std::io::BufReader;
@@ -25,6 +27,7 @@ use reqwest::header::Authorization;
 use reqwest::mime::APPLICATION_OCTET_STREAM;
 use reqwest::mime::APPLICATION_OCTET_STREAM;
 use reqwest::multipart::Part;
 use reqwest::multipart::Part;
 
 
+use action::upload::UploadResponse;
 use cmd::Handler;
 use cmd::Handler;
 use cmd::cmd_upload::CmdUpload;
 use cmd::cmd_upload::CmdUpload;
 use crypto::{derive_auth_key, derive_file_key, derive_meta_key};
 use crypto::{derive_auth_key, derive_file_key, derive_meta_key};
@@ -58,8 +61,9 @@ fn invoke_action(handler: &Handler) {
 
 
 /// The upload action.
 /// The upload action.
 fn action_upload(cmd_upload: &CmdUpload) {
 fn action_upload(cmd_upload: &CmdUpload) {
-    // Get the path
+    // Get the path and host
     let path = Path::new(cmd_upload.file());
     let path = Path::new(cmd_upload.file());
+    let host = cmd_upload.host();
 
 
     // Make sure the path is a file
     // Make sure the path is a file
     if !path.is_file() {
     if !path.is_file() {
@@ -129,7 +133,9 @@ fn action_upload(cmd_upload: &CmdUpload) {
         .part("data", part);
         .part("data", part);
 
 
     // Make the request
     // Make the request
-    let mut res = client.post("http://localhost:8080/api/upload")
+    // TODO: properly format an URL here
+    let url = format!("{}/api/upload", host);
+    let mut res = client.post(&url)
         .header(Authorization(format!("send-v1 {}", b64::encode(&auth_key))))
         .header(Authorization(format!("send-v1 {}", b64::encode(&auth_key))))
         .header(XFileMetadata::from(&metadata))
         .header(XFileMetadata::from(&metadata))
         .multipart(form)
         .multipart(form)
@@ -140,8 +146,9 @@ fn action_upload(cmd_upload: &CmdUpload) {
     let upload_res: UploadResponse = res.json().unwrap();
     let upload_res: UploadResponse = res.json().unwrap();
 
 
     // Print the response
     // Print the response
-    let url = upload_res.download_url(&secret);
-    println!("Response: {:#?}", upload_res);
+    let file = upload_res.into_file(host.to_owned(), secret.to_vec());
+    let url = file.download_url();
+    println!("File: {:#?}", file);
     println!("Secret key: {}", b64::encode(&secret));
     println!("Secret key: {}", b64::encode(&secret));
     println!("Download URL: {}", url);
     println!("Download URL: {}", url);
 
 
@@ -151,33 +158,3 @@ fn action_upload(cmd_upload: &CmdUpload) {
 
 
 // TODO: implement this some other way
 // TODO: implement this some other way
 unsafe impl Send for EncryptedFileReaderTagged {}
 unsafe impl Send for EncryptedFileReaderTagged {}
-
-/// The response from the server after a file has been uploaded.
-/// This response contains the file ID and owner key, to manage the file.
-///
-/// It also contains the download URL, although an additional secret is
-/// required.
-///
-/// The download URL can be generated using `download_url()` which will
-/// include the required secret in the URL.
-#[derive(Debug, Deserialize)]
-struct UploadResponse {
-    /// unkhe URL the file is reachable at.
-    /// This includes the file ID, but does not include the secret.
-    url: String,
-
-    /// The owner key, used to do further file modifications.
-    owner: String,
-
-    /// The file ID.
-    id: String,
-}
-
-impl UploadResponse {
-    /// Get the download URL, including the secret.
-    ///
-    /// The secret bytes must be passed to `secret`.
-    pub fn download_url(&self, secret: &[u8]) -> String {
-        format!("{}#{}", self.url, b64::encode(secret))
-    }
-}

+ 66 - 0
src/send/file.rs

@@ -0,0 +1,66 @@
+use super::super::b64;
+
+/// A struct representing an uploaded file on a Send host.
+///
+/// The struct contains the file ID, the file URL, the key that is required
+/// in combination with the file, and the owner key.
+#[derive(Debug)]
+pub struct File {
+    /// The ID of the file on that server.
+    id: String,
+
+    /// The host the file was uploaded to.
+    host: String,
+
+    // TODO: a date the file was created at
+
+    /// The file URL that was provided by the server.
+    url: String,
+
+    /// The secret key that is required to download the file.
+    secret: Vec<u8>,
+
+    /// The owner key, that can be used to manage the file on the server.
+    owner_key: String,
+}
+
+impl File {
+    /// Construct a new file.
+    pub fn new(
+        id: String,
+        host: String,
+        url: String,
+        secret: Vec<u8>,
+        owner_key: String,
+    ) -> Self {
+        File {
+            id,
+            host,
+            url,
+            secret,
+            owner_key,
+        }
+    }
+
+    /// Construct a new file, that was created at this exact time.
+    pub fn new_now(
+        id: String,
+        host: String,
+        url: String,
+        secret: Vec<u8>,
+        owner_key: String,
+    ) -> Self {
+        Self::new(
+            id,
+            host,
+            url,
+            secret,
+            owner_key,
+        )
+    }
+
+    /// Get the download URL of the file, with the secret key included.
+    pub fn download_url(&self) -> String {
+        format!("{}#{}", self.url, b64::encode(&self.secret))
+    }
+}

+ 1 - 0
src/send/mod.rs

@@ -0,0 +1 @@
+pub mod file;