From 8045296657a6ee74d98046852e3e7bd5a3d10b08 Mon Sep 17 00:00:00 2001 From: Kaleb Elwert Date: Thu, 26 Mar 2020 04:22:42 -0700 Subject: [PATCH] Switch to a concrete Error type --- Cargo.toml | 2 + README.md | 12 ++--- examples/hello_world.rs | 4 +- examples/middleware.rs | 7 +-- examples/next_reuse.rs | 7 +-- examples/persistent.rs | 4 +- examples/post.rs | 4 +- src/client.rs | 22 +++++----- src/error.rs | 43 ++++++++++++++++++ src/lib.rs | 13 +++--- src/middleware/logger/mod.rs | 4 +- src/middleware/logger/native.rs | 9 ++-- src/middleware/logger/wasm.rs | 2 +- src/middleware/mod.rs | 22 +++++----- src/one_off.rs | 18 ++++---- src/request.rs | 78 +++++++++++++++++---------------- src/response.rs | 32 +++++++------- tests/test.rs | 4 +- 18 files changed, 167 insertions(+), 120 deletions(-) create mode 100644 src/error.rs diff --git a/Cargo.toml b/Cargo.toml index cc8061b..898ad3f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ http = "0.1.17" log = { version = "0.4.7", features = ["kv_unstable"] } mime = "0.3.13" mime_guess = "2.0.3" +thiserror = "1.0" serde = "1.0.97" serde_json = "1.0.40" serde_urlencoded = "0.6.1" @@ -73,6 +74,7 @@ features = [ ] [dev-dependencies] +anyhow = "1.0" async-std = { version = "1.0", features = ["attributes"] } femme = "1.1.0" serde = { version = "1.0.97", features = ["derive"] } diff --git a/README.md b/README.md index 925069f..d76092f 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ quick script, or a cross-platform SDK, Surf will make it work. ```rust use async_std::task; -fn main() -> Result<(), Box> { +fn main() -> Result<(), surf::Error> { task::block_on(async { let mut res = surf::get("https://httpbin.org/get").await?; dbg!(res.body_string().await?); @@ -79,7 +79,7 @@ type directly. ```rust use async_std::task; -fn main() -> Result<(), Box> { +fn main() -> Result<(), surf::Error> { task::block_on(async { dbg!(surf::get("https://httpbin.org/get").recv_string().await?); Ok(()) @@ -93,7 +93,7 @@ Both sending and receiving JSON is real easy too. use async_std::task; use serde::{Deserialize, Serialize}; -fn main() -> Result<(), Box> { +fn main() -> Result<(), surf::Error> { #[derive(Deserialize, Serialize)] struct Ip { ip: String @@ -118,7 +118,7 @@ And even creating streaming proxies is no trouble at all. ```rust use async_std::task; -fn main() -> Result<(), Box> { +fn main() -> Result<(), surf::Error> { task::block_on(async { let reader = surf::get("https://img.fyi/q6YvNqP").await?; let res = surf::post("https://box.rs/upload").body(reader).await?; @@ -129,11 +129,11 @@ fn main() -> Result<(), Box> { ## Installation -Install OpenSSL - +Install OpenSSL - - Ubuntu - ``` sudo apt install libssl-dev ``` - Fedora - ``` sudo dnf install openssl-devel ``` -Make sure your rust is up to date using: +Make sure your rust is up to date using: ``` rustup update ``` With [cargo add](https://github.com/killercup/cargo-edit#Installation) installed : diff --git a/examples/hello_world.rs b/examples/hello_world.rs index f99dbf6..b240ca3 100644 --- a/examples/hello_world.rs +++ b/examples/hello_world.rs @@ -2,13 +2,13 @@ use async_std::task; // The need for Ok with turbofish is explained here // https://rust-lang.github.io/async-book/07_workarounds/03_err_in_async_blocks.html -fn main() -> Result<(), surf::Exception> { +fn main() -> anyhow::Result<()> { femme::start(log::LevelFilter::Info)?; task::block_on(async { let uri = "https://httpbin.org/get"; let string: String = surf::get(uri).recv_string().await?; println!("{}", string); - Ok::<(), surf::Exception>(()) + Ok(()) }) } diff --git a/examples/middleware.rs b/examples/middleware.rs index e5b6717..768f18b 100644 --- a/examples/middleware.rs +++ b/examples/middleware.rs @@ -1,6 +1,7 @@ use async_std::task; use futures::future::BoxFuture; use surf::middleware::{HttpClient, Middleware, Next, Request, Response}; +use surf::Result; struct Printer; @@ -10,7 +11,7 @@ impl Middleware for Printer { req: Request, client: C, next: Next<'a, C>, - ) -> BoxFuture<'a, Result> { + ) -> BoxFuture<'a, Result> { Box::pin(async move { println!("sending a request!"); let res = next.run(req, client).await?; @@ -22,13 +23,13 @@ impl Middleware for Printer { // The need for Ok with turbofish is explained here // https://rust-lang.github.io/async-book/07_workarounds/03_err_in_async_blocks.html -fn main() -> Result<(), surf::Exception> { +fn main() -> anyhow::Result<()> { femme::start(log::LevelFilter::Info)?; task::block_on(async { surf::get("https://httpbin.org/get") .middleware(Printer {}) .await?; - Ok::<(), surf::Exception>(()) + Ok(()) }) } diff --git a/examples/next_reuse.rs b/examples/next_reuse.rs index 11d7c21..fe3a449 100644 --- a/examples/next_reuse.rs +++ b/examples/next_reuse.rs @@ -2,6 +2,7 @@ use async_std::task; use futures::future::BoxFuture; use futures::io::AsyncReadExt; use surf::middleware::{Body, HttpClient, Middleware, Next, Request, Response}; +use surf::Result; struct Doubler; @@ -11,7 +12,7 @@ impl Middleware for Doubler { req: Request, client: C, next: Next<'a, C>, - ) -> BoxFuture<'a, Result> { + ) -> BoxFuture<'a, Result> { if req.method().is_safe() { let mut new_req = Request::new(Body::empty()); *new_req.method_mut() = req.method().clone(); @@ -43,7 +44,7 @@ impl Middleware for Doubler { // The need for Ok with turbofish is explained here // https://rust-lang.github.io/async-book/07_workarounds/03_err_in_async_blocks.html -fn main() -> Result<(), surf::Exception> { +fn main() -> surf::Result<()> { femme::start(log::LevelFilter::Info).unwrap(); task::block_on(async { let mut res = surf::get("https://httpbin.org/get") @@ -53,6 +54,6 @@ fn main() -> Result<(), surf::Exception> { let body = res.body_bytes().await?; let body = String::from_utf8_lossy(&body); println!("{}", body); - Ok::<(), surf::Exception>(()) + Ok(()) }) } diff --git a/examples/persistent.rs b/examples/persistent.rs index 8b59e40..394cbf1 100644 --- a/examples/persistent.rs +++ b/examples/persistent.rs @@ -2,13 +2,13 @@ use async_std::task; // The need for Ok with turbofish is explained here // https://rust-lang.github.io/async-book/07_workarounds/03_err_in_async_blocks.html -fn main() -> Result<(), surf::Exception> { +fn main() -> surf::Result<()> { femme::start(log::LevelFilter::Info).unwrap(); task::block_on(async { let client = surf::Client::new(); let req1 = client.get("https://httpbin.org/get").recv_string(); let req2 = client.get("https://httpbin.org/get").recv_string(); futures::future::try_join(req1, req2).await?; - Ok::<(), surf::Exception>(()) + Ok(()) }) } diff --git a/examples/post.rs b/examples/post.rs index c3b690d..cc4b5b4 100644 --- a/examples/post.rs +++ b/examples/post.rs @@ -2,13 +2,13 @@ use async_std::task; // The need for Ok with turbofish is explained here // https://rust-lang.github.io/async-book/07_workarounds/03_err_in_async_blocks.html -fn main() -> Result<(), surf::Exception> { +fn main() -> surf::Result<()> { femme::start(log::LevelFilter::Info).unwrap(); task::block_on(async { let uri = "https://httpbin.org/post"; let data = serde_json::json!({ "name": "chashu" }); let res = surf::post(uri).body_json(&data).unwrap().await?; assert_eq!(res.status(), 200); - Ok::<(), surf::Exception>(()) + Ok(()) }) } diff --git a/src/client.rs b/src/client.rs index ca066b6..22434f8 100644 --- a/src/client.rs +++ b/src/client.rs @@ -10,7 +10,7 @@ use http_client::native::NativeClient; /// /// ```no_run /// # #[async_std::main] -/// # async fn main() -> Result<(), Box> { +/// # async fn main() -> Result<(), surf::Error> { /// let client = surf::Client::new(); /// let req1 = client.get("https://httpbin.org/get").recv_string(); /// let req2 = client.get("https://httpbin.org/get").recv_string(); @@ -30,7 +30,7 @@ impl Client { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// let client = surf::Client::new(); /// # Ok(()) } /// ``` @@ -63,7 +63,7 @@ impl Client { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// let client = surf::Client::new(); /// let string = client.get("https://httpbin.org/get").recv_string().await?; /// # Ok(()) } @@ -87,7 +87,7 @@ impl Client { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// let client = surf::Client::new(); /// let string = client.head("https://httpbin.org/head").recv_string().await?; /// # Ok(()) } @@ -111,7 +111,7 @@ impl Client { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// let client = surf::Client::new(); /// let string = client.post("https://httpbin.org/post").recv_string().await?; /// # Ok(()) } @@ -135,7 +135,7 @@ impl Client { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// let client = surf::Client::new(); /// let string = client.put("https://httpbin.org/put").recv_string().await?; /// # Ok(()) } @@ -159,7 +159,7 @@ impl Client { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// let client = surf::Client::new(); /// let string = client.delete("https://httpbin.org/delete").recv_string().await?; /// # Ok(()) } @@ -183,7 +183,7 @@ impl Client { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// let client = surf::Client::new(); /// let string = client.connect("https://httpbin.org/connect").recv_string().await?; /// # Ok(()) } @@ -207,7 +207,7 @@ impl Client { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// let client = surf::Client::new(); /// let string = client.options("https://httpbin.org/options").recv_string().await?; /// # Ok(()) } @@ -231,7 +231,7 @@ impl Client { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// let client = surf::Client::new(); /// let string = client.trace("https://httpbin.org/trace").recv_string().await?; /// # Ok(()) } @@ -255,7 +255,7 @@ impl Client { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// let client = surf::Client::new(); /// let string = client.patch("https://httpbin.org/patch").recv_string().await?; /// # Ok(()) } diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..6c05933 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,43 @@ +use std::result::Result as StdResult; + +use thiserror::Error as ThisError; + +#[allow(missing_docs)] +pub type Result = StdResult; + +#[allow(missing_docs)] +#[derive(ThisError, Debug)] +#[error(transparent)] +pub struct Error(#[from] InternalError); + +macro_rules! impl_from { + ($bound:ty) => { + impl From<$bound> for Error { + fn from(err: $bound) -> Error { + InternalError::from(err).into() + } + } + }; +} + +impl_from!(log::kv::Error); +impl_from!(serde_urlencoded::ser::Error); +impl_from!(serde_urlencoded::de::Error); +impl_from!(std::io::Error); +impl_from!(serde_json::Error); + +#[derive(ThisError, Debug)] +pub(crate) enum InternalError { + #[error(transparent)] + LogError(#[from] log::kv::Error), + #[error(transparent)] + UrlEncodeError(#[from] serde_urlencoded::ser::Error), + #[error(transparent)] + UrlDecodeError(#[from] serde_urlencoded::de::Error), + #[error(transparent)] + IoError(#[from] std::io::Error), + #[error(transparent)] + JsonError(#[from] serde_json::Error), + #[error("{0}")] + HttpError(String), +} diff --git a/src/lib.rs b/src/lib.rs index 5c9e066..4f3697f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,7 +15,7 @@ //! # Examples //! ```no_run //! # #[async_std::main] -//! # async fn main() -> Result<(), Box> { +//! # async fn main() -> Result<(), surf::Error> { //! let mut res = surf::get("https://httpbin.org/get").await?; //! dbg!(res.body_string().await?); //! # Ok(()) } @@ -24,7 +24,7 @@ //! It's also possible to skip the intermediate `Response`, and access the response type directly. //! ```no_run //! # #[async_std::main] -//! # async fn main() -> Result<(), Box> { +//! # async fn main() -> Result<(), surf::Error> { //! dbg!(surf::get("https://httpbin.org/get").recv_string().await?); //! # Ok(()) } //! ``` @@ -33,7 +33,7 @@ //! ```no_run //! # use serde::{Deserialize, Serialize}; //! # #[async_std::main] -//! # async fn main() -> Result<(), Box> { +//! # async fn main() -> Result<(), surf::Error> { //! #[derive(Deserialize, Serialize)] //! struct Ip { //! ip: String @@ -54,7 +54,7 @@ //! //! ```no_run //! # #[async_std::main] -//! # async fn main() -> Result<(), Box> { +//! # async fn main() -> Result<(), surf::Error> { //! let reader = surf::get("https://img.fyi/q6YvNqP").await?; //! let res = surf::post("https://box.rs/upload").body(reader).await?; //! # Ok(()) } @@ -75,6 +75,7 @@ #![cfg_attr(test, deny(warnings))] mod client; +mod error; mod request; mod response; @@ -86,6 +87,7 @@ pub use mime; pub use url; pub use client::Client; +pub use error::{Error, Result}; pub use request::Request; pub use response::{DecodeError, Response}; @@ -93,6 +95,3 @@ pub use response::{DecodeError, Response}; mod one_off; #[cfg(feature = "native-client")] pub use one_off::{connect, delete, get, head, options, patch, post, put, trace}; - -/// A generic error type. -pub type Exception = Box; diff --git a/src/middleware/logger/mod.rs b/src/middleware/logger/mod.rs index cbd683a..b6509b5 100644 --- a/src/middleware/logger/mod.rs +++ b/src/middleware/logger/mod.rs @@ -4,7 +4,7 @@ //! //! ```no_run //! # #[async_std::main] -//! # async fn main() -> Result<(), Box> { +//! # async fn main() -> Result<(), surf::Error> { //! let mut res = surf::get("https://httpbin.org/get") //! .middleware(surf::middleware::logger::new()) //! .await?; @@ -30,7 +30,7 @@ use native::Logger; /// /// ```no_run /// # #[async_std::main] -/// # async fn main() -> Result<(), Box> { +/// # async fn main() -> Result<(), surf::Error> { /// let mut res = surf::get("https://httpbin.org/get") /// .middleware(surf::middleware::logger::new()) /// .await?; diff --git a/src/middleware/logger/native.rs b/src/middleware/logger/native.rs index 85ae792..689b42c 100644 --- a/src/middleware/logger/native.rs +++ b/src/middleware/logger/native.rs @@ -1,7 +1,8 @@ use crate::middleware::{Middleware, Next, Request, Response}; -use http_client::HttpClient; +use crate::Result; use futures::future::BoxFuture; +use http_client::HttpClient; use std::fmt::Arguments; use std::sync::atomic::{AtomicUsize, Ordering}; use std::time; @@ -28,7 +29,7 @@ impl Middleware for Logger { req: Request, client: C, next: Next<'a, C>, - ) -> BoxFuture<'a, Result> { + ) -> BoxFuture<'a, Result> { Box::pin(async move { let start_time = time::Instant::now(); let uri = format!("{}", req.uri()); @@ -80,7 +81,7 @@ impl<'a> log::kv::Source for RequestPairs<'a> { fn visit<'kvs>( &'kvs self, visitor: &mut dyn log::kv::Visitor<'kvs>, - ) -> Result<(), log::kv::Error> { + ) -> std::result::Result<(), log::kv::Error> { visitor.visit_pair("req.id".into(), self.id.into())?; visitor.visit_pair("req.method".into(), self.method.into())?; visitor.visit_pair("req.uri".into(), self.uri.into())?; @@ -98,7 +99,7 @@ impl<'a> log::kv::Source for ResponsePairs<'a> { fn visit<'kvs>( &'kvs self, visitor: &mut dyn log::kv::Visitor<'kvs>, - ) -> Result<(), log::kv::Error> { + ) -> std::result::Result<(), log::kv::Error> { visitor.visit_pair("req.id".into(), self.id.into())?; visitor.visit_pair("req.status".into(), self.status.into())?; visitor.visit_pair("elapsed".into(), self.elapsed.into())?; diff --git a/src/middleware/logger/wasm.rs b/src/middleware/logger/wasm.rs index 0d32142..86921e9 100644 --- a/src/middleware/logger/wasm.rs +++ b/src/middleware/logger/wasm.rs @@ -25,7 +25,7 @@ impl Middleware for Logger { req: Request, client: C, next: Next<'a, C>, - ) -> BoxFuture<'a, Result> { + ) -> BoxFuture<'a, Result> { Box::pin(async move { let uri = format!("{}", req.uri()); let method = format!("{}", req.method()); diff --git a/src/middleware/mod.rs b/src/middleware/mod.rs index d58fd44..b67c727 100644 --- a/src/middleware/mod.rs +++ b/src/middleware/mod.rs @@ -16,7 +16,7 @@ //! req: Request, //! client: C, //! next: Next<'a, C>, -//! ) -> BoxFuture<'a, Result> { +//! ) -> BoxFuture<'a, Result> { //! Box::pin(async move { //! println!("sending request to {}", req.uri()); //! let now = time::Instant::now(); @@ -35,7 +35,7 @@ //! use surf::middleware::{Next, Middleware, Request, Response, HttpClient}; //! use std::time; //! -//! fn logger<'a, C: HttpClient>(req: Request, client: C, next: Next<'a, C>) -> BoxFuture<'a, Result> { +//! fn logger<'a, C: HttpClient>(req: Request, client: C, next: Next<'a, C>) -> BoxFuture<'a, Result> { //! Box::pin(async move { //! println!("sending request to {}", req.uri()); //! let now = time::Instant::now(); @@ -51,7 +51,7 @@ pub use http_client::{Body, HttpClient, Request, Response}; pub mod logger; -use crate::Exception; +use crate::Result; use futures::future::BoxFuture; use std::sync::Arc; @@ -63,7 +63,7 @@ pub trait Middleware: 'static + Send + Sync { req: Request, client: C, next: Next<'a, C>, - ) -> BoxFuture<'a, Result>; + ) -> BoxFuture<'a, Result>; } // This allows functions to work as middleware too. @@ -72,14 +72,14 @@ where F: Send + Sync + 'static - + for<'a> Fn(Request, C, Next<'a, C>) -> BoxFuture<'a, Result>, + + for<'a> Fn(Request, C, Next<'a, C>) -> BoxFuture<'a, Result>, { fn handle<'a>( &'a self, req: Request, client: C, next: Next<'a, C>, - ) -> BoxFuture<'a, Result> { + ) -> BoxFuture<'a, Result> { (self)(req, client, next) } } @@ -88,10 +88,8 @@ where #[allow(missing_debug_implementations)] pub struct Next<'a, C: HttpClient> { next_middleware: &'a [Arc>], - endpoint: &'a (dyn (Fn(Request, C) -> BoxFuture<'static, Result>) - + 'static - + Send - + Sync), + endpoint: + &'a (dyn (Fn(Request, C) -> BoxFuture<'static, Result>) + 'static + Send + Sync), } impl Clone for Next<'_, C> { @@ -109,7 +107,7 @@ impl<'a, C: HttpClient> Next<'a, C> { /// Create a new instance pub fn new( next: &'a [Arc>], - endpoint: &'a (dyn (Fn(Request, C) -> BoxFuture<'static, Result>) + endpoint: &'a (dyn (Fn(Request, C) -> BoxFuture<'static, Result>) + 'static + Send + Sync), @@ -121,7 +119,7 @@ impl<'a, C: HttpClient> Next<'a, C> { } /// Asynchronously execute the remaining middleware chain. - pub fn run(mut self, req: Request, client: C) -> BoxFuture<'a, Result> { + pub fn run(mut self, req: Request, client: C) -> BoxFuture<'a, Result> { if let Some((current, next)) = self.next_middleware.split_first() { self.next_middleware = next; current.handle(req, client, self) diff --git a/src/one_off.rs b/src/one_off.rs index a15e0bb..ab4f305 100644 --- a/src/one_off.rs +++ b/src/one_off.rs @@ -26,7 +26,7 @@ use super::Request; /// /// ```no_run /// # #[async_std::main] -/// # async fn main() -> Result<(), Box> { +/// # async fn main() -> Result<(), surf::Error> { /// let string = surf::get("https://httpbin.org/get").recv_string().await?; /// # Ok(()) } /// ``` @@ -67,7 +67,7 @@ pub fn get(uri: impl AsRef) -> Request { /// /// ```no_run /// # #[async_std::main] -/// # async fn main() -> Result<(), Box> { +/// # async fn main() -> Result<(), surf::Error> { /// let string = surf::head("https://httpbin.org/head").recv_string().await?; /// # Ok(()) } /// ``` @@ -125,7 +125,7 @@ pub fn head(uri: impl AsRef) -> Request { /// /// ```no_run /// # #[async_std::main] -/// # async fn main() -> Result<(), Box> { +/// # async fn main() -> Result<(), surf::Error> { /// let string = surf::post("https://httpbin.org/post").recv_string().await?; /// # Ok(()) } /// ``` @@ -161,7 +161,7 @@ pub fn post(uri: impl AsRef) -> Request { /// /// ```no_run /// # #[async_std::main] -/// # async fn main() -> Result<(), Box> { +/// # async fn main() -> Result<(), surf::Error> { /// let string = surf::put("https://httpbin.org/put").recv_string().await?; /// # Ok(()) } /// ``` @@ -192,7 +192,7 @@ pub fn put(uri: impl AsRef) -> Request { /// /// ```no_run /// # #[async_std::main] -/// # async fn main() -> Result<(), Box> { +/// # async fn main() -> Result<(), surf::Error> { /// let string = surf::delete("https://httpbin.org/delete").recv_string().await?; /// # Ok(()) } /// ``` @@ -232,7 +232,7 @@ pub fn delete(uri: impl AsRef) -> Request { /// /// ```no_run /// # #[async_std::main] -/// # async fn main() -> Result<(), Box> { +/// # async fn main() -> Result<(), surf::Error> { /// let string = surf::connect("https://httpbin.org/connect").recv_string().await?; /// # Ok(()) } /// ``` @@ -265,7 +265,7 @@ pub fn connect(uri: impl AsRef) -> Request { /// /// ```no_run /// # #[async_std::main] -/// # async fn main() -> Result<(), Box> { +/// # async fn main() -> Result<(), surf::Error> { /// let string = surf::options("https://httpbin.org/options").recv_string().await?; /// # Ok(()) } /// ``` @@ -302,7 +302,7 @@ pub fn options(uri: impl AsRef) -> Request { /// /// ```no_run /// # #[async_std::main] -/// # async fn main() -> Result<(), Box> { +/// # async fn main() -> Result<(), surf::Error> { /// let string = surf::trace("https://httpbin.org/trace").recv_string().await?; /// # Ok(()) } /// ``` @@ -345,7 +345,7 @@ pub fn trace(uri: impl AsRef) -> Request { /// /// ```no_run /// # #[async_std::main] -/// # async fn main() -> Result<(), Box> { +/// # async fn main() -> Result<(), surf::Error> { /// let string = surf::patch("https://httpbin.org/patch").recv_string().await?; /// # Ok(()) } /// ``` diff --git a/src/request.rs b/src/request.rs index 86749c3..3e33dae 100644 --- a/src/request.rs +++ b/src/request.rs @@ -7,8 +7,8 @@ use url::Url; use crate::headers::Headers; use crate::middleware::{Middleware, Next}; -use crate::Exception; use crate::Response; +use crate::Result; use http_client::{self, Body, HttpClient}; use std::fmt; @@ -35,7 +35,7 @@ pub struct Request { /// Holds the inner middleware. middleware: Option>>>, /// Holds the state of the `impl Future`. - fut: Option>>, + fut: Option>>, /// Holds a reference to the Url url: Url, } @@ -52,7 +52,7 @@ impl Request { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), anyhow::Error> { /// use surf::{http, url}; /// /// let method = http::Method::GET; @@ -98,7 +98,7 @@ impl Request { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// let res = surf::get("https://httpbin.org/get") /// .middleware(surf::middleware::logger::new()) /// .await?; @@ -116,7 +116,7 @@ impl Request { /// ```no_run /// # use serde::{Deserialize, Serialize}; /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// #[derive(Serialize, Deserialize)] /// struct Index { /// page: u32 @@ -127,7 +127,7 @@ impl Request { /// assert_eq!(page, 2); /// # Ok(()) } /// ``` - pub fn query(&self) -> Result { + pub fn query(&self) -> Result { use std::io::{Error, ErrorKind}; let query = self .url @@ -143,7 +143,7 @@ impl Request { /// ```no_run /// # use serde::{Deserialize, Serialize}; /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// #[derive(Serialize, Deserialize)] /// struct Index { /// page: u32 @@ -155,10 +155,7 @@ impl Request { /// assert_eq!(format!("{}", req.request().unwrap().uri()), "https://httpbin.org/get?page=2"); /// # Ok(()) } /// ``` - pub fn set_query( - mut self, - query: &(impl Serialize + ?Sized), - ) -> Result { + pub fn set_query(mut self, query: &(impl Serialize + ?Sized)) -> Result { let query = serde_urlencoded::to_string(query)?; self.url.set_query(Some(&query)); @@ -175,7 +172,7 @@ impl Request { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// let req = surf::get("https://httpbin.org/get") /// .set_header("X-Requested-With", "surf"); /// assert_eq!(req.header("X-Requested-With"), Some("surf")); @@ -195,7 +192,7 @@ impl Request { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// let req = surf::get("https://httpbin.org/get") /// .set_header("X-Requested-With", "surf"); /// assert_eq!(req.header("X-Requested-With"), Some("surf")); @@ -217,7 +214,7 @@ impl Request { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), surf::Exception> { + /// # async fn main() -> Result<(), surf::Error> { /// let mut req = surf::get("https://httpbin.org/get") /// .set_header("X-Requested-With", "surf"); /// @@ -236,7 +233,7 @@ impl Request { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// use surf::http; /// let req = surf::get("https://httpbin.org/get"); /// assert_eq!(req.method(), http::Method::GET); @@ -253,7 +250,7 @@ impl Request { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), anyhow::Error> { /// use surf::url::Url; /// let req = surf::get("https://httpbin.org/get"); /// assert_eq!(req.url(), &Url::parse("https://httpbin.org/get")?); @@ -280,7 +277,7 @@ impl Request { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// use surf::mime; /// let req = surf::post("https://httpbin.org/get") /// .set_mime(mime::TEXT_CSS); @@ -300,7 +297,7 @@ impl Request { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// use surf::mime; /// let req = surf::post("https://httpbin.org/get") /// .set_mime(mime::TEXT_CSS); @@ -321,7 +318,7 @@ impl Request { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// let reader = surf::get("https://httpbin.org/get").await?; /// let uri = "https://httpbin.org/post"; /// let res = surf::post(uri).body(reader).await?; @@ -350,7 +347,7 @@ impl Request { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// let uri = "https://httpbin.org/post"; /// let data = serde_json::json!({ "name": "chashu" }); /// let res = surf::post(uri).body_json(&data)?.await?; @@ -372,7 +369,7 @@ impl Request { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// let uri = "https://httpbin.org/post"; /// let data = "hello world".to_string(); /// let res = surf::post(uri).body_string(data).await?; @@ -394,7 +391,7 @@ impl Request { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// let uri = "https://httpbin.org/post"; /// let data = b"hello world"; /// let res = surf::post(uri).body_bytes(data).await?; @@ -424,7 +421,7 @@ impl Request { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), surf::Exception> { + /// # async fn main() -> Result<(), surf::Error> { /// let res = surf::post("https://httpbin.org/post") /// .body_file("README.md")? /// .await?; @@ -453,7 +450,7 @@ impl Request { /// ```no_run /// # use serde::{Deserialize, Serialize}; /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// #[derive(Serialize, Deserialize)] /// struct Body { /// apples: u32 @@ -465,10 +462,7 @@ impl Request { /// assert_eq!(res.status(), 200); /// # Ok(()) } /// ``` - pub fn body_form( - mut self, - form: &(impl Serialize + ?Sized), - ) -> Result { + pub fn body_form(mut self, form: &(impl Serialize + ?Sized)) -> Result { let query = serde_urlencoded::to_string(form)?; self = self.body_string(query); self = self.set_mime(mime::APPLICATION_WWW_FORM_URLENCODED); @@ -481,12 +475,12 @@ impl Request { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// let bytes = surf::get("https://httpbin.org/get").recv_bytes().await?; /// assert!(bytes.len() > 0); /// # Ok(()) } /// ``` - pub async fn recv_bytes(self) -> Result, Exception> { + pub async fn recv_bytes(self) -> Result> { let mut req = self.await?; Ok(req.body_bytes().await?) } @@ -497,12 +491,12 @@ impl Request { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// let string = surf::get("https://httpbin.org/get").recv_string().await?; /// assert!(string.len() > 0); /// # Ok(()) } /// ``` - pub async fn recv_string(self) -> Result { + pub async fn recv_string(self) -> Result { let mut req = self.await?; Ok(req.body_string().await?) } @@ -514,7 +508,7 @@ impl Request { /// ```no_run /// # use serde::{Deserialize, Serialize}; /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// #[derive(Deserialize, Serialize)] /// struct Ip { /// ip: String @@ -525,7 +519,7 @@ impl Request { /// assert!(ip.len() > 10); /// # Ok(()) } /// ``` - pub async fn recv_json(self) -> Result { + pub async fn recv_json(self) -> Result { let mut req = self.await?; Ok(req.body_json::().await?) } @@ -545,7 +539,7 @@ impl Request { /// ```no_run /// # use serde::{Deserialize, Serialize}; /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// #[derive(Deserialize, Serialize)] /// struct Body { /// apples: u32 @@ -555,7 +549,7 @@ impl Request { /// let Body { apples } = surf::get(url).recv_form().await?; /// # Ok(()) } /// ``` - pub async fn recv_form(self) -> Result { + pub async fn recv_form(self) -> Result { let mut req = self.await?; Ok(req.body_form::().await?) } @@ -567,7 +561,7 @@ impl Request { } impl Future for Request { - type Output = Result; + type Output = Result; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { if self.fut.is_none() { @@ -579,7 +573,15 @@ impl Future for Request { self.fut = Some(Box::pin(async move { let next = Next::new(&middleware, &|req, client| { - Box::pin(async move { client.send(req).await.map_err(|e| e.into()) }) + Box::pin(async move { + client.send(req).await.map_err(|e| { + // The error returned by http_client is a boxed + // error. Because of this, we need to force it to be + // a more useful type that we can actually put + // inside out error struct. + crate::error::InternalError::HttpError(e.to_string()).into() + }) + }) }); let res = next.run(req, client).await?; diff --git a/src/response.rs b/src/response.rs index cfbf162..8155e60 100644 --- a/src/response.rs +++ b/src/response.rs @@ -10,7 +10,7 @@ use std::pin::Pin; use std::task::{Context, Poll}; use crate::headers::Headers; -use crate::Exception; +use crate::Result; use futures::io::AsyncReadExt; use http_client; @@ -31,7 +31,7 @@ impl Response { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// let res = surf::get("https://httpbin.org/get").await?; /// assert_eq!(res.status(), 200); /// # Ok(()) } @@ -46,7 +46,7 @@ impl Response { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// use surf::http::version::Version; /// /// let res = surf::get("https://httpbin.org/get").await?; @@ -63,7 +63,7 @@ impl Response { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// let res = surf::get("https://httpbin.org/get").await?; /// assert!(res.header("Content-Length").is_some()); /// # Ok(()) } @@ -79,7 +79,7 @@ impl Response { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), surf::Exception> { + /// # async fn main() -> Result<(), surf::Error> { /// let mut res = surf::post("https://httpbin.org/get").await?; /// for (name, value) in res.headers() { /// println!("{}: {}", name, value); @@ -104,7 +104,7 @@ impl Response { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// use surf::mime; /// let res = surf::get("https://httpbin.org/json").await?; /// assert_eq!(res.mime(), Some(mime::APPLICATION_JSON)); @@ -129,7 +129,7 @@ impl Response { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// let mut res = surf::get("https://httpbin.org/get").await?; /// let bytes: Vec = res.body_bytes().await?; /// # Ok(()) } @@ -165,12 +165,12 @@ impl Response { /// /// ```no_run /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// let mut res = surf::get("https://httpbin.org/get").await?; /// let string: String = res.body_string().await?; /// # Ok(()) } /// ``` - pub async fn body_string(&mut self) -> Result { + pub async fn body_string(&mut self) -> Result { let bytes = self.body_bytes().await?; let mime = self.mime(); let claimed_encoding = mime @@ -195,7 +195,7 @@ impl Response { /// ```no_run /// # use serde::{Deserialize, Serialize}; /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// #[derive(Deserialize, Serialize)] /// struct Ip { /// ip: String @@ -225,7 +225,7 @@ impl Response { /// ```no_run /// # use serde::{Deserialize, Serialize}; /// # #[async_std::main] - /// # async fn main() -> Result<(), Box> { + /// # async fn main() -> Result<(), surf::Error> { /// #[derive(Deserialize, Serialize)] /// struct Body { /// apples: u32 @@ -235,7 +235,7 @@ impl Response { /// let Body { apples } = res.body_form().await?; /// # Ok(()) } /// ``` - pub async fn body_form(&mut self) -> Result { + pub async fn body_form(&mut self) -> Result { let string = self.body_string().await?; Ok(serde_urlencoded::from_str(&string) .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?) @@ -248,7 +248,7 @@ impl AsyncRead for Response { mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8], - ) -> Poll> { + ) -> Poll> { Pin::new(&mut self.response.body_mut()).poll_read(cx, buf) } } @@ -313,7 +313,7 @@ fn is_utf8_encoding(encoding_label: &str) -> bool { /// If the body cannot be decoded as utf-8, this function returns an `std::io::Error` of kind /// `std::io::ErrorKind::InvalidData`, carrying a `DecodeError` struct. #[cfg(not(feature = "encoding"))] -fn decode_body(bytes: Vec, content_encoding: Option<&str>) -> Result { +fn decode_body(bytes: Vec, content_encoding: Option<&str>) -> Result { if is_utf8_encoding(content_encoding.unwrap_or("utf-8")) { Ok(String::from_utf8(bytes).map_err(|err| { let err = DecodeError { @@ -341,7 +341,7 @@ fn decode_body(bytes: Vec, content_encoding: Option<&str>) -> Result, content_encoding: Option<&str>) -> Result { +fn decode_body(bytes: Vec, content_encoding: Option<&str>) -> Result { use encoding_rs::Encoding; use std::borrow::Cow; @@ -382,7 +382,7 @@ fn decode_body(bytes: Vec, content_encoding: Option<&str>) -> Result, content_encoding: Option<&str>) -> Result { +fn decode_body(mut bytes: Vec, content_encoding: Option<&str>) -> Result { use web_sys::TextDecoder; // Encoding names are always valid ASCII, so we can avoid including casing mapping tables diff --git a/tests/test.rs b/tests/test.rs index e08b856..325f12b 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -1,7 +1,7 @@ use mockito::mock; #[async_std::test] -async fn post_json() -> Result<(), surf::Exception> { +async fn post_json() -> anyhow::Result<()> { #[derive(serde::Deserialize, serde::Serialize)] struct Cat { name: String, @@ -23,7 +23,7 @@ async fn post_json() -> Result<(), surf::Exception> { } #[async_std::test] -async fn get_json() -> Result<(), surf::Exception> { +async fn get_json() -> anyhow::Result<()> { #[derive(serde::Deserialize)] struct Message { message: String,