Make Response::to_json preserve io::Error of ErrorKind::TimedOut

Close #119
This commit is contained in:
Martin Algesten
2020-07-30 17:40:14 +02:00
parent db4cc90956
commit 6614856163
2 changed files with 23 additions and 14 deletions

View File

@@ -400,8 +400,20 @@ impl Response {
/// ``` /// ```
#[cfg(feature = "json")] #[cfg(feature = "json")]
pub fn into_json(self) -> IoResult<serde_json::Value> { pub fn into_json(self) -> IoResult<serde_json::Value> {
use crate::stream::io_err_timeout;
use std::error::Error;
let reader = self.into_reader(); let reader = self.into_reader();
serde_json::from_reader(reader).map_err(|e| { serde_json::from_reader(reader).map_err(|e| {
// This is to unify TimedOut IoError in the API.
// We make a clone of the original error since serde_json::Error doesn't
// let us get the wrapped error instance back.
if let Some(ioe) = e.source().and_then(|s| s.downcast_ref::<IoError>()) {
if ioe.kind() == ErrorKind::TimedOut {
return io_err_timeout(ioe.to_string());
}
}
IoError::new( IoError::new(
ErrorKind::InvalidData, ErrorKind::InvalidData,
format!("Failed to read JSON: {}", e), format!("Failed to read JSON: {}", e),

View File

@@ -79,7 +79,7 @@ impl Read for DeadlineStream {
// Since the socket most definitely not set_nonblocking(true), // Since the socket most definitely not set_nonblocking(true),
// we can safely normalize WouldBlock to TimedOut // we can safely normalize WouldBlock to TimedOut
if e.kind() == ErrorKind::WouldBlock { if e.kind() == ErrorKind::WouldBlock {
return io_error_timeout(); return io_err_timeout("timed out reading response".to_string());
} }
e e
}) })
@@ -91,13 +91,13 @@ impl Read for DeadlineStream {
fn time_until_deadline(deadline: Instant) -> IoResult<Duration> { fn time_until_deadline(deadline: Instant) -> IoResult<Duration> {
let now = Instant::now(); let now = Instant::now();
match deadline.checked_duration_since(now) { match deadline.checked_duration_since(now) {
None => Err(io_error_timeout()), None => Err(io_err_timeout("timed out reading response".to_string())),
Some(duration) => Ok(duration), Some(duration) => Ok(duration),
} }
} }
fn io_error_timeout() -> IoError { pub(crate) fn io_err_timeout(error: String) -> IoError {
IoError::new(ErrorKind::TimedOut, "timed out reading response") IoError::new(ErrorKind::TimedOut, error)
} }
impl ::std::fmt::Debug for Stream { impl ::std::fmt::Debug for Stream {
@@ -541,20 +541,17 @@ fn connect_socks5(
let done = lock.lock().unwrap(); let done = lock.lock().unwrap();
let timeout_connect = time_until_deadline(deadline)?; let timeout_connect = time_until_deadline(deadline)?;
let done_result = cvar let done_result = cvar.wait_timeout(done, timeout_connect).unwrap();
.wait_timeout(done, timeout_connect)
.unwrap();
let done = done_result.0; let done = done_result.0;
if *done { if *done {
rx.recv().unwrap()? rx.recv().unwrap()?
} else { } else {
return Err(std::io::Error::new( return Err(io_err_timeout(format!(
ErrorKind::TimedOut,
format!(
"SOCKS5 proxy: {}:{} timed out connecting after {}ms.", "SOCKS5 proxy: {}:{} timed out connecting after {}ms.",
host, port, timeout_connect.as_millis() host,
), port,
)); timeout_connect.as_millis()
)));
} }
} else { } else {
get_socks5_stream(&proxy, &proxy_addr, host_addr)? get_socks5_stream(&proxy, &proxy_addr, host_addr)?