Added authentication and more robust response logs
This commit is contained in:
parent
648de8c8e5
commit
6afdc06cc7
|
@ -22,15 +22,10 @@ macro_rules! methods {
|
||||||
|
|
||||||
let url = url.as_ref();
|
let url = url.as_ref();
|
||||||
debug!(url = url, method = stringify!($method), call_id = as_debug!(call_id); "making API request");
|
debug!(url = url, method = stringify!($method), call_id = as_debug!(call_id); "making API request");
|
||||||
let response = self.client
|
let response = self.authenticated(self.client.$method(url)).send().await?;
|
||||||
.$method(url)
|
|
||||||
.send()
|
|
||||||
.await?;
|
|
||||||
match response.error_for_status() {
|
match response.error_for_status() {
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
let response = response
|
let response = read_response(response).await?;
|
||||||
.json()
|
|
||||||
.await?;
|
|
||||||
debug!(response = as_serde!(response), url = url, method = stringify!($method), call_id = as_debug!(call_id); "received API response");
|
debug!(response = as_serde!(response), url = url, method = stringify!($method), call_id = as_debug!(call_id); "received API response");
|
||||||
Ok(response)
|
Ok(response)
|
||||||
}
|
}
|
||||||
|
@ -66,7 +61,7 @@ macro_rules! paged_routes {
|
||||||
let url = self.route(concat!("/api/v1/", $url));
|
let url = self.route(concat!("/api/v1/", $url));
|
||||||
let call_id = uuid::Uuid::new_v4();
|
let call_id = uuid::Uuid::new_v4();
|
||||||
debug!(url = url, method = stringify!($method), call_id = as_debug!(call_id); "making API request");
|
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() {
|
match response.error_for_status() {
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
|
@ -122,7 +117,7 @@ macro_rules! paged_routes {
|
||||||
|
|
||||||
debug!(url = url, method = "get", call_id = as_debug!(call_id); "making API request");
|
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() {
|
match response.error_for_status() {
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
|
@ -208,7 +203,8 @@ macro_rules! route {
|
||||||
let form_data = Form::new()
|
let form_data = Form::new()
|
||||||
$(
|
$(
|
||||||
.part(stringify!($param), {
|
.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) => {
|
Ok(mut file) => {
|
||||||
let mut data = if let Ok(metadata) = file.metadata() {
|
let mut data = if let Ok(metadata) = file.metadata() {
|
||||||
Vec::with_capacity(metadata.len().try_into()?)
|
Vec::with_capacity(metadata.len().try_into()?)
|
||||||
|
@ -219,7 +215,7 @@ macro_rules! route {
|
||||||
Part::bytes(data)
|
Part::bytes(data)
|
||||||
}
|
}
|
||||||
Err(err) => {
|
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());
|
return Err(err.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -234,8 +230,7 @@ macro_rules! route {
|
||||||
"making API request"
|
"making API request"
|
||||||
);
|
);
|
||||||
|
|
||||||
let response = self.client
|
let response = self.authenticated(self.client.post(url))
|
||||||
.post(url)
|
|
||||||
.multipart(form_data)
|
.multipart(form_data)
|
||||||
.send()
|
.send()
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -319,15 +314,15 @@ macro_rules! route {
|
||||||
stringify!($param): $param,
|
stringify!($param): $param,
|
||||||
)*
|
)*
|
||||||
});
|
});
|
||||||
|
let url = &self.route(concat!("/api/v1/", $url));
|
||||||
debug!(
|
debug!(
|
||||||
url = $url, method = stringify!($method),
|
url = url.as_str(), method = stringify!($method),
|
||||||
call_id = as_debug!(call_id),
|
call_id = as_debug!(call_id),
|
||||||
form_data = as_serde!(&form_data);
|
form_data = as_serde!(&form_data);
|
||||||
"making API request"
|
"making API request"
|
||||||
);
|
);
|
||||||
|
|
||||||
let response = self.client
|
let response = self.authenticated(self.client.$method(url))
|
||||||
.$method(&self.route(concat!("/api/v1/", $url)))
|
|
||||||
.json(&form_data)
|
.json(&form_data)
|
||||||
.send()
|
.send()
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -425,7 +420,7 @@ macro_rules! paged_routes_with_id {
|
||||||
let url = self.route(&format!(concat!("/api/v1/", $url), 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");
|
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() {
|
match response.error_for_status() {
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
Page::new(self.clone(), response, call_id).await
|
Page::new(self.clone(), response, call_id).await
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::{borrow::Cow, ops::Deref, sync::Arc};
|
use std::{borrow::Cow, ops::Deref, path::Path, sync::Arc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
entities::{
|
entities::{
|
||||||
|
@ -11,6 +11,7 @@ use crate::{
|
||||||
errors::{Error, Result},
|
errors::{Error, Result},
|
||||||
event_stream::event_stream,
|
event_stream::event_stream,
|
||||||
helpers::read_response::read_response,
|
helpers::read_response::read_response,
|
||||||
|
log_serde,
|
||||||
AddFilterRequest,
|
AddFilterRequest,
|
||||||
AddPushRequest,
|
AddPushRequest,
|
||||||
Data,
|
Data,
|
||||||
|
@ -22,7 +23,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
use futures::TryStream;
|
use futures::TryStream;
|
||||||
use log::{as_debug, as_serde, debug, error, info, trace};
|
use log::{as_debug, as_serde, debug, error, info, trace};
|
||||||
use reqwest::Client;
|
use reqwest::{Client, RequestBuilder};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
@ -91,7 +92,7 @@ impl Mastodon {
|
||||||
(get (q: &'a str, resolve: bool,)) search: "search" => SearchResult,
|
(get (q: &'a str, resolve: bool,)) search: "search" => SearchResult,
|
||||||
(get (local: bool,)) get_public_timeline: "timelines/public" => Vec<Status>,
|
(get (local: bool,)) get_public_timeline: "timelines/public" => Vec<Status>,
|
||||||
(post (uri: Cow<'static, str>,)) follows: "follows" => Account,
|
(post (uri: Cow<'static, str>,)) follows: "follows" => Account,
|
||||||
(post multipart (file: Cow<'static, str>,)) media: "media" => Attachment,
|
(post multipart (file: impl AsRef<Path>,)) media: "media" => Attachment,
|
||||||
(post) clear_notifications: "notifications/clear" => Empty,
|
(post) clear_notifications: "notifications/clear" => Empty,
|
||||||
(post (id: &str,)) dismiss_notification: "notifications/dismiss" => Empty,
|
(post (id: &str,)) dismiss_notification: "notifications/dismiss" => Empty,
|
||||||
(get) get_push_subscription: "push/subscription" => Subscription,
|
(get) get_push_subscription: "push/subscription" => Subscription,
|
||||||
|
@ -187,14 +188,18 @@ impl Mastodon {
|
||||||
|
|
||||||
/// Post a new status to the account.
|
/// Post a new status to the account.
|
||||||
pub async fn new_status(&self, status: NewStatus) -> Result<Status> {
|
pub async fn new_status(&self, status: NewStatus) -> Result<Status> {
|
||||||
Ok(self
|
let url = self.route("/api/v1/statuses");
|
||||||
.client
|
let response = self
|
||||||
.post(&self.route("/api/v1/statuses"))
|
.authenticated(self.client.post(&url))
|
||||||
.json(&status)
|
.json(&status)
|
||||||
.send()
|
.send()
|
||||||
.await?
|
.await?;
|
||||||
.json()
|
debug!(
|
||||||
.await?)
|
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
|
/// 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,
|
Ok(response) => Page::new(self.clone(), response, call_id).await,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!(err = as_debug!(err), url = url, method = stringify!($method), call_id = as_debug!(call_id); "error making API request");
|
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())
|
Err(err.into())
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -411,7 +418,9 @@ impl Mastodon {
|
||||||
url.set_scheme(new_scheme)
|
url.set_scheme(new_scheme)
|
||||||
.map_err(|_| Error::Other("Bad URL scheme!".to_string()))?;
|
.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")?;
|
let route = route.join("card")?;
|
||||||
self.get(route.as_str()).await
|
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 {
|
impl Deref for Mastodon {
|
||||||
type Target = Arc<MastodonClient>;
|
type Target = Arc<MastodonClient>;
|
||||||
|
|
Loading…
Reference in New Issue