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};
24
25pub type Result<T, E = Error> = std::result::Result<T, E>;
29
30#[derive(Debug, Display, Error)]
32#[display("Blocking thread pool is shut down unexpectedly")]
33#[non_exhaustive]
34pub struct BlockingError;
35
36impl ResponseError for crate::error::BlockingError {}
37
38#[derive(Debug, PartialEq, Eq, Display, Error, From)]
40#[non_exhaustive]
41pub enum UrlGenerationError {
42 #[display("Resource not found")]
44 ResourceNotFound,
45
46 #[display("Not all URL parameters covered")]
48 NotEnoughElements,
49
50 #[display("{}", _0)]
52 ParseError(UrlParseError),
53}
54
55impl ResponseError for UrlGenerationError {}
56
57#[derive(Debug, Display, Error, From)]
59#[non_exhaustive]
60pub enum UrlencodedError {
61 #[display("Can not decode chunked transfer encoding.")]
63 Chunked,
64
65 #[display(
67 "URL encoded payload is larger ({} bytes) than allowed (limit: {} bytes).",
68 size,
69 limit
70 )]
71 Overflow { size: usize, limit: usize },
72
73 #[display("Payload size is now known.")]
75 UnknownLength,
76
77 #[display("Content type error.")]
79 ContentType,
80
81 #[display("Parse error: {}.", _0)]
83 Parse(FormDeError),
84
85 #[display("Encoding error.")]
87 Encoding,
88
89 #[display("Serialize error: {}.", _0)]
91 Serialize(FormError),
92
93 #[display("Error that occur during reading payload: {}.", _0)]
95 Payload(PayloadError),
96}
97
98impl ResponseError for UrlencodedError {
99 fn status_code(&self) -> StatusCode {
100 match self {
101 Self::Overflow { .. } => StatusCode::PAYLOAD_TOO_LARGE,
102 Self::UnknownLength => StatusCode::LENGTH_REQUIRED,
103 Self::ContentType => StatusCode::UNSUPPORTED_MEDIA_TYPE,
104 Self::Payload(err) => err.status_code(),
105 _ => StatusCode::BAD_REQUEST,
106 }
107 }
108}
109
110#[derive(Debug, Display, Error)]
112#[non_exhaustive]
113pub enum JsonPayloadError {
114 #[display(
116 "JSON payload ({} bytes) is larger than allowed (limit: {} bytes).",
117 length,
118 limit
119 )]
120 OverflowKnownLength { length: usize, limit: usize },
121
122 #[display("JSON payload has exceeded limit ({} bytes).", limit)]
124 Overflow { limit: usize },
125
126 #[display("Content type error")]
128 ContentType,
129
130 #[display("Json deserialize error: {}", _0)]
132 Deserialize(JsonError),
133
134 #[display("Json serialize error: {}", _0)]
136 Serialize(JsonError),
137
138 #[display("Error that occur during reading payload: {}", _0)]
140 Payload(PayloadError),
141}
142
143impl From<PayloadError> for JsonPayloadError {
144 fn from(err: PayloadError) -> Self {
145 Self::Payload(err)
146 }
147}
148
149impl ResponseError for JsonPayloadError {
150 fn status_code(&self) -> StatusCode {
151 match self {
152 Self::OverflowKnownLength {
153 length: _,
154 limit: _,
155 } => StatusCode::PAYLOAD_TOO_LARGE,
156 Self::Overflow { limit: _ } => StatusCode::PAYLOAD_TOO_LARGE,
157 Self::Serialize(_) => StatusCode::INTERNAL_SERVER_ERROR,
158 Self::Payload(err) => err.status_code(),
159 _ => StatusCode::BAD_REQUEST,
160 }
161 }
162}
163
164#[derive(Debug, Display, Error)]
166#[non_exhaustive]
167pub enum PathError {
168 #[display("Path deserialize error: {}", _0)]
170 Deserialize(serde::de::value::Error),
171}
172
173impl ResponseError for PathError {
175 fn status_code(&self) -> StatusCode {
176 StatusCode::BAD_REQUEST
177 }
178}
179
180#[derive(Debug, Display, Error, From)]
182#[non_exhaustive]
183pub enum QueryPayloadError {
184 #[display("Query deserialize error: {}", _0)]
186 Deserialize(serde::de::value::Error),
187}
188
189impl ResponseError for QueryPayloadError {
190 fn status_code(&self) -> StatusCode {
191 StatusCode::BAD_REQUEST
192 }
193}
194
195#[derive(Debug, Display, Error, From)]
197#[non_exhaustive]
198pub enum ReadlinesError {
199 #[display("Encoding error")]
200 EncodingError,
202
203 #[display("Error that occur during reading payload: {}", _0)]
205 Payload(PayloadError),
206
207 #[display("Line limit exceeded")]
209 LimitOverflow,
210
211 #[display("Content-type error")]
213 ContentTypeError(ContentTypeError),
214}
215
216impl ResponseError for ReadlinesError {
217 fn status_code(&self) -> StatusCode {
218 match *self {
219 ReadlinesError::LimitOverflow => StatusCode::PAYLOAD_TOO_LARGE,
220 _ => StatusCode::BAD_REQUEST,
221 }
222 }
223}
224
225#[cfg(test)]
226mod tests {
227 use super::*;
228
229 #[test]
230 fn test_urlencoded_error() {
231 let resp = UrlencodedError::Overflow { size: 0, limit: 0 }.error_response();
232 assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
233 let resp = UrlencodedError::UnknownLength.error_response();
234 assert_eq!(resp.status(), StatusCode::LENGTH_REQUIRED);
235 let resp = UrlencodedError::ContentType.error_response();
236 assert_eq!(resp.status(), StatusCode::UNSUPPORTED_MEDIA_TYPE);
237 }
238
239 #[test]
240 fn test_json_payload_error() {
241 let resp = JsonPayloadError::OverflowKnownLength {
242 length: 0,
243 limit: 0,
244 }
245 .error_response();
246 assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
247 let resp = JsonPayloadError::Overflow { limit: 0 }.error_response();
248 assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
249 let resp = JsonPayloadError::ContentType.error_response();
250 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
251 }
252
253 #[test]
254 fn test_query_payload_error() {
255 let resp = QueryPayloadError::Deserialize(
256 serde_urlencoded::from_str::<i32>("bad query").unwrap_err(),
257 )
258 .error_response();
259 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
260 }
261
262 #[test]
263 fn test_readlines_error() {
264 let resp = ReadlinesError::LimitOverflow.error_response();
265 assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
266 let resp = ReadlinesError::EncodingError.error_response();
267 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
268 }
269}