From 90cecd015e7da207ce664ed314563213a2682581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn-Michael=20Miehe?= <40151420+ldericher@users.noreply.github.com> Date: Sun, 8 Jun 2025 17:13:01 +0000 Subject: [PATCH] [wip] impl `Client` for `ureq::Agent` --- src/sharry/client.rs | 59 ++++++++++++++++++++++++++++++++---- src/sharry/file/checked.rs | 4 +++ src/sharry/file/mod.rs | 7 ++++- src/sharry/file/uploading.rs | 6 +++- 4 files changed, 68 insertions(+), 8 deletions(-) diff --git a/src/sharry/client.rs b/src/sharry/client.rs index fa19cb6..85951ee 100644 --- a/src/sharry/client.rs +++ b/src/sharry/client.rs @@ -2,7 +2,10 @@ use std::{error::Error, io}; use log::debug; -use super::api::{NewShareRequest, NewShareResponse, NotifyShareResponse, Uri}; +use super::{ + api::{NewShareRequest, NewShareResponse, NotifyShareResponse, Uri}, + file::{FileChecked, FileUploading, SharryFile}, +}; pub trait Client { fn sharry_share_create( @@ -19,7 +22,13 @@ pub trait Client { share_id: &str, ) -> Result<(), ClientError>; - // fn sharry_file_create(&self); + fn sharry_file_create( + &self, + uri: &Uri, + alias_id: &str, + share_id: &str, + file: FileChecked, + ) -> Result; // fn sharry_file_patch(&self); } @@ -34,10 +43,10 @@ pub enum ClientError { #[error("response parsing failed: {0}")] ResponseParsing(String), - // - // #[error("unexpected response status: {actual} (expected {expected})")] - // ResponseStatus { actual: u64, expected: u64 }, - // + + #[error("unexpected response status: {actual} (expected {expected})")] + ResponseStatus { actual: u16, expected: u16 }, + #[error("unexpected response content: {0}")] ResponseContent(String), // @@ -95,4 +104,42 @@ impl Client for ureq::Agent { Ok(()) } + + fn sharry_file_create( + &self, + uri: &Uri, + alias_id: &str, + share_id: &str, + file: FileChecked, + ) -> Result { + let size = file.get_size(); + + let res = { + let endpoint = uri.get_endpoint(format!("alias/upload/{}/files/tus", share_id)); + + self.post(endpoint) + .header("Sharry-Alias", alias_id) + .header("Sharry-File-Name", file.get_name()) + .header("Upload-Length", size) + .send_empty() + .map_err(|e| ClientError::Request(e.to_string()))? + }; + + if res.status() != ureq::http::StatusCode::CREATED { + return Err(ClientError::ResponseStatus { + actual: res.status().as_u16(), + expected: ureq::http::StatusCode::CREATED.as_u16(), + }); + } + + let location = (res.headers().get("Location")) + .ok_or_else(|| ClientError::ResponseParsing("Location header not found".to_owned()))? + .to_str() + .map_err(|_| ClientError::ResponseParsing("Location header invalid".to_owned()))? + .to_string(); + + debug!("patch uri: {location}"); + + Ok(FileUploading::new(file.into_path(), size, location)) + } } diff --git a/src/sharry/file/checked.rs b/src/sharry/file/checked.rs index 05a9180..e31adc9 100644 --- a/src/sharry/file/checked.rs +++ b/src/sharry/file/checked.rs @@ -66,6 +66,10 @@ impl FileChecked { } impl<'t> SharryFile<'t> for FileChecked { + fn into_path(self) -> PathBuf { + self.path + } + /// get a reference to the file's name /// /// Uses `SharryFile::extract_file_name`, which may **panic**! diff --git a/src/sharry/file/mod.rs b/src/sharry/file/mod.rs index d100954..c3e4502 100644 --- a/src/sharry/file/mod.rs +++ b/src/sharry/file/mod.rs @@ -1,7 +1,10 @@ mod checked; mod uploading; -use std::{ffi::OsStr, path::Path}; +use std::{ + ffi::OsStr, + path::{Path, PathBuf}, +}; pub use checked::FileChecked; pub use uploading::{ChunkState, FileUploading, UploadError}; @@ -20,6 +23,8 @@ pub trait SharryFile<'t> { .expect("bad file name") } + fn into_path(self) -> PathBuf; + fn get_name(&'t self) -> &'t str; fn get_size(&self) -> u64; diff --git a/src/sharry/file/uploading.rs b/src/sharry/file/uploading.rs index 3109a0a..15fa3d9 100644 --- a/src/sharry/file/uploading.rs +++ b/src/sharry/file/uploading.rs @@ -58,7 +58,7 @@ impl fmt::Display for FileUploading { } impl FileUploading { - pub(super) fn new(path: PathBuf, size: u64, uri: String) -> Self { + pub fn new(path: PathBuf, size: u64, uri: String) -> Self { Self { path, size, @@ -135,6 +135,10 @@ impl FileUploading { } impl<'t> SharryFile<'t> for FileUploading { + fn into_path(self) -> PathBuf { + self.path + } + fn get_name(&'t self) -> &'t str { ::extract_file_name(&self.path) }