Make Response::to_json preserve io::Error of ErrorKind::TimedOut
Close #119
This commit is contained in:
@@ -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),
|
||||||
|
|||||||
@@ -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)?
|
||||||
|
|||||||
Reference in New Issue
Block a user