From 478ac079ee5b4006df30fdcb19128f0d702f1b34 Mon Sep 17 00:00:00 2001 From: Martin Algesten <martin@algesten.se> Date: Mon, 3 Feb 2025 22:08:46 +0100 Subject: [PATCH] Pass through ureq::Error wrapped as io::Error --- CHANGELOG.md | 2 ++ src/body/brotli.rs | 12 +++++++++--- src/body/gzip.rs | 12 +++++++++--- src/error.rs | 8 +++++--- 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4303413..2da8b3e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Unreleased + * ureq::Error wrapped as io::Error should pass through body chain (#984) + # 3.0.4 * Manually unroll some macros to regular code (#978) diff --git a/src/body/brotli.rs b/src/body/brotli.rs index 8379619f..ea81be3e 100644 --- a/src/body/brotli.rs +++ b/src/body/brotli.rs @@ -2,6 +2,7 @@ use std::io; use brotli_decompressor::Decompressor; +use crate::error::is_wrapped_ureq_error; use crate::Error; pub(crate) struct BrotliDecoder<R: io::Read>(Decompressor<R>); @@ -14,8 +15,13 @@ impl<R: io::Read> BrotliDecoder<R> { impl<R: io::Read> io::Read for BrotliDecoder<R> { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { - self.0 - .read(buf) - .map_err(|e| Error::Decompress("brotli", e).into_io()) + self.0.read(buf).map_err(|e| { + if is_wrapped_ureq_error(&e) { + // If this already is a ureq::Error, like Timeout, pass it along. + e + } else { + Error::Decompress("brotli", e).into_io() + } + }) } } diff --git a/src/body/gzip.rs b/src/body/gzip.rs index 0cf0511b..96397271 100644 --- a/src/body/gzip.rs +++ b/src/body/gzip.rs @@ -2,6 +2,7 @@ use std::io; use flate2::read::MultiGzDecoder; +use crate::error::is_wrapped_ureq_error; use crate::Error; pub(crate) struct GzipDecoder<R>(MultiGzDecoder<R>); @@ -14,9 +15,14 @@ impl<R: io::Read> GzipDecoder<R> { impl<R: io::Read> io::Read for GzipDecoder<R> { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { - self.0 - .read(buf) - .map_err(|e| Error::Decompress("gzip", e).into_io()) + self.0.read(buf).map_err(|e| { + if is_wrapped_ureq_error(&e) { + // If this already is a ureq::Error, like Timeout, pass it along. + e + } else { + Error::Decompress("gzip", e).into_io() + } + }) } } diff --git a/src/error.rs b/src/error.rs index 9fe616d5..337fa6fe 100644 --- a/src/error.rs +++ b/src/error.rs @@ -169,11 +169,13 @@ impl Error { } } +pub(crate) fn is_wrapped_ureq_error(e: &io::Error) -> bool { + e.get_ref().map(|x| x.is::<Error>()).unwrap_or(false) +} + impl From<io::Error> for Error { fn from(e: io::Error) -> Self { - let is_wrapped_ureq_error = e.get_ref().map(|x| x.is::<Error>()).unwrap_or(false); - - if is_wrapped_ureq_error { + if is_wrapped_ureq_error(&e) { // unwraps are ok, see above. let boxed = e.into_inner().unwrap(); let ureq = boxed.downcast::<Error>().unwrap();