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