Skip to main content

reqwest_streams/
error.rs

1//! Error types for streaming responses.
2
3use std::fmt;
4
5type BoxedError = Box<dyn std::error::Error + Send + Sync>;
6
7/// The error that may occur when attempting to stream a [`reqwest::Response`].
8pub struct StreamBodyError {
9    kind: StreamBodyKind,
10    source: Option<BoxedError>,
11    message: Option<String>,
12}
13
14impl StreamBodyError {
15    /// Create a new instance of an error.
16    pub fn new(kind: StreamBodyKind, source: Option<BoxedError>, message: Option<String>) -> Self {
17        Self {
18            kind,
19            source,
20            message,
21        }
22    }
23
24    /// The kind of error that occurred during streaming.
25    pub fn kind(&self) -> StreamBodyKind {
26        self.kind
27    }
28
29    /// The actual error that occurred.
30    pub fn source(&self) -> Option<&BoxedError> {
31        self.source.as_ref()
32    }
33
34    /// The message associated with the error.
35    pub fn message(&self) -> Option<&str> {
36        self.message.as_deref()
37    }
38}
39
40/// The kind of error that occurred during streaming.
41#[derive(Clone, Copy, Debug)]
42pub enum StreamBodyKind {
43    /// An error occured while decoding a frame or format.
44    CodecError,
45
46    /// An error occured while reading the stream.
47    InputOutputError,
48
49    /// The maximum object length was exceeded.
50    MaxLenReachedError,
51}
52
53impl StreamBodyKind {
54    /// A short, stable name for this kind, reported as the `error_kind` tracing field so that
55    /// errors can be aggregated without parsing their [`Display`] output.
56    ///
57    /// [`Display`]: fmt::Display
58    pub fn as_str(&self) -> &'static str {
59        match self {
60            StreamBodyKind::CodecError => "codec",
61            StreamBodyKind::InputOutputError => "io",
62            StreamBodyKind::MaxLenReachedError => "max_len",
63        }
64    }
65}
66
67impl fmt::Debug for StreamBodyError {
68    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
69        let mut builder = f.debug_struct("reqwest::Error");
70
71        builder.field("kind", &self.kind);
72
73        if let Some(ref source) = self.source {
74            builder.field("source", source);
75        }
76
77        if let Some(ref message) = self.message {
78            builder.field("message", message);
79        }
80
81        builder.finish()
82    }
83}
84
85impl fmt::Display for StreamBodyError {
86    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
87        match self.kind {
88            StreamBodyKind::CodecError => f.write_str("Frame/codec error")?,
89            StreamBodyKind::InputOutputError => f.write_str("I/O error")?,
90            StreamBodyKind::MaxLenReachedError => f.write_str("Max object length reached")?,
91        };
92
93        if let Some(message) = &self.message {
94            write!(f, ": {}", message)?;
95        }
96
97        if let Some(e) = &self.source {
98            write!(f, ": {}", e)?;
99        }
100
101        Ok(())
102    }
103}
104
105impl std::error::Error for StreamBodyError {}
106
107impl From<std::io::Error> for StreamBodyError {
108    fn from(err: std::io::Error) -> Self {
109        StreamBodyError::new(StreamBodyKind::InputOutputError, Some(Box::new(err)), None)
110    }
111}