From 51ecab41bbabcfd5d99ec8830729b1fe8f92b87b 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 01:20:41 +0000 Subject: [PATCH] [wip] impl `Client` for `ureq::Agent` --- src/sharry/api.rs | 8 ++++ src/sharry/client.rs | 98 ++++++++++++++++++++++++++++++++++++++++++++ src/sharry/mod.rs | 2 + 3 files changed, 108 insertions(+) create mode 100644 src/sharry/client.rs diff --git a/src/sharry/api.rs b/src/sharry/api.rs index 0898bf1..079dcda 100644 --- a/src/sharry/api.rs +++ b/src/sharry/api.rs @@ -1,5 +1,6 @@ use std::fmt; +use log::debug; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, Hash)] @@ -9,6 +10,13 @@ pub struct Uri { } impl Uri { + pub(super) fn get_endpoint(&self, endpoint: impl fmt::Display + fmt::Debug) -> String { + let uri = format!("{}/{}", self, endpoint); + debug!("endpoint uri: {uri:?}"); + + uri + } + pub fn with_protocol(protocol: impl Into, base_url: impl Into) -> Self { Self { protocol: protocol.into(), diff --git a/src/sharry/client.rs b/src/sharry/client.rs new file mode 100644 index 0000000..fa19cb6 --- /dev/null +++ b/src/sharry/client.rs @@ -0,0 +1,98 @@ +use std::{error::Error, io}; + +use log::debug; + +use super::api::{NewShareRequest, NewShareResponse, NotifyShareResponse, Uri}; + +pub trait Client { + fn sharry_share_create( + &self, + uri: &Uri, + alias_id: &str, + data: NewShareRequest, + ) -> Result; + + fn sharry_share_notify( + &self, + uri: &Uri, + alias_id: &str, + share_id: &str, + ) -> Result<(), ClientError>; + + // fn sharry_file_create(&self); + + // fn sharry_file_patch(&self); +} + +#[derive(Debug, thiserror::Error)] +pub enum ClientError { + #[error("file I/O error: {0}")] + FileIO(#[from] io::Error), + + #[error("network request failed: {0}")] + Request(String), + + #[error("response parsing failed: {0}")] + ResponseParsing(String), + // + // #[error("unexpected response status: {actual} (expected {expected})")] + // ResponseStatus { actual: u64, expected: u64 }, + // + #[error("unexpected response content: {0}")] + ResponseContent(String), + // + // #[error("could not parse offset header")] + // ResponseOffset, +} + +impl Client for ureq::Agent { + fn sharry_share_create( + &self, + uri: &Uri, + alias_id: &str, + data: NewShareRequest, + ) -> Result { + let res = { + let endpoint = uri.get_endpoint("alias/upload/new"); + + self.post(endpoint) + .header("Sharry-Alias", alias_id) + .send_json(data) + .map_err(|e| ClientError::Request(e.to_string()))? + .body_mut() + .read_json::() + .map_err(|e| ClientError::ResponseParsing(e.to_string()))? + }; + + debug!("response: {res:?}"); + + if res.success && (res.message == "Share created.") { + Ok(res.id) + } else { + Err(ClientError::ResponseContent(format!("{res:?}"))) + } + } + + fn sharry_share_notify( + &self, + uri: &Uri, + alias_id: &str, + share_id: &str, + ) -> Result<(), ClientError> { + let res = { + let endpoint = uri.get_endpoint(format!("alias/mail/notify/{}", share_id)); + + self.post(endpoint) + .header("Sharry-Alias", alias_id) + .send_empty() + .map_err(|e| ClientError::Request(e.to_string()))? + .body_mut() + .read_json::() + .map_err(|e| ClientError::ResponseParsing(e.to_string()))? + }; + + debug!("response: {res:?}"); + + Ok(()) + } +} diff --git a/src/sharry/mod.rs b/src/sharry/mod.rs index 33192d5..05ce16e 100644 --- a/src/sharry/mod.rs +++ b/src/sharry/mod.rs @@ -2,10 +2,12 @@ mod alias; mod api; +mod client; mod file; mod share; pub use alias::Alias; pub use api::{NewShareRequest, Uri}; +// pub use client::SharryClient; pub use file::{ChunkState, FileChecked, FileUploading, SharryFile, UploadError}; pub use share::Share;