From e7ef6a565f272be48171c4e073f0f0cd67d071d6 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Tue, 25 Aug 2026 04:02:38 +0200 Subject: [PATCH] Preserve safe SSE failure classes --- src/provider_backend.rs | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/provider_backend.rs b/src/provider_backend.rs index 91c4870..6776e86 100644 --- a/src/provider_backend.rs +++ b/src/provider_backend.rs @@ -500,7 +500,7 @@ fn parse_responses_sse(reader: impl Read) -> Result Result &'static str { +fn provider_sse_read_error(error: &io::Error) -> &'static str { + if let Some(ureq_error) = error + .get_ref() + .and_then(|source| source.downcast_ref::()) + { + return match ureq_error { + ureq::Error::Timeout(_) => "provider SSE read timed out", + ureq::Error::Protocol(_) => "provider SSE protocol failed", + ureq::Error::Tls(_) | ureq::Error::Rustls(_) => "provider SSE secure transport failed", + ureq::Error::BodyStalled => "provider SSE body stalled", + ureq::Error::Io(inner) => provider_sse_io_error(inner.kind()), + _ => "provider SSE read failed", + }; + } + provider_sse_io_error(error.kind()) +} + +fn provider_sse_io_error(kind: io::ErrorKind) -> &'static str { match kind { io::ErrorKind::TimedOut | io::ErrorKind::WouldBlock => "provider SSE read timed out", io::ErrorKind::ConnectionReset @@ -1057,6 +1074,14 @@ mod tests { } } + struct WrappedFailingReader(Option); + + impl Read for WrappedFailingReader { + fn read(&mut self, _buf: &mut [u8]) -> io::Result { + Err(io::Error::other(self.0.take().unwrap())) + } + } + fn jwt(payload: Value) -> String { let payload = URL_SAFE_NO_PAD.encode(serde_json::to_vec(&payload).unwrap()); format!("e30.{payload}.signature") @@ -1257,6 +1282,10 @@ mod tests { parse_responses_sse(FailingReader(io::ErrorKind::Other)).err(), Some("provider SSE read failed") ); + assert_eq!( + parse_responses_sse(WrappedFailingReader(Some(ureq::Error::BodyStalled))).err(), + Some("provider SSE body stalled") + ); } #[test]