1pub use actix_http::error::{ContentTypeError, DispatchError, HttpError, ParseError, PayloadError};
9use derive_more::{Display, Error, From};
10use serde_json::error::Error as JsonError;
11use serde_urlencoded::{de::Error as FormDeError, ser::Error as FormError};
12use url::ParseError as UrlParseError;
13
14use crate::http::StatusCode;
15
16#[allow(clippy::module_inception)]
17mod error;
18mod internal;
19mod macros;
20mod response_error;
21
22pub(crate) use self::macros::{downcast_dyn, downcast_get_type_id};
23pub use self::{error::Error, internal::*, response_error::ResponseError};
24pub use crate::types::EitherExtractError;
25
26pub type Result<T, E = Error> = std::result::Result<T, E>;
30
31#[derive(Debug, Display, Error)]
33#[display("Blocking thread pool is shut down unexpectedly")]
34#[non_exhaustive]
35pub struct BlockingError;
36
37impl ResponseError for crate::error::BlockingError {}
38
39#[derive(Debug, PartialEq, Eq, Display, Error, From)]
41#[non_exhaustive]
42pub enum UrlGenerationError {
43 #[display("Resource not found")]
45 ResourceNotFound,
46
47 #[display("Not all URL parameters covered")]
49 NotEnoughElements,
50
51 #[display("{}", _0)]
53 ParseError(UrlParseError),
54}
55
56impl ResponseError for UrlGenerationError {}
57
58#[derive(Debug, Display, Error, From)]
60#[non_exhaustive]
61pub enum UrlencodedError {
62 #[display("Can not decode chunked transfer encoding.")]
64 Chunked,
65
66 #[display(
68 "URL encoded payload is larger ({} bytes) than allowed (limit: {} bytes).",
69 size,
70 limit
71 )]
72 Overflow { size: usize, limit: usize },
73
74 #[display("URL encoded payload is larger than allowed (limit: {} bytes)", limit)]
76 OverflowUnknownLength { limit: usize },
77
78 #[display("Payload size is now known.")]
80 UnknownLength,
81
82 #[display("Content type error.")]
84 ContentType,
85
86 #[display("Parse error: {}.", _0)]
88 Parse(FormDeError),
89
90 #[display("Encoding error.")]
92 Encoding,
93
94 #[display("Serialize error: {}.", _0)]
96 Serialize(FormError),
97
98 #[display("Error that occur during reading payload: {}.", _0)]
100 Payload(PayloadError),
101}
102
103impl ResponseError for UrlencodedError {
104 fn status_code(&self) -> StatusCode {
105 match self {
106 Self::Overflow { .. } | Self::OverflowUnknownLength { .. } => {
107 StatusCode::PAYLOAD_TOO_LARGE
108 }
109 Self::UnknownLength => StatusCode::LENGTH_REQUIRED,
110 Self::ContentType => StatusCode::UNSUPPORTED_MEDIA_TYPE,
111 Self::Payload(err) => err.status_code(),
112 _ => StatusCode::BAD_REQUEST,
113 }
114 }
115}
116
117#[derive(Debug, Display, Error)]
119#[non_exhaustive]
120pub enum JsonPayloadError {
121 #[display(
123 "JSON payload ({} bytes) is larger than allowed (limit: {} bytes).",
124 length,
125 limit
126 )]
127 OverflowKnownLength { length: usize, limit: usize },
128
129 #[display("JSON payload has exceeded limit ({} bytes).", limit)]
131 Overflow { limit: usize },
132
133 #[display("Content type error")]
135 ContentType,
136
137 #[display("Json deserialize error: {}", _0)]
139 Deserialize(JsonError),
140
141 #[display("Json serialize error: {}", _0)]
143 Serialize(JsonError),
144
145 #[display("Error that occur during reading payload: {}", _0)]
147 Payload(PayloadError),
148}
149
150impl From<PayloadError> for JsonPayloadError {
151 fn from(err: PayloadError) -> Self {
152 Self::Payload(err)
153 }
154}
155
156impl ResponseError for JsonPayloadError {
157 fn status_code(&self) -> StatusCode {
158 match self {
159 Self::OverflowKnownLength {
160 length: _,
161 limit: _,
162 } => StatusCode::PAYLOAD_TOO_LARGE,
163 Self::Overflow { limit: _ } => StatusCode::PAYLOAD_TOO_LARGE,
164 Self::Serialize(_) => StatusCode::INTERNAL_SERVER_ERROR,
165 Self::Payload(err) => err.status_code(),
166 _ => StatusCode::BAD_REQUEST,
167 }
168 }
169}
170
171#[derive(Debug, Display, Error)]
173#[non_exhaustive]
174pub enum PathError {
175 #[display("Path deserialize error: {}", _0)]
177 Deserialize(serde::de::value::Error),
178}
179
180impl ResponseError for PathError {
182 fn status_code(&self) -> StatusCode {
183 StatusCode::BAD_REQUEST
184 }
185}
186
187#[derive(Debug, Display, Error, From)]
189#[non_exhaustive]
190pub enum QueryPayloadError {
191 #[display("Query deserialize error: {}", _0)]
193 Deserialize(serde::de::value::Error),
194}
195
196impl ResponseError for QueryPayloadError {
197 fn status_code(&self) -> StatusCode {
198 StatusCode::BAD_REQUEST
199 }
200}
201
202#[derive(Debug, Display, Error, From)]
204#[non_exhaustive]
205pub enum ReadlinesError {
206 #[display("Encoding error")]
207 EncodingError,
209
210 #[display("Error that occur during reading payload: {}", _0)]
212 Payload(PayloadError),
213
214 #[display("Line limit exceeded")]
216 LimitOverflow,
217
218 #[display("Content-type error")]
220 ContentTypeError(ContentTypeError),
221}
222
223impl ResponseError for ReadlinesError {
224 fn status_code(&self) -> StatusCode {
225 match *self {
226 ReadlinesError::LimitOverflow => StatusCode::PAYLOAD_TOO_LARGE,
227 _ => StatusCode::BAD_REQUEST,
228 }
229 }
230}
231
232#[cfg(test)]
233mod tests {
234 use super::*;
235
236 #[test]
237 fn test_urlencoded_error() {
238 let resp = UrlencodedError::Overflow { size: 0, limit: 0 }.error_response();
239 assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
240 let resp = UrlencodedError::UnknownLength.error_response();
241 assert_eq!(resp.status(), StatusCode::LENGTH_REQUIRED);
242 let resp = UrlencodedError::ContentType.error_response();
243 assert_eq!(resp.status(), StatusCode::UNSUPPORTED_MEDIA_TYPE);
244 }
245
246 #[test]
247 fn test_json_payload_error() {
248 let resp = JsonPayloadError::OverflowKnownLength {
249 length: 0,
250 limit: 0,
251 }
252 .error_response();
253 assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
254 let resp = JsonPayloadError::Overflow { limit: 0 }.error_response();
255 assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
256 let resp = JsonPayloadError::ContentType.error_response();
257 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
258 }
259
260 #[test]
261 fn test_query_payload_error() {
262 let resp = QueryPayloadError::Deserialize(
263 serde_urlencoded::from_str::<i32>("bad query").unwrap_err(),
264 )
265 .error_response();
266 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
267 }
268
269 #[test]
270 fn test_readlines_error() {
271 let resp = ReadlinesError::LimitOverflow.error_response();
272 assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
273 let resp = ReadlinesError::EncodingError.error_response();
274 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
275 }
276}