From 098a4299f0b7e9857c515858f43a9e2f47649889 Mon Sep 17 00:00:00 2001 From: cetra3 Date: Mon, 20 Nov 2023 21:12:47 +1030 Subject: [PATCH] Remove `anyhow` from trait definitions (#82) --- Cargo.toml | 2 +- examples/local_federation/instance.rs | 6 ++- examples/local_federation/objects/person.rs | 2 +- src/activity_sending.rs | 57 +++++++++------------ src/actix_web/inbox.rs | 17 ++---- src/actix_web/mod.rs | 2 +- src/axum/inbox.rs | 9 ++-- src/config.rs | 40 ++++++--------- src/error.rs | 46 +++++++++++++---- src/fetch/mod.rs | 6 +-- src/fetch/object_id.rs | 9 ++-- src/fetch/webfinger.rs | 33 ++++++------ src/http_signatures.rs | 29 +++++------ src/protocol/verification.rs | 5 +- src/reqwest_shim.rs | 9 ++-- src/traits.rs | 2 +- 16 files changed, 137 insertions(+), 137 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ad11179..d1f8bb9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,6 @@ serde = { version = "1.0.189", features = ["derive"] } async-trait = "0.1.74" url = { version = "2.4.1", features = ["serde"] } serde_json = { version = "1.0.107", features = ["preserve_order"] } -anyhow = "1.0.75" reqwest = { version = "0.11.22", features = ["json", "stream"] } reqwest-middleware = "0.2.3" tracing = "0.1.40" @@ -65,6 +64,7 @@ actix-web = ["dep:actix-web"] axum = ["dep:axum", "dep:tower", "dep:hyper"] [dev-dependencies] +anyhow = "1.0.75" rand = "0.8.5" env_logger = "0.10.0" tower-http = { version = "0.4.4", features = ["map-request-body", "util"] } diff --git a/examples/local_federation/instance.rs b/examples/local_federation/instance.rs index 5a9794c..f377f31 100644 --- a/examples/local_federation/instance.rs +++ b/examples/local_federation/instance.rs @@ -49,9 +49,11 @@ struct MyUrlVerifier(); #[async_trait] impl UrlVerifier for MyUrlVerifier { - async fn verify(&self, url: &Url) -> Result<(), anyhow::Error> { + async fn verify(&self, url: &Url) -> Result<(), activitypub_federation::error::Error> { if url.domain() == Some("malicious.com") { - Err(anyhow!("malicious domain")) + Err(activitypub_federation::error::Error::Other( + "malicious domain".into(), + )) } else { Ok(()) } diff --git a/examples/local_federation/objects/person.rs b/examples/local_federation/objects/person.rs index 5961205..2c47fcd 100644 --- a/examples/local_federation/objects/person.rs +++ b/examples/local_federation/objects/person.rs @@ -107,7 +107,7 @@ impl DbUser { activity: Activity, recipients: Vec, data: &Data, - ) -> Result<(), ::Error> + ) -> Result<(), Error> where Activity: ActivityHandler + Serialize + Debug + Send + Sync, ::Error: From + From, diff --git a/src/activity_sending.rs b/src/activity_sending.rs index 30713b4..01d78fb 100644 --- a/src/activity_sending.rs +++ b/src/activity_sending.rs @@ -10,7 +10,6 @@ use crate::{ traits::{ActivityHandler, Actor}, FEDERATION_CONTENT_TYPE, }; -use anyhow::{anyhow, Context}; use bytes::Bytes; use futures::StreamExt; @@ -57,17 +56,16 @@ impl SendActivityTask<'_> { actor: &ActorType, inboxes: Vec, data: &Data, - ) -> Result>, ::Error> + ) -> Result>, Error> where Activity: ActivityHandler + Serialize, - ::Error: From + From, Datatype: Clone, ActorType: Actor, { let config = &data.config; let actor_id = activity.actor(); let activity_id = activity.id(); - let activity_serialized: Bytes = serde_json::to_vec(&activity)?.into(); + let activity_serialized: Bytes = serde_json::to_vec(&activity).map_err(Error::Json)?.into(); let private_key = get_pkey_cached(data, actor).await?; Ok(futures::stream::iter( @@ -95,10 +93,7 @@ impl SendActivityTask<'_> { } /// convert a sendactivitydata to a request, signing and sending it - pub async fn sign_and_send( - &self, - data: &Data, - ) -> Result<(), anyhow::Error> { + pub async fn sign_and_send(&self, data: &Data) -> Result<(), Error> { let req = self .sign(&data.config.client, data.config.request_timeout) .await?; @@ -108,7 +103,7 @@ impl SendActivityTask<'_> { &self, client: &ClientWithMiddleware, timeout: Duration, - ) -> Result { + ) -> Result { let task = self; let request_builder = client .post(task.inbox.to_string()) @@ -121,36 +116,31 @@ impl SendActivityTask<'_> { task.private_key.clone(), task.http_signature_compat, ) - .await - .context("signing request")?; + .await?; Ok(request) } - async fn send( - &self, - client: &ClientWithMiddleware, - request: Request, - ) -> Result<(), anyhow::Error> { - let response = client.execute(request).await; + async fn send(&self, client: &ClientWithMiddleware, request: Request) -> Result<(), Error> { + let response = client.execute(request).await?; match response { - Ok(o) if o.status().is_success() => { + o if o.status().is_success() => { debug!("Activity {self} delivered successfully"); Ok(()) } - Ok(o) if o.status().is_client_error() => { - let text = o.text_limited().await.map_err(Error::other)?; + o if o.status().is_client_error() => { + let text = o.text_limited().await?; debug!("Activity {self} was rejected, aborting: {text}"); Ok(()) } - Ok(o) => { + o => { let status = o.status(); - let text = o.text_limited().await.map_err(Error::other)?; - Err(anyhow!( + let text = o.text_limited().await?; + + Err(Error::Other(format!( "Activity {self} failure with status {status}: {text}", - )) + ))) } - Err(e) => Err(anyhow!("Activity {self} connection failure: {e}")), } } } @@ -158,7 +148,7 @@ impl SendActivityTask<'_> { async fn get_pkey_cached( data: &Data, actor: &ActorType, -) -> Result, anyhow::Error> +) -> Result, Error> where ActorType: Actor, { @@ -168,20 +158,23 @@ where .actor_pkey_cache .try_get_with_by_ref(&actor_id, async { let private_key_pem = actor.private_key_pem().ok_or_else(|| { - anyhow!("Actor {actor_id} does not contain a private key for signing") + Error::Other(format!( + "Actor {actor_id} does not contain a private key for signing" + )) })?; // This is a mostly expensive blocking call, we don't want to tie up other tasks while this is happening let pkey = tokio::task::spawn_blocking(move || { - PKey::private_key_from_pem(private_key_pem.as_bytes()) - .map_err(|err| anyhow!("Could not create private key from PEM data:{err}")) + PKey::private_key_from_pem(private_key_pem.as_bytes()).map_err(|err| { + Error::Other(format!("Could not create private key from PEM data:{err}")) + }) }) .await - .map_err(|err| anyhow!("Error joining: {err}"))??; - std::result::Result::, anyhow::Error>::Ok(pkey) + .map_err(|err| Error::Other(format!("Error joining: {err}")))??; + std::result::Result::, Error>::Ok(pkey) }) .await - .map_err(|e| anyhow!("cloned error: {e}")) + .map_err(|e| Error::Other(format!("cloned error: {e}"))) } pub(crate) fn generate_request_headers(inbox_url: &Url) -> HeaderMap { diff --git a/src/actix_web/inbox.rs b/src/actix_web/inbox.rs index ba5a20b..e7e19e8 100644 --- a/src/actix_web/inbox.rs +++ b/src/actix_web/inbox.rs @@ -8,7 +8,6 @@ use crate::{ traits::{ActivityHandler, Actor, Object}, }; use actix_web::{web::Bytes, HttpRequest, HttpResponse}; -use anyhow::Context; use serde::de::DeserializeOwned; use tracing::debug; @@ -24,17 +23,13 @@ where Activity: ActivityHandler + DeserializeOwned + Send + 'static, ActorT: Object + Actor + Send + 'static, for<'de2> ::Kind: serde::Deserialize<'de2>, - ::Error: From - + From - + From<::Error> - + From, - ::Error: From + From, + ::Error: From + From<::Error>, + ::Error: From, Datatype: Clone, { verify_body_hash(request.headers().get("Digest"), &body)?; - let activity: Activity = serde_json::from_slice(&body) - .with_context(|| format!("deserializing body: {}", String::from_utf8_lossy(&body)))?; + let activity: Activity = serde_json::from_slice(&body).map_err(Error::Json)?; data.config.verify_url_and_domain(&activity).await?; let actor = ObjectId::::from(activity.actor().clone()) .dereference(data) @@ -91,8 +86,7 @@ mod test { .err() .unwrap(); - let e = err.root_cause().downcast_ref::().unwrap(); - assert_eq!(e, &Error::ActivityBodyDigestInvalid) + assert_eq!(&err, &Error::ActivityBodyDigestInvalid) } #[tokio::test] @@ -108,8 +102,7 @@ mod test { .err() .unwrap(); - let e = err.root_cause().downcast_ref::().unwrap(); - assert_eq!(e, &Error::ActivitySignatureInvalid) + assert_eq!(&err, &Error::ActivitySignatureInvalid) } async fn setup_receive_test() -> (Bytes, TestRequest, FederationConfig) { diff --git a/src/actix_web/mod.rs b/src/actix_web/mod.rs index d7d137a..d3323ad 100644 --- a/src/actix_web/mod.rs +++ b/src/actix_web/mod.rs @@ -22,7 +22,7 @@ pub async fn signing_actor( ) -> Result::Error> where A: Object + Actor, - ::Error: From + From, + ::Error: From, for<'de2> ::Kind: Deserialize<'de2>, { verify_body_hash(request.headers().get("Digest"), &body.unwrap_or_default())?; diff --git a/src/axum/inbox.rs b/src/axum/inbox.rs index 6c20e25..c110bb6 100644 --- a/src/axum/inbox.rs +++ b/src/axum/inbox.rs @@ -29,16 +29,13 @@ where Activity: ActivityHandler + DeserializeOwned + Send + 'static, ActorT: Object + Actor + Send + 'static, for<'de2> ::Kind: serde::Deserialize<'de2>, - ::Error: From - + From - + From<::Error> - + From, - ::Error: From + From, + ::Error: From + From<::Error>, + ::Error: From, Datatype: Clone, { verify_body_hash(activity_data.headers.get("Digest"), &activity_data.body)?; - let activity: Activity = serde_json::from_slice(&activity_data.body)?; + let activity: Activity = serde_json::from_slice(&activity_data.body).map_err(Error::Json)?; data.config.verify_url_and_domain(&activity).await?; let actor = ObjectId::::from(activity.actor().clone()) .dereference(data) diff --git a/src/config.rs b/src/config.rs index 7f52aa7..7573234 100644 --- a/src/config.rs +++ b/src/config.rs @@ -19,7 +19,6 @@ use crate::{ protocol::verification::verify_domains_match, traits::{ActivityHandler, Actor}, }; -use anyhow::anyhow; use async_trait::async_trait; use derive_builder::Builder; use dyn_clone::{clone_trait_object, DynClone}; @@ -104,9 +103,9 @@ impl FederationConfig { verify_domains_match(activity.id(), activity.actor())?; self.verify_url_valid(activity.id()).await?; if self.is_local_url(activity.id()) { - return Err(Error::UrlVerificationError(anyhow!( - "Activity was sent from local instance" - ))); + return Err(Error::UrlVerificationError( + "Activity was sent from local instance", + )); } Ok(()) @@ -129,12 +128,12 @@ impl FederationConfig { "https" => {} "http" => { if !self.allow_http_urls { - return Err(Error::UrlVerificationError(anyhow!( - "Http urls are only allowed in debug mode" - ))); + return Err(Error::UrlVerificationError( + "Http urls are only allowed in debug mode", + )); } } - _ => return Err(Error::UrlVerificationError(anyhow!("Invalid url scheme"))), + _ => return Err(Error::UrlVerificationError("Invalid url scheme")), }; // Urls which use our local domain are not a security risk, no further verification needed @@ -143,21 +142,16 @@ impl FederationConfig { } if url.domain().is_none() { - return Err(Error::UrlVerificationError(anyhow!( - "Url must have a domain" - ))); + return Err(Error::UrlVerificationError("Url must have a domain")); } if url.domain() == Some("localhost") && !self.debug { - return Err(Error::UrlVerificationError(anyhow!( - "Localhost is only allowed in debug mode" - ))); + return Err(Error::UrlVerificationError( + "Localhost is only allowed in debug mode", + )); } - self.url_verifier - .verify(url) - .await - .map_err(Error::UrlVerificationError)?; + self.url_verifier.verify(url).await?; Ok(()) } @@ -227,7 +221,7 @@ impl Deref for FederationConfig { /// # use async_trait::async_trait; /// # use url::Url; /// # use activitypub_federation::config::UrlVerifier; -/// # use anyhow::anyhow; +/// # use activitypub_federation::error::Error; /// # #[derive(Clone)] /// # struct DatabaseConnection(); /// # async fn get_blocklist(_: &DatabaseConnection) -> Vec { @@ -240,11 +234,11 @@ impl Deref for FederationConfig { /// /// #[async_trait] /// impl UrlVerifier for Verifier { -/// async fn verify(&self, url: &Url) -> Result<(), anyhow::Error> { +/// async fn verify(&self, url: &Url) -> Result<(), Error> { /// let blocklist = get_blocklist(&self.db_connection).await; /// let domain = url.domain().unwrap().to_string(); /// if blocklist.contains(&domain) { -/// Err(anyhow!("Domain is blocked")) +/// Err(Error::Other("Domain is blocked".into())) /// } else { /// Ok(()) /// } @@ -254,7 +248,7 @@ impl Deref for FederationConfig { #[async_trait] pub trait UrlVerifier: DynClone + Send { /// Should return Ok iff the given url is valid for processing. - async fn verify(&self, url: &Url) -> Result<(), anyhow::Error>; + async fn verify(&self, url: &Url) -> Result<(), Error>; } /// Default URL verifier which does nothing. @@ -263,7 +257,7 @@ struct DefaultUrlVerifier(); #[async_trait] impl UrlVerifier for DefaultUrlVerifier { - async fn verify(&self, _url: &Url) -> Result<(), anyhow::Error> { + async fn verify(&self, _url: &Url) -> Result<(), Error> { Ok(()) } } diff --git a/src/error.rs b/src/error.rs index 91de96a..c66e16c 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,5 +1,11 @@ //! Error messages returned by this library +use std::string::FromUtf8Error; + +use http_signature_normalization_reqwest::SignError; +use openssl::error::ErrorStack; +use url::Url; + /// Error messages returned by this library #[derive(thiserror::Error, Debug)] pub enum Error { @@ -13,11 +19,11 @@ pub enum Error { #[error("Response body limit was reached during fetch")] ResponseBodyLimit, /// Object to be fetched was deleted - #[error("Object to be fetched was deleted")] - ObjectDeleted, + #[error("Fetched remote object {0} which was deleted")] + ObjectDeleted(Url), /// url verification error #[error("URL failed verification: {0}")] - UrlVerificationError(anyhow::Error), + UrlVerificationError(&'static str), /// Incoming activity has invalid digest for body #[error("Incoming activity has invalid digest for body")] ActivityBodyDigestInvalid, @@ -27,17 +33,35 @@ pub enum Error { /// Failed to resolve actor via webfinger #[error("Failed to resolve actor via webfinger")] WebfingerResolveFailed, - /// other error + /// Failed to resolve actor via webfinger + #[error("Webfinger regex failed to match")] + WebfingerRegexFailed, + /// JSON Error #[error(transparent)] - Other(#[from] anyhow::Error), + Json(#[from] serde_json::Error), + /// Reqwest Middleware Error + #[error(transparent)] + ReqwestMiddleware(#[from] reqwest_middleware::Error), + /// Reqwest Error + #[error(transparent)] + Reqwest(#[from] reqwest::Error), + /// UTF-8 error + #[error(transparent)] + Utf8(#[from] FromUtf8Error), + /// Url Parse + #[error(transparent)] + UrlParse(#[from] url::ParseError), + /// Signing errors + #[error(transparent)] + SignError(#[from] SignError), + /// Other generic errors + #[error("{0}")] + Other(String), } -impl Error { - pub(crate) fn other(error: T) -> Self - where - T: Into, - { - Error::Other(error.into()) +impl From for Error { + fn from(value: ErrorStack) -> Self { + Error::Other(value.to_string()) } } diff --git a/src/fetch/mod.rs b/src/fetch/mod.rs index bf1bfd5..4a0d502 100644 --- a/src/fetch/mod.rs +++ b/src/fetch/mod.rs @@ -83,13 +83,13 @@ async fn fetch_object_http_with_accept( data.config.http_signature_compat, ) .await?; - config.client.execute(req).await.map_err(Error::other)? + config.client.execute(req).await? } else { - req.send().await.map_err(Error::other)? + req.send().await? }; if res.status() == StatusCode::GONE { - return Err(Error::ObjectDeleted); + return Err(Error::ObjectDeleted(url.clone())); } let url = res.url().clone(); diff --git a/src/fetch/object_id.rs b/src/fetch/object_id.rs index 8c0e5aa..921951c 100644 --- a/src/fetch/object_id.rs +++ b/src/fetch/object_id.rs @@ -1,5 +1,4 @@ use crate::{config::Data, error::Error, fetch::fetch_object_http, traits::Object}; -use anyhow::anyhow; use chrono::{DateTime, Duration as ChronoDuration, Utc}; use serde::{Deserialize, Serialize}; use std::{ @@ -90,7 +89,7 @@ where data: &Data<::DataType>, ) -> Result::Error> where - ::Error: From + From, + ::Error: From, { let db_object = self.dereference_from_db(data).await?; // if its a local object, only fetch it from the database and not over http @@ -145,15 +144,15 @@ where db_object: Option, ) -> Result::Error> where - ::Error: From + From, + ::Error: From, { let res = fetch_object_http(&self.0, data).await; - if let Err(Error::ObjectDeleted) = &res { + if let Err(Error::ObjectDeleted(url)) = res { if let Some(db_object) = db_object { db_object.delete(data).await?; } - return Err(anyhow!("Fetched remote object {} which was deleted", self).into()); + return Err(Error::ObjectDeleted(url).into()); } let res = res?; diff --git a/src/fetch/webfinger.rs b/src/fetch/webfinger.rs index a8ddb15..a345fd4 100644 --- a/src/fetch/webfinger.rs +++ b/src/fetch/webfinger.rs @@ -5,7 +5,6 @@ use crate::{ traits::{Actor, Object}, FEDERATION_CONTENT_TYPE, }; -use anyhow::anyhow; use itertools::Itertools; use regex::Regex; use serde::{Deserialize, Serialize}; @@ -24,8 +23,7 @@ pub async fn webfinger_resolve_actor( where Kind: Object + Actor + Send + 'static + Object, for<'de2> ::Kind: serde::Deserialize<'de2>, - ::Error: - From + From + From + Send + Sync, + ::Error: From + Send + Sync, { let (_, domain) = identifier .splitn(2, '@') @@ -36,10 +34,13 @@ where format!("{protocol}://{domain}/.well-known/webfinger?resource=acct:{identifier}"); debug!("Fetching webfinger url: {}", &fetch_url); - let res: Webfinger = - fetch_object_http_with_accept(&Url::parse(&fetch_url)?, data, "application/jrd+json") - .await? - .object; + let res: Webfinger = fetch_object_http_with_accept( + &Url::parse(&fetch_url).map_err(Error::UrlParse)?, + data, + "application/jrd+json", + ) + .await? + .object; debug_assert_eq!(res.subject, format!("acct:{identifier}")); let links: Vec = res @@ -94,14 +95,16 @@ where { // Regex to extract usernames from webfinger query. Supports different alphabets using `\p{L}`. // TODO: would be nice if we could implement this without regex and remove the dependency - let regex = - Regex::new(&format!(r"^acct:([\p{{L}}0-9_]+)@{}$", data.domain())).map_err(Error::other)?; - Ok(regex - .captures(query) - .and_then(|c| c.get(1)) - .ok_or_else(|| Error::other(anyhow!("Webfinger regex failed to match")))? - .as_str() - .to_string()) + let result = Regex::new(&format!(r"^acct:([\p{{L}}0-9_]+)@{}$", data.domain())) + .map_err(|_| Error::WebfingerRegexFailed) + .and_then(|regex| { + regex + .captures(query) + .and_then(|c| c.get(1)) + .ok_or_else(|| Error::WebfingerRegexFailed) + })?; + + return Ok(result.as_str().to_string()); } /// Builds a basic webfinger response for the actor. diff --git a/src/http_signatures.rs b/src/http_signatures.rs index 96ce936..4b0e9ee 100644 --- a/src/http_signatures.rs +++ b/src/http_signatures.rs @@ -12,7 +12,6 @@ use crate::{ protocol::public_key::main_key_id, traits::{Actor, Object}, }; -use anyhow::Context; use base64::{engine::general_purpose::STANDARD as Base64, Engine}; use bytes::Bytes; use http::{header::HeaderName, uri::PathAndQuery, HeaderValue, Method, Uri}; @@ -83,7 +82,7 @@ pub(crate) async fn sign_request( activity: Bytes, private_key: PKey, http_signature_compat: bool, -) -> Result { +) -> Result { static CONFIG: Lazy = Lazy::new(|| Config::new().set_expiration(EXPIRES_AFTER)); static CONFIG_COMPAT: Lazy = Lazy::new(|| { Config::new() @@ -103,14 +102,10 @@ pub(crate) async fn sign_request( Sha256::new(), activity, move |signing_string| { - let mut signer = Signer::new(MessageDigest::sha256(), &private_key) - .context("instantiating signer")?; - signer - .update(signing_string.as_bytes()) - .context("updating signer")?; + let mut signer = Signer::new(MessageDigest::sha256(), &private_key)?; + signer.update(signing_string.as_bytes())?; - Ok(Base64.encode(signer.sign_to_vec().context("sign to vec")?)) - as Result<_, anyhow::Error> + Ok(Base64.encode(signer.sign_to_vec()?)) as Result<_, Error> }, ) .await @@ -152,7 +147,7 @@ pub(crate) async fn signing_actor<'a, A, H>( ) -> Result::Error> where A: Object + Actor, - ::Error: From + From, + ::Error: From, for<'de2> ::Kind: Deserialize<'de2>, H: IntoIterator, { @@ -197,8 +192,8 @@ fn verify_signature_inner( let verified = CONFIG .begin_verify(method.as_str(), path_and_query, header_map) - .map_err(Error::other)? - .verify(|signature, signing_string| -> anyhow::Result { + .map_err(|val| Error::Other(val.to_string()))? + .verify(|signature, signing_string| -> Result { debug!( "Verifying with key {}, message {}", &public_key, &signing_string @@ -206,9 +201,13 @@ fn verify_signature_inner( let public_key = PKey::public_key_from_pem(public_key.as_bytes())?; let mut verifier = Verifier::new(MessageDigest::sha256(), &public_key)?; verifier.update(signing_string.as_bytes())?; - Ok(verifier.verify(&Base64.decode(signature)?)?) - }) - .map_err(Error::other)?; + + let base64_decoded = Base64 + .decode(signature) + .map_err(|err| Error::Other(err.to_string()))?; + + Ok(verifier.verify(&base64_decoded)?) + })?; if verified { debug!("verified signature for {}", uri); diff --git a/src/protocol/verification.rs b/src/protocol/verification.rs index 3383bd9..18595b9 100644 --- a/src/protocol/verification.rs +++ b/src/protocol/verification.rs @@ -1,7 +1,6 @@ //! Verify that received data is valid use crate::error::Error; -use anyhow::anyhow; use url::Url; /// Check that both urls have the same domain. If not, return UrlVerificationError. @@ -16,7 +15,7 @@ use url::Url; /// ``` pub fn verify_domains_match(a: &Url, b: &Url) -> Result<(), Error> { if a.domain() != b.domain() { - return Err(Error::UrlVerificationError(anyhow!("Domains do not match"))); + return Err(Error::UrlVerificationError("Domains do not match")); } Ok(()) } @@ -33,7 +32,7 @@ pub fn verify_domains_match(a: &Url, b: &Url) -> Result<(), Error> { /// ``` pub fn verify_urls_match(a: &Url, b: &Url) -> Result<(), Error> { if a != b { - return Err(Error::UrlVerificationError(anyhow!("Urls do not match"))); + return Err(Error::UrlVerificationError("Urls do not match")); } Ok(()) } diff --git a/src/reqwest_shim.rs b/src/reqwest_shim.rs index 81c571b..9db846e 100644 --- a/src/reqwest_shim.rs +++ b/src/reqwest_shim.rs @@ -30,10 +30,7 @@ impl Future for BytesFuture { fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { loop { let this = self.as_mut().project(); - if let Some(chunk) = ready!(this.stream.poll_next(cx)) - .transpose() - .map_err(Error::other)? - { + if let Some(chunk) = ready!(this.stream.poll_next(cx)).transpose()? { this.aggregator.put(chunk); if this.aggregator.len() > *this.limit { return Poll::Ready(Err(Error::ResponseBodyLimit)); @@ -66,7 +63,7 @@ where fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); let bytes = ready!(this.future.poll(cx))?; - Poll::Ready(serde_json::from_slice(&bytes).map_err(Error::other)) + Poll::Ready(serde_json::from_slice(&bytes).map_err(Error::Json)) } } @@ -83,7 +80,7 @@ impl Future for TextFuture { fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let this = self.project(); let bytes = ready!(this.future.poll(cx))?; - Poll::Ready(String::from_utf8(bytes.to_vec()).map_err(Error::other)) + Poll::Ready(String::from_utf8(bytes.to_vec()).map_err(Error::Utf8)) } } diff --git a/src/traits.rs b/src/traits.rs index e4ed6d0..21a1540 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -340,12 +340,12 @@ pub trait Collection: Sized { pub mod tests { use super::*; use crate::{ + error::Error, fetch::object_id::ObjectId, http_signatures::{generate_actor_keypair, Keypair}, protocol::{public_key::PublicKey, verification::verify_domains_match}, }; use activitystreams_kinds::{activity::FollowType, actor::PersonType}; - use anyhow::Error; use once_cell::sync::Lazy; use serde::{Deserialize, Serialize};