improve error messages from gzip decoder
This commit is contained in:
@@ -217,28 +217,30 @@ impl Stream for Gzip {
|
|||||||
//
|
//
|
||||||
// To be safe, this memory could be zeroed before passing to `flate2`.
|
// To be safe, this memory could be zeroed before passing to `flate2`.
|
||||||
// Otherwise we might need to deal with the case where `flate2` panics.
|
// Otherwise we might need to deal with the case where `flate2` panics.
|
||||||
let read = {
|
let read = try_io!(self.inner.read(unsafe { self.buf.bytes_mut() }));
|
||||||
let mut buf = unsafe { self.buf.bytes_mut() };
|
|
||||||
self.inner.read(&mut buf)
|
|
||||||
};
|
|
||||||
|
|
||||||
match read {
|
if read == 0 {
|
||||||
Ok(read) if read == 0 => match self.inner.get_mut().read(&mut [0]) {
|
// If GzDecoder reports EOF, it doesn't necessarily mean the
|
||||||
Ok(0) => Ok(Async::Ready(None)),
|
// underlying stream reached EOF (such as the `0\r\n\r\n`
|
||||||
Ok(_) => Err(error::from(io::Error::new(io::ErrorKind::InvalidData, "Unexpected Data"))),
|
// header meaning a chunked transfer has completed). If it
|
||||||
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => Ok(Async::NotReady),
|
// isn't polled till EOF, the connection may not be able
|
||||||
Err(e) => Err(error::from(e))
|
// to be re-used.
|
||||||
},
|
//
|
||||||
Ok(read) => {
|
// See https://github.com/seanmonstar/reqwest/issues/508.
|
||||||
unsafe { self.buf.advance_mut(read) };
|
let inner_read = try_io!(self.inner.get_mut().read(&mut [0]));
|
||||||
let chunk = Chunk::from_chunk(self.buf.split_to(read).freeze());
|
if inner_read == 0 {
|
||||||
|
Ok(Async::Ready(None))
|
||||||
|
} else {
|
||||||
|
Err(error::from(io::Error::new(
|
||||||
|
io::ErrorKind::InvalidData,
|
||||||
|
"unexpected data after gzip decoder signaled end-of-file",
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unsafe { self.buf.advance_mut(read) };
|
||||||
|
let chunk = Chunk::from_chunk(self.buf.split_to(read).freeze());
|
||||||
|
|
||||||
Ok(Async::Ready(Some(chunk)))
|
Ok(Async::Ready(Some(chunk)))
|
||||||
},
|
|
||||||
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
|
|
||||||
Ok(Async::NotReady)
|
|
||||||
},
|
|
||||||
Err(e) => Err(error::from(e))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
40
src/error.rs
40
src/error.rs
@@ -484,6 +484,18 @@ pub(crate) fn into_io(e: Error) -> io::Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn from_io(e: io::Error) -> Error {
|
||||||
|
if e.get_ref().map(|r| r.is::<Error>()).unwrap_or(false) {
|
||||||
|
*e
|
||||||
|
.into_inner()
|
||||||
|
.expect("io::Error::get_ref was Some(_)")
|
||||||
|
.downcast::<Error>()
|
||||||
|
.expect("StdError::is() was true")
|
||||||
|
} else {
|
||||||
|
from(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
macro_rules! try_ {
|
macro_rules! try_ {
|
||||||
($e:expr) => (
|
($e:expr) => (
|
||||||
@@ -504,6 +516,20 @@ macro_rules! try_ {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! try_io {
|
||||||
|
($e:expr) => (
|
||||||
|
match $e {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(ref err) if err.kind() == ::std::io::ErrorKind::WouldBlock => {
|
||||||
|
return Ok(::futures::Async::NotReady);
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
return Err(::error::from_io(err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn loop_detected(url: Url) -> Error {
|
pub(crate) fn loop_detected(url: Url) -> Error {
|
||||||
Error::new(Kind::RedirectLoop, Some(url))
|
Error::new(Kind::RedirectLoop, Some(url))
|
||||||
}
|
}
|
||||||
@@ -594,4 +620,18 @@ mod tests {
|
|||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
assert_eq!(size_of::<Error>(), size_of::<usize>());
|
assert_eq!(size_of::<Error>(), size_of::<usize>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn roundtrip_io_error() {
|
||||||
|
let orig = unknown_proxy_scheme();
|
||||||
|
// Convert reqwest::Error into an io::Error...
|
||||||
|
let io = into_io(orig);
|
||||||
|
// Convert that io::Error back into a reqwest::Error...
|
||||||
|
let err = from_io(io);
|
||||||
|
// It should have pulled out the original, not nested it...
|
||||||
|
match err.inner.kind {
|
||||||
|
Kind::UnknownProxyScheme => (),
|
||||||
|
_ => panic!("{:?}", err),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user