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("Payload size is now known.")]
76 UnknownLength,
77
78 #[display("Content type error.")]
80 ContentType,
81
82 #[display("Parse error: {}.", _0)]
84 Parse(FormDeError),
85
86 #[display("Encoding error.")]
88 Encoding,
89
90 #[display("Serialize error: {}.", _0)]
92 Serialize(FormError),
93
94 #[display("Error that occur during reading payload: {}.", _0)]
96 Payload(PayloadError),
97}
98
99impl ResponseError for UrlencodedError {
100 fn status_code(&self) -> StatusCode {
101 match self {
102 Self::Overflow { .. } => StatusCode::PAYLOAD_TOO_LARGE,
103 Self::UnknownLength => StatusCode::LENGTH_REQUIRED,
104 Self::ContentType => StatusCode::UNSUPPORTED_MEDIA_TYPE,
105 Self::Payload(err) => err.status_code(),
106 _ => StatusCode::BAD_REQUEST,
107 }
108 }
109}
110
111#[derive(Debug, Display, Error)]
113#[non_exhaustive]
114pub enum JsonPayloadError {
115 #[display(
117 "JSON payload ({} bytes) is larger than allowed (limit: {} bytes).",
118 length,
119 limit
120 )]
121 OverflowKnownLength { length: usize, limit: usize },
122
123 #[display("JSON payload has exceeded limit ({} bytes).", limit)]
125 Overflow { limit: usize },
126
127 #[display("Content type error")]
129 ContentType,
130
131 #[display("Json deserialize error: {}", _0)]
133 Deserialize(JsonError),
134
135 #[display("Json serialize error: {}", _0)]
137 Serialize(JsonError),
138
139 #[display("Error that occur during reading payload: {}", _0)]
141 Payload(PayloadError),
142}
143
144impl From<PayloadError> for JsonPayloadError {
145 fn from(err: PayloadError) -> Self {
146 Self::Payload(err)
147 }
148}
149
150impl ResponseError for JsonPayloadError {
151 fn status_code(&self) -> StatusCode {
152 match self {
153 Self::OverflowKnownLength {
154 length: _,
155 limit: _,
156 } => StatusCode::PAYLOAD_TOO_LARGE,
157 Self::Overflow { limit: _ } => StatusCode::PAYLOAD_TOO_LARGE,
158 Self::Serialize(_) => StatusCode::INTERNAL_SERVER_ERROR,
159 Self::Payload(err) => err.status_code(),
160 _ => StatusCode::BAD_REQUEST,
161 }
162 }
163}
164
165#[derive(Debug, Display, Error)]
167#[non_exhaustive]
168pub enum PathError {
169 #[display("Path deserialize error: {}", _0)]
171 Deserialize(serde::de::value::Error),
172}
173
174impl ResponseError for PathError {
176 fn status_code(&self) -> StatusCode {
177 StatusCode::BAD_REQUEST
178 }
179}
180
181#[derive(Debug, Display, Error, From)]
183#[non_exhaustive]
184pub enum QueryPayloadError {
185 #[display("Query deserialize error: {}", _0)]
187 Deserialize(serde::de::value::Error),
188}
189
190impl ResponseError for QueryPayloadError {
191 fn status_code(&self) -> StatusCode {
192 StatusCode::BAD_REQUEST
193 }
194}
195
196#[derive(Debug, Display, Error, From)]
198#[non_exhaustive]
199pub enum ReadlinesError {
200 #[display("Encoding error")]
201 EncodingError,
203
204 #[display("Error that occur during reading payload: {}", _0)]
206 Payload(PayloadError),
207
208 #[display("Line limit exceeded")]
210 LimitOverflow,
211
212 #[display("Content-type error")]
214 ContentTypeError(ContentTypeError),
215}
216
217impl ResponseError for ReadlinesError {
218 fn status_code(&self) -> StatusCode {
219 match *self {
220 ReadlinesError::LimitOverflow => StatusCode::PAYLOAD_TOO_LARGE,
221 _ => StatusCode::BAD_REQUEST,
222 }
223 }
224}
225
226#[cfg(test)]
227mod tests {
228 use super::*;
229
230 #[test]
231 fn test_urlencoded_error() {
232 let resp = UrlencodedError::Overflow { size: 0, limit: 0 }.error_response();
233 assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
234 let resp = UrlencodedError::UnknownLength.error_response();
235 assert_eq!(resp.status(), StatusCode::LENGTH_REQUIRED);
236 let resp = UrlencodedError::ContentType.error_response();
237 assert_eq!(resp.status(), StatusCode::UNSUPPORTED_MEDIA_TYPE);
238 }
239
240 #[test]
241 fn test_json_payload_error() {
242 let resp = JsonPayloadError::OverflowKnownLength {
243 length: 0,
244 limit: 0,
245 }
246 .error_response();
247 assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
248 let resp = JsonPayloadError::Overflow { limit: 0 }.error_response();
249 assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
250 let resp = JsonPayloadError::ContentType.error_response();
251 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
252 }
253
254 #[test]
255 fn test_query_payload_error() {
256 let resp = QueryPayloadError::Deserialize(
257 serde_urlencoded::from_str::<i32>("bad query").unwrap_err(),
258 )
259 .error_response();
260 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
261 }
262
263 #[test]
264 fn test_readlines_error() {
265 let resp = ReadlinesError::LimitOverflow.error_response();
266 assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
267 let resp = ReadlinesError::EncodingError.error_response();
268 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
269 }
270}