Extract response object, create uploaded file struct
This commit is contained in:
parent
ae83064b36
commit
c92ab109f6
6 changed files with 122 additions and 35 deletions
1
src/action/mod.rs
Normal file
1
src/action/mod.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub mod upload;
|
37
src/action/upload.rs
Normal file
37
src/action/upload.rs
Normal file
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
|
@ -46,4 +46,9 @@ impl<'a: 'b, 'b> CmdUpload<'a> {
|
|||
self.matches.value_of("FILE")
|
||||
.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()
|
||||
}
|
||||
}
|
||||
|
|
47
src/main.rs
47
src/main.rs
|
@ -8,12 +8,14 @@ extern crate reqwest;
|
|||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
mod action;
|
||||
mod app;
|
||||
mod cmd;
|
||||
mod b64;
|
||||
mod cmd;
|
||||
mod crypto;
|
||||
mod metadata;
|
||||
mod reader;
|
||||
mod send;
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
|
@ -25,6 +27,7 @@ use reqwest::header::Authorization;
|
|||
use reqwest::mime::APPLICATION_OCTET_STREAM;
|
||||
use reqwest::multipart::Part;
|
||||
|
||||
use action::upload::UploadResponse;
|
||||
use cmd::Handler;
|
||||
use cmd::cmd_upload::CmdUpload;
|
||||
use crypto::{derive_auth_key, derive_file_key, derive_meta_key};
|
||||
|
@ -58,8 +61,9 @@ fn invoke_action(handler: &Handler) {
|
|||
|
||||
/// The upload action.
|
||||
fn action_upload(cmd_upload: &CmdUpload) {
|
||||
// Get the path
|
||||
// Get the path and host
|
||||
let path = Path::new(cmd_upload.file());
|
||||
let host = cmd_upload.host();
|
||||
|
||||
// Make sure the path is a file
|
||||
if !path.is_file() {
|
||||
|
@ -129,7 +133,9 @@ fn action_upload(cmd_upload: &CmdUpload) {
|
|||
.part("data", part);
|
||||
|
||||
// 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(XFileMetadata::from(&metadata))
|
||||
.multipart(form)
|
||||
|
@ -140,8 +146,9 @@ fn action_upload(cmd_upload: &CmdUpload) {
|
|||
let upload_res: UploadResponse = res.json().unwrap();
|
||||
|
||||
// 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!("Download URL: {}", url);
|
||||
|
||||
|
@ -151,33 +158,3 @@ fn action_upload(cmd_upload: &CmdUpload) {
|
|||
|
||||
// TODO: implement this some other way
|
||||
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
src/send/file.rs
Normal file
66
src/send/file.rs
Normal file
|
@ -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
src/send/mod.rs
Normal file
1
src/send/mod.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub mod file;
|
Loading…
Reference in a new issue