Skip to main content

eventsource_client/
error.rs

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