diff --git a/src/macros.rs b/src/macros.rs index cf0e26a..ddcc555 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -22,15 +22,10 @@ macro_rules! methods { let url = url.as_ref(); debug!(url = url, method = stringify!($method), call_id = as_debug!(call_id); "making API request"); - let response = self.client - .$method(url) - .send() - .await?; + let response = self.authenticated(self.client.$method(url)).send().await?; match response.error_for_status() { Ok(response) => { - let response = response - .json() - .await?; + let response = read_response(response).await?; debug!(response = as_serde!(response), url = url, method = stringify!($method), call_id = as_debug!(call_id); "received API response"); Ok(response) } @@ -66,7 +61,7 @@ macro_rules! paged_routes { let url = self.route(concat!("/api/v1/", $url)); let call_id = uuid::Uuid::new_v4(); debug!(url = url, method = stringify!($method), call_id = as_debug!(call_id); "making API request"); - let response = self.client.$method(&url).send().await?; + let response = self.authenticated(self.client.$method(&url)).send().await?; match response.error_for_status() { Ok(response) => { @@ -122,7 +117,7 @@ macro_rules! paged_routes { debug!(url = url, method = "get", call_id = as_debug!(call_id); "making API request"); - let response = self.client.get(&url).send().await?; + let response = self.authenticated(self.client.get(&url)).send().await?; match response.error_for_status() { Ok(response) => { @@ -208,7 +203,8 @@ macro_rules! route { let form_data = Form::new() $( .part(stringify!($param), { - match std::fs::File::open($param.as_ref()) { + let path = $param.as_ref(); + match std::fs::File::open(path) { Ok(mut file) => { let mut data = if let Ok(metadata) = file.metadata() { Vec::with_capacity(metadata.len().try_into()?) @@ -219,7 +215,7 @@ macro_rules! route { Part::bytes(data) } Err(err) => { - error!(path = $param.as_ref(), error = as_debug!(err); "error reading file contents for multipart form"); + error!(path = as_debug!(path), error = as_debug!(err); "error reading file contents for multipart form"); return Err(err.into()); } } @@ -234,8 +230,7 @@ macro_rules! route { "making API request" ); - let response = self.client - .post(url) + let response = self.authenticated(self.client.post(url)) .multipart(form_data) .send() .await?; @@ -319,15 +314,15 @@ macro_rules! route { stringify!($param): $param, )* }); + let url = &self.route(concat!("/api/v1/", $url)); debug!( - url = $url, method = stringify!($method), + url = url.as_str(), method = stringify!($method), call_id = as_debug!(call_id), form_data = as_serde!(&form_data); "making API request" ); - let response = self.client - .$method(&self.route(concat!("/api/v1/", $url))) + let response = self.authenticated(self.client.$method(url)) .json(&form_data) .send() .await?; @@ -425,7 +420,7 @@ macro_rules! paged_routes_with_id { let url = self.route(&format!(concat!("/api/v1/", $url), id)); debug!(url = url, method = stringify!($method), call_id = as_debug!(call_id); "making API request"); - let response = self.client.$method(&url).send().await?; + let response = self.authenticated(self.client.$method(&url)).send().await?; match response.error_for_status() { Ok(response) => { Page::new(self.clone(), response, call_id).await diff --git a/src/mastodon.rs b/src/mastodon.rs index 4b7b55a..1b3ee0a 100644 --- a/src/mastodon.rs +++ b/src/mastodon.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, ops::Deref, sync::Arc}; +use std::{borrow::Cow, ops::Deref, path::Path, sync::Arc}; use crate::{ entities::{ @@ -11,6 +11,7 @@ use crate::{ errors::{Error, Result}, event_stream::event_stream, helpers::read_response::read_response, + log_serde, AddFilterRequest, AddPushRequest, Data, @@ -22,7 +23,7 @@ use crate::{ }; use futures::TryStream; use log::{as_debug, as_serde, debug, error, info, trace}; -use reqwest::Client; +use reqwest::{Client, RequestBuilder}; use url::Url; use uuid::Uuid; @@ -91,7 +92,7 @@ impl Mastodon { (get (q: &'a str, resolve: bool,)) search: "search" => SearchResult, (get (local: bool,)) get_public_timeline: "timelines/public" => Vec, (post (uri: Cow<'static, str>,)) follows: "follows" => Account, - (post multipart (file: Cow<'static, str>,)) media: "media" => Attachment, + (post multipart (file: impl AsRef,)) media: "media" => Attachment, (post) clear_notifications: "notifications/clear" => Empty, (post (id: &str,)) dismiss_notification: "notifications/dismiss" => Empty, (get) get_push_subscription: "push/subscription" => Subscription, @@ -187,14 +188,18 @@ impl Mastodon { /// Post a new status to the account. pub async fn new_status(&self, status: NewStatus) -> Result { - Ok(self - .client - .post(&self.route("/api/v1/statuses")) + let url = self.route("/api/v1/statuses"); + let response = self + .authenticated(self.client.post(&url)) .json(&status) .send() - .await? - .json() - .await?) + .await?; + debug!( + status = log_serde!(response Status), url = url, + headers = log_serde!(response Headers); + "received API response" + ); + Ok(read_response(response).await?) } /// Get timeline filtered by a hashtag(eg. `#coffee`) either locally or @@ -252,6 +257,8 @@ impl Mastodon { Ok(response) => Page::new(self.clone(), response, call_id).await, Err(err) => { error!(err = as_debug!(err), url = url, method = stringify!($method), call_id = as_debug!(call_id); "error making API request"); + // Cannot retrieve request body as it's been moved into the + // other match arm. Err(err.into()) }, } @@ -411,7 +418,9 @@ impl Mastodon { url.set_scheme(new_scheme) .map_err(|_| Error::Other("Bad URL scheme!".to_string()))?; - event_stream(url.to_string()) + /// Set the bearer authentication token + fn authenticated(&self, request: RequestBuilder) -> RequestBuilder { + request.bearer_auth(&self.data.token) } } @@ -460,6 +469,12 @@ impl MastodonUnauthenticated { let route = route.join("card")?; self.get(route.as_str()).await } + + /// Since this client needs no authentication, this returns the + /// `RequestBuilder` unmodified. + fn authenticated(&self, request: RequestBuilder) -> RequestBuilder { + request + } } impl Deref for Mastodon { type Target = Arc;