Redesign Error type
				
					
				
			- The `Error`'s kind is a now a set of variants depending on the context of when an error could occur. - If another error was the cause, it is now always the `source`. Along with the `is_*` methods, this should help in understanding *when* a certain error occurred. For example, an error setting the TLS certificates will return a builder error, with the TLS error as the source. This should help differentiate from a TLS error that happens when connecting to a server. It also makes the internal code less dependent on all the exact dependencies that can be enabled or disabled.
This commit is contained in:
		| @@ -258,9 +258,8 @@ async fn send_future(sender: Sender) -> Result<(), crate::Error> { | ||||
|                     buf.advance_mut(n); | ||||
|                 }, | ||||
|                 Err(e) => { | ||||
|                     let ret = io::Error::new(e.kind(), e.to_string()); | ||||
|                     tx.take().expect("tx only taken on error").abort(); | ||||
|                     return Err(crate::error::from(ret)); | ||||
|                     return Err(crate::error::body(e)); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @@ -273,7 +272,7 @@ async fn send_future(sender: Sender) -> Result<(), crate::Error> { | ||||
|             .expect("tx only taken on error") | ||||
|             .send_data(buf.take().freeze().into()) | ||||
|             .await | ||||
|             .map_err(crate::error::from)?; | ||||
|             .map_err(crate::error::body)?; | ||||
|  | ||||
|         written += buf_len; | ||||
|     } | ||||
|   | ||||
| @@ -550,7 +550,7 @@ impl ClientHandle { | ||||
|             .spawn(move || { | ||||
|                 use tokio::runtime::current_thread::Runtime; | ||||
|  | ||||
|                 let mut rt = match Runtime::new().map_err(crate::error::from) { | ||||
|                 let mut rt = match Runtime::new().map_err(crate::error::builder) { | ||||
|                     Err(e) => { | ||||
|                         if let Err(e) = spawn_tx.send(Err(e)) { | ||||
|                             error!("Failed to communicate runtime creation failure: {:?}", e); | ||||
| @@ -587,7 +587,7 @@ impl ClientHandle { | ||||
|  | ||||
|                 rt.block_on(f) | ||||
|             }) | ||||
|             .map_err(crate::error::from)?; | ||||
|             .map_err(crate::error::builder)?; | ||||
|  | ||||
|         // Wait for the runtime thread to start up... | ||||
|         match wait::timeout(spawn_rx, None) { | ||||
| @@ -639,8 +639,8 @@ impl ClientHandle { | ||||
|                 self.timeout.0, | ||||
|                 KeepCoreThreadAlive(Some(self.inner.clone())), | ||||
|             )), | ||||
|             Err(wait::Waited::TimedOut) => Err(crate::error::timedout(Some(url))), | ||||
|             Err(wait::Waited::Executor(err)) => Err(crate::error::from(err).with_url(url)), | ||||
|             Err(wait::Waited::TimedOut(e)) => Err(crate::error::request(e).with_url(url)), | ||||
|             Err(wait::Waited::Executor(err)) => Err(crate::error::request(err).with_url(url)), | ||||
|             Err(wait::Waited::Inner(err)) => Err(err.with_url(url)), | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -60,8 +60,6 @@ mod request; | ||||
| mod response; | ||||
| mod wait; | ||||
|  | ||||
| pub(crate) use self::wait::Waited; | ||||
|  | ||||
| pub use self::body::Body; | ||||
| pub use self::client::{Client, ClientBuilder}; | ||||
| pub use self::request::{Request, RequestBuilder}; | ||||
|   | ||||
| @@ -234,7 +234,7 @@ impl Part { | ||||
|  | ||||
|     /// Tries to set the mime of this part. | ||||
|     pub fn mime_str(self, mime: &str) -> crate::Result<Part> { | ||||
|         Ok(self.mime(mime.parse().map_err(crate::error::from)?)) | ||||
|         Ok(self.mime(mime.parse().map_err(crate::error::builder)?)) | ||||
|     } | ||||
|  | ||||
|     // Re-export when mime 0.4 is available, with split MediaType/MediaRange. | ||||
|   | ||||
| @@ -149,9 +149,9 @@ impl RequestBuilder { | ||||
|                     Ok(value) => { | ||||
|                         req.headers_mut().append(key, value); | ||||
|                     } | ||||
|                     Err(e) => error = Some(crate::error::from(e.into())), | ||||
|                     Err(e) => error = Some(crate::error::builder(e.into())), | ||||
|                 }, | ||||
|                 Err(e) => error = Some(crate::error::from(e.into())), | ||||
|                 Err(e) => error = Some(crate::error::builder(e.into())), | ||||
|             }; | ||||
|         } | ||||
|         if let Some(err) = error { | ||||
| @@ -323,7 +323,7 @@ impl RequestBuilder { | ||||
|             let serializer = serde_urlencoded::Serializer::new(&mut pairs); | ||||
|  | ||||
|             if let Err(err) = query.serialize(serializer) { | ||||
|                 error = Some(crate::error::from(err)); | ||||
|                 error = Some(crate::error::builder(err)); | ||||
|             } | ||||
|         } | ||||
|         if let Ok(ref mut req) = self.request { | ||||
| @@ -374,7 +374,7 @@ impl RequestBuilder { | ||||
|                     ); | ||||
|                     *req.body_mut() = Some(body.into()); | ||||
|                 } | ||||
|                 Err(err) => error = Some(crate::error::from(err)), | ||||
|                 Err(err) => error = Some(crate::error::builder(err)), | ||||
|             } | ||||
|         } | ||||
|         if let Some(err) = error { | ||||
| @@ -417,7 +417,7 @@ impl RequestBuilder { | ||||
|                         .insert(CONTENT_TYPE, HeaderValue::from_static("application/json")); | ||||
|                     *req.body_mut() = Some(body.into()); | ||||
|                 } | ||||
|                 Err(err) => error = Some(crate::error::from(err)), | ||||
|                 Err(err) => error = Some(crate::error::builder(err)), | ||||
|             } | ||||
|         } | ||||
|         if let Some(err) = error { | ||||
| @@ -797,8 +797,9 @@ mod tests { | ||||
|  | ||||
|     #[test] | ||||
|     fn add_json_fail() { | ||||
|         use serde::ser::Error; | ||||
|         use serde::ser::Error as _; | ||||
|         use serde::{Serialize, Serializer}; | ||||
|         use std::error::Error as _; | ||||
|         struct MyStruct; | ||||
|         impl Serialize for MyStruct { | ||||
|             fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error> | ||||
| @@ -813,7 +814,9 @@ mod tests { | ||||
|         let some_url = "https://google.com/"; | ||||
|         let r = client.post(some_url); | ||||
|         let json_data = MyStruct; | ||||
|         assert!(r.json(&json_data).build().unwrap_err().is_serialization()); | ||||
|         let err = r.json(&json_data).build().unwrap_err(); | ||||
|         assert!(err.is_builder()); // well, duh ;) | ||||
|         assert!(err.source().unwrap().is::<serde_json::Error>()); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|   | ||||
| @@ -205,8 +205,8 @@ impl Response { | ||||
|     /// [`serde_json::from_reader`]: https://docs.serde.rs/serde_json/fn.from_reader.html | ||||
|     pub fn json<T: DeserializeOwned>(self) -> crate::Result<T> { | ||||
|         wait::timeout(self.inner.json(), self.timeout).map_err(|e| match e { | ||||
|             wait::Waited::TimedOut => crate::error::timedout(None), | ||||
|             wait::Waited::Executor(e) => crate::error::from(e), | ||||
|             wait::Waited::TimedOut(e) => crate::error::decode(e), | ||||
|             wait::Waited::Executor(e) => crate::error::decode(e), | ||||
|             wait::Waited::Inner(e) => e, | ||||
|         }) | ||||
|     } | ||||
| @@ -253,8 +253,8 @@ impl Response { | ||||
|     pub fn text_with_charset(self, default_encoding: &str) -> crate::Result<String> { | ||||
|         wait::timeout(self.inner.text_with_charset(default_encoding), self.timeout).map_err(|e| { | ||||
|             match e { | ||||
|                 wait::Waited::TimedOut => crate::error::timedout(None), | ||||
|                 wait::Waited::Executor(e) => crate::error::from(e), | ||||
|                 wait::Waited::TimedOut(e) => crate::error::decode(e), | ||||
|                 wait::Waited::Executor(e) => crate::error::decode(e), | ||||
|                 wait::Waited::Inner(e) => e, | ||||
|             } | ||||
|         }) | ||||
| @@ -284,7 +284,7 @@ impl Response { | ||||
|     where | ||||
|         W: io::Write, | ||||
|     { | ||||
|         io::copy(self, w).map_err(crate::error::from) | ||||
|         io::copy(self, w).map_err(crate::error::response) | ||||
|     } | ||||
|  | ||||
|     /// Turn a response into an error if the server returned an error. | ||||
| @@ -359,8 +359,8 @@ impl Read for Response { | ||||
|  | ||||
|         let timeout = self.timeout; | ||||
|         wait::timeout(self.body_mut().read(buf), timeout).map_err(|e| match e { | ||||
|             wait::Waited::TimedOut => crate::error::timedout(None).into_io(), | ||||
|             wait::Waited::Executor(e) => crate::error::from(e).into_io(), | ||||
|             wait::Waited::TimedOut(e) => crate::error::response(e).into_io(), | ||||
|             wait::Waited::Executor(e) => crate::error::response(e).into_io(), | ||||
|             wait::Waited::Inner(e) => e, | ||||
|         }) | ||||
|     } | ||||
|   | ||||
| @@ -7,14 +7,14 @@ use tokio::clock; | ||||
| use tokio_executor::{ | ||||
|     enter, | ||||
|     park::{Park, ParkThread, Unpark, UnparkThread}, | ||||
|     EnterError, | ||||
| }; | ||||
|  | ||||
| pub(crate) fn timeout<F, I, E>(fut: F, timeout: Option<Duration>) -> Result<I, Waited<E>> | ||||
| where | ||||
|     F: Future<Output = Result<I, E>>, | ||||
| { | ||||
|     let _entered = enter().map_err(Waited::Executor)?; | ||||
|     let _entered = | ||||
|         enter().map_err(|_| Waited::Executor(crate::error::BlockingClientInAsyncContext))?; | ||||
|     let deadline = timeout.map(|d| { | ||||
|         log::trace!("wait at most {:?}", d); | ||||
|         clock::now() + d | ||||
| @@ -39,7 +39,7 @@ where | ||||
|             let now = clock::now(); | ||||
|             if now >= deadline { | ||||
|                 log::trace!("wait timeout exceeded"); | ||||
|                 return Err(Waited::TimedOut); | ||||
|                 return Err(Waited::TimedOut(crate::error::TimedOut)); | ||||
|             } | ||||
|  | ||||
|             log::trace!("park timeout {:?}", deadline - now); | ||||
| @@ -53,8 +53,8 @@ where | ||||
|  | ||||
| #[derive(Debug)] | ||||
| pub(crate) enum Waited<E> { | ||||
|     TimedOut, | ||||
|     Executor(EnterError), | ||||
|     TimedOut(crate::error::TimedOut), | ||||
|     Executor(crate::error::BlockingClientInAsyncContext), | ||||
|     Inner(E), | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user