multer/
error.rs

1use std::fmt::{self, Debug, Display, Formatter};
2
3type BoxError = Box<dyn std::error::Error + Send + Sync>;
4
5/// A set of errors that can occur during parsing multipart stream and in other
6/// operations.
7#[non_exhaustive]
8pub enum Error {
9    /// An unknown field is detected when multipart
10    /// [`constraints`](crate::Constraints::allowed_fields) are added.
11    UnknownField { field_name: Option<String> },
12
13    /// The field data is found incomplete.
14    IncompleteFieldData { field_name: Option<String> },
15
16    /// Couldn't read the field headers completely.
17    IncompleteHeaders,
18
19    /// Failed to read headers.
20    ReadHeaderFailed(httparse::Error),
21
22    /// Failed to decode the field's raw header name to
23    /// [`HeaderName`](http::header::HeaderName) type.
24    DecodeHeaderName { name: String, cause: BoxError },
25
26    /// Failed to decode the field's raw header value to
27    /// [`HeaderValue`](http::header::HeaderValue) type.
28    DecodeHeaderValue { value: Vec<u8>, cause: BoxError },
29
30    /// Multipart stream is incomplete.
31    IncompleteStream,
32
33    /// The incoming field size exceeded the maximum limit.
34    FieldSizeExceeded { limit: u64, field_name: Option<String> },
35
36    /// The incoming stream size exceeded the maximum limit.
37    StreamSizeExceeded { limit: u64 },
38
39    /// Stream read failed.
40    StreamReadFailed(BoxError),
41
42    /// Failed to lock the multipart shared state for any changes.
43    LockFailure,
44
45    /// The `Content-Type` header is not `multipart/form-data`.
46    NoMultipart,
47
48    /// Failed to convert the `Content-Type` to [`mime::Mime`] type.
49    DecodeContentType(mime::FromStrError),
50
51    /// No boundary found in `Content-Type` header.
52    NoBoundary,
53
54    /// Failed to decode the field data as `JSON` in
55    /// [`field.json()`](crate::Field::json) method.
56    #[cfg(feature = "json")]
57    #[cfg_attr(nightly, doc(cfg(feature = "json")))]
58    DecodeJson(serde_json::Error),
59}
60
61impl Debug for Error {
62    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
63        Display::fmt(self, f)
64    }
65}
66
67impl Display for Error {
68    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
69        match self {
70            Error::UnknownField { field_name } => {
71                let name = field_name.as_deref().unwrap_or("<unknown>");
72                write!(f, "unknown field received: {:?}", name)
73            }
74            Error::IncompleteFieldData { field_name } => {
75                let name = field_name.as_deref().unwrap_or("<unknown>");
76                write!(f, "field {:?} received with incomplete data", name)
77            }
78            Error::DecodeHeaderName { name, .. } => {
79                write!(f, "failed to decode field's raw header name: {:?}", name)
80            }
81            Error::DecodeHeaderValue { .. } => {
82                write!(f, "failed to decode field's raw header value")
83            }
84            Error::FieldSizeExceeded { limit, field_name } => {
85                let name = field_name.as_deref().unwrap_or("<unknown>");
86                write!(f, "field {:?} exceeded the size limit: {} bytes", name, limit)
87            }
88            Error::StreamSizeExceeded { limit } => {
89                write!(f, "stream size exceeded limit: {} bytes", limit)
90            }
91            Error::ReadHeaderFailed(_) => write!(f, "failed to read headers"),
92            Error::StreamReadFailed(_) => write!(f, "failed to read stream"),
93            Error::DecodeContentType(_) => write!(f, "failed to decode Content-Type"),
94            Error::IncompleteHeaders => write!(f, "failed to read field complete headers"),
95            Error::IncompleteStream => write!(f, "incomplete multipart stream"),
96            Error::LockFailure => write!(f, "failed to lock multipart state"),
97            Error::NoMultipart => write!(f, "Content-Type is not multipart/form-data"),
98            Error::NoBoundary => write!(f, "multipart boundary not found in Content-Type"),
99            #[cfg(feature = "json")]
100            Error::DecodeJson(_) => write!(f, "failed to decode field data as JSON"),
101        }
102    }
103}
104
105impl std::error::Error for Error {
106    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
107        match self {
108            Error::ReadHeaderFailed(e) => Some(e),
109            Error::DecodeHeaderName { cause, .. } => Some(cause.as_ref()),
110            Error::DecodeHeaderValue { cause, .. } => Some(cause.as_ref()),
111            Error::StreamReadFailed(e) => Some(e.as_ref()),
112            Error::DecodeContentType(e) => Some(e),
113            #[cfg(feature = "json")]
114            Error::DecodeJson(e) => Some(e),
115            Error::UnknownField { .. }
116            | Error::IncompleteFieldData { .. }
117            | Error::IncompleteHeaders
118            | Error::IncompleteStream
119            | Error::FieldSizeExceeded { .. }
120            | Error::StreamSizeExceeded { .. }
121            | Error::LockFailure
122            | Error::NoMultipart
123            | Error::NoBoundary => None,
124        }
125    }
126}
127
128impl PartialEq for Error {
129    fn eq(&self, other: &Self) -> bool {
130        self.to_string().eq(&other.to_string())
131    }
132}
133
134impl Eq for Error {}