Extract response object, create uploaded file struct

This commit is contained in:
timvisee 2018-03-08 20:25:15 +01:00
parent ae83064b36
commit c92ab109f6
No known key found for this signature in database
GPG key ID: 109CBA0BF74036C2
6 changed files with 122 additions and 35 deletions

1
src/action/mod.rs Normal file
View file

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

37
src/action/upload.rs Normal file
View 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,
)
}
}

View file

@ -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()
}
}

View file

@ -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
View 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
View file

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