eventsource_client/
error.rs

1use crate::response::{ErrorBody, Response};
2
3/// Error type for invalid response headers encountered in ResponseDetails.
4#[derive(Debug)]
5pub struct HeaderError {
6    /// Wrapped inner error providing details about the header issue.
7    inner_error: Box<dyn std::error::Error + Send + Sync + 'static>,
8}
9
10impl HeaderError {
11    /// Constructs a new `HeaderError` wrapping an existing error.
12    pub fn new(err: Box<dyn std::error::Error + Send + Sync + 'static>) -> Self {
13        HeaderError { inner_error: err }
14    }
15}
16
17impl std::fmt::Display for HeaderError {
18    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19        write!(f, "Invalid response header: {}", self.inner_error)
20    }
21}
22
23impl std::error::Error for HeaderError {
24    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
25        Some(self.inner_error.as_ref())
26    }
27}
28
29/// Error type returned from this library's functions.
30#[derive(Debug)]
31pub enum Error {
32    TimedOut,
33    StreamClosed,
34    /// An invalid request parameter
35    InvalidParameter(Box<dyn std::error::Error + Send + Sync + 'static>),
36    /// The HTTP response could not be handled.
37    UnexpectedResponse(Response, ErrorBody),
38    /// An error reading from the HTTP response body.
39    HttpStream(Box<dyn std::error::Error + Send + Sync + 'static>),
40    /// The HTTP response stream ended
41    Eof,
42    /// The HTTP response stream ended unexpectedly (e.g. in the
43    /// middle of an event).
44    UnexpectedEof,
45    /// Encountered a line not conforming to the SSE protocol.
46    InvalidLine(String),
47    InvalidEvent,
48    /// Encountered a malformed Location header.
49    MalformedLocationHeader(Box<dyn std::error::Error + Send + Sync + 'static>),
50    /// Reached maximum redirect limit after encountering Location headers.
51    MaxRedirectLimitReached(u32),
52}
53
54impl std::fmt::Display for Error {
55    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56        use Error::*;
57        match self {
58            TimedOut => write!(f, "timed out"),
59            StreamClosed => write!(f, "stream closed"),
60            InvalidParameter(err) => write!(f, "invalid parameter: {err}"),
61            UnexpectedResponse(r, _) => {
62                let status = r.status();
63                write!(f, "unexpected response: {status}")
64            }
65            HttpStream(err) => write!(f, "http error: {err}"),
66            Eof => write!(f, "eof"),
67            UnexpectedEof => write!(f, "unexpected eof"),
68            InvalidLine(line) => write!(f, "invalid line: {line}"),
69            InvalidEvent => write!(f, "invalid event"),
70            MalformedLocationHeader(err) => write!(f, "malformed header: {err}"),
71            MaxRedirectLimitReached(limit) => write!(f, "maximum redirect limit reached: {limit}"),
72        }
73    }
74}
75
76impl std::error::Error for Error {}
77
78impl PartialEq<Error> for Error {
79    fn eq(&self, other: &Error) -> bool {
80        use Error::*;
81        if let (InvalidLine(msg1), InvalidLine(msg2)) = (self, other) {
82            return msg1 == msg2;
83        } else if let (UnexpectedEof, UnexpectedEof) = (self, other) {
84            return true;
85        }
86        false
87    }
88}
89
90impl Error {
91    pub fn is_http_stream_error(&self) -> bool {
92        if let Error::HttpStream(_) = self {
93            return true;
94        }
95        false
96    }
97
98    pub fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
99        match self {
100            Error::HttpStream(err) => Some(err.as_ref()),
101            _ => None,
102        }
103    }
104}
105
106pub type Result<T> = std::result::Result<T, Error>;