2019-03-09 22:06:24 +00:00
|
|
|
//! Error and Result module
|
2021-12-11 16:05:08 +00:00
|
|
|
|
2021-12-08 06:01:11 +00:00
|
|
|
// This is meant to be a glob import of the whole error module except for `Error`. Rustdoc can't yet
|
|
|
|
// correctly resolve the conflicting `Error` type defined in this module, so these re-exports are
|
|
|
|
// expanded manually.
|
|
|
|
//
|
|
|
|
// See <https://github.com/rust-lang/rust/issues/83375>
|
2023-07-17 01:38:12 +00:00
|
|
|
pub use actix_http::error::{ContentTypeError, DispatchError, HttpError, ParseError, PayloadError};
|
2021-01-09 13:17:19 +00:00
|
|
|
use derive_more::{Display, Error, From};
|
2019-03-17 07:48:40 +00:00
|
|
|
use serde_json::error::Error as JsonError;
|
2023-07-17 01:38:12 +00:00
|
|
|
use serde_urlencoded::{de::Error as FormDeError, ser::Error as FormError};
|
2019-03-09 15:39:34 +00:00
|
|
|
use url::ParseError as UrlParseError;
|
|
|
|
|
2021-04-09 17:07:10 +00:00
|
|
|
use crate::http::StatusCode;
|
2019-03-17 07:48:40 +00:00
|
|
|
|
2021-06-17 16:57:58 +00:00
|
|
|
#[allow(clippy::module_inception)]
|
|
|
|
mod error;
|
2021-05-14 15:40:00 +00:00
|
|
|
mod internal;
|
2021-06-17 16:57:58 +00:00
|
|
|
mod macros;
|
|
|
|
mod response_error;
|
2021-05-14 15:40:00 +00:00
|
|
|
|
2023-07-17 01:38:12 +00:00
|
|
|
pub(crate) use self::macros::{downcast_dyn, downcast_get_type_id};
|
|
|
|
pub use self::{error::Error, internal::*, response_error::ResponseError};
|
2021-05-14 15:40:00 +00:00
|
|
|
|
2021-05-09 19:12:48 +00:00
|
|
|
/// A convenience [`Result`](std::result::Result) for Actix Web operations.
|
|
|
|
///
|
|
|
|
/// This type alias is generally used to avoid writing out `actix_http::Error` directly.
|
2021-06-17 16:57:58 +00:00
|
|
|
pub type Result<T, E = Error> = std::result::Result<T, E>;
|
2021-05-09 19:12:48 +00:00
|
|
|
|
2022-02-22 08:45:28 +00:00
|
|
|
/// An error representing a problem running a blocking task on a thread pool.
|
|
|
|
#[derive(Debug, Display, Error)]
|
|
|
|
#[display(fmt = "Blocking thread pool is shut down unexpectedly")]
|
|
|
|
#[non_exhaustive]
|
|
|
|
pub struct BlockingError;
|
|
|
|
|
|
|
|
impl ResponseError for crate::error::BlockingError {}
|
|
|
|
|
2019-03-09 15:39:34 +00:00
|
|
|
/// Errors which can occur when attempting to generate resource uri.
|
2022-07-23 15:26:48 +00:00
|
|
|
#[derive(Debug, PartialEq, Eq, Display, Error, From)]
|
2021-04-12 09:30:28 +00:00
|
|
|
#[non_exhaustive]
|
2019-03-09 15:39:34 +00:00
|
|
|
pub enum UrlGenerationError {
|
2021-12-05 04:39:18 +00:00
|
|
|
/// Resource not found.
|
2019-03-09 15:39:34 +00:00
|
|
|
#[display(fmt = "Resource not found")]
|
|
|
|
ResourceNotFound,
|
2021-02-13 15:08:43 +00:00
|
|
|
|
2021-12-05 04:39:18 +00:00
|
|
|
/// Not all URL parameters covered.
|
|
|
|
#[display(fmt = "Not all URL parameters covered")]
|
2019-03-09 15:39:34 +00:00
|
|
|
NotEnoughElements,
|
2021-02-13 15:08:43 +00:00
|
|
|
|
2021-12-05 04:39:18 +00:00
|
|
|
/// URL parse error.
|
2019-03-09 15:39:34 +00:00
|
|
|
#[display(fmt = "{}", _0)]
|
|
|
|
ParseError(UrlParseError),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ResponseError for UrlGenerationError {}
|
2019-03-12 06:19:05 +00:00
|
|
|
|
2019-03-17 07:48:40 +00:00
|
|
|
/// A set of errors that can occur during parsing urlencoded payloads
|
2021-01-09 13:17:19 +00:00
|
|
|
#[derive(Debug, Display, Error, From)]
|
2021-04-12 09:30:28 +00:00
|
|
|
#[non_exhaustive]
|
2019-03-17 07:48:40 +00:00
|
|
|
pub enum UrlencodedError {
|
2021-01-09 13:17:19 +00:00
|
|
|
/// Can not decode chunked transfer encoding.
|
|
|
|
#[display(fmt = "Can not decode chunked transfer encoding.")]
|
2019-03-17 07:48:40 +00:00
|
|
|
Chunked,
|
2021-01-09 13:17:19 +00:00
|
|
|
|
|
|
|
/// Payload size is larger than allowed. (default limit: 256kB).
|
2019-09-17 00:58:04 +00:00
|
|
|
#[display(
|
2021-01-09 13:17:19 +00:00
|
|
|
fmt = "URL encoded payload is larger ({} bytes) than allowed (limit: {} bytes).",
|
2019-09-17 00:58:04 +00:00
|
|
|
size,
|
|
|
|
limit
|
|
|
|
)]
|
|
|
|
Overflow { size: usize, limit: usize },
|
2021-01-09 13:17:19 +00:00
|
|
|
|
|
|
|
/// Payload size is now known.
|
|
|
|
#[display(fmt = "Payload size is now known.")]
|
2019-03-17 07:48:40 +00:00
|
|
|
UnknownLength,
|
2021-01-09 13:17:19 +00:00
|
|
|
|
|
|
|
/// Content type error.
|
|
|
|
#[display(fmt = "Content type error.")]
|
2019-03-17 07:48:40 +00:00
|
|
|
ContentType,
|
2021-01-09 13:17:19 +00:00
|
|
|
|
|
|
|
/// Parse error.
|
2021-04-12 09:30:28 +00:00
|
|
|
#[display(fmt = "Parse error: {}.", _0)]
|
|
|
|
Parse(FormDeError),
|
|
|
|
|
|
|
|
/// Encoding error.
|
|
|
|
#[display(fmt = "Encoding error.")]
|
|
|
|
Encoding,
|
|
|
|
|
|
|
|
/// Serialize error.
|
|
|
|
#[display(fmt = "Serialize error: {}.", _0)]
|
|
|
|
Serialize(FormError),
|
2021-01-09 13:17:19 +00:00
|
|
|
|
|
|
|
/// Payload error.
|
|
|
|
#[display(fmt = "Error that occur during reading payload: {}.", _0)]
|
2019-03-17 07:48:40 +00:00
|
|
|
Payload(PayloadError),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ResponseError for UrlencodedError {
|
2019-11-26 10:07:39 +00:00
|
|
|
fn status_code(&self) -> StatusCode {
|
2021-04-12 09:30:28 +00:00
|
|
|
match self {
|
|
|
|
Self::Overflow { .. } => StatusCode::PAYLOAD_TOO_LARGE,
|
|
|
|
Self::UnknownLength => StatusCode::LENGTH_REQUIRED,
|
|
|
|
Self::Payload(err) => err.status_code(),
|
2019-11-26 10:07:39 +00:00
|
|
|
_ => StatusCode::BAD_REQUEST,
|
2019-03-17 07:48:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A set of errors that can occur during parsing json payloads
|
2021-04-12 09:30:28 +00:00
|
|
|
#[derive(Debug, Display, Error)]
|
|
|
|
#[non_exhaustive]
|
2019-03-17 07:48:40 +00:00
|
|
|
pub enum JsonPayloadError {
|
2021-06-16 14:52:49 +00:00
|
|
|
/// Payload size is bigger than allowed & content length header set. (default: 2MB)
|
|
|
|
#[display(
|
|
|
|
fmt = "JSON payload ({} bytes) is larger than allowed (limit: {} bytes).",
|
|
|
|
length,
|
|
|
|
limit
|
|
|
|
)]
|
|
|
|
OverflowKnownLength { length: usize, limit: usize },
|
|
|
|
|
|
|
|
/// Payload size is bigger than allowed but no content length header set. (default: 2MB)
|
|
|
|
#[display(fmt = "JSON payload has exceeded limit ({} bytes).", limit)]
|
|
|
|
Overflow { limit: usize },
|
2021-04-12 09:30:28 +00:00
|
|
|
|
2019-03-17 07:48:40 +00:00
|
|
|
/// Content type error
|
|
|
|
#[display(fmt = "Content type error")]
|
|
|
|
ContentType,
|
2021-04-12 09:30:28 +00:00
|
|
|
|
2019-03-17 07:48:40 +00:00
|
|
|
/// Deserialize error
|
|
|
|
#[display(fmt = "Json deserialize error: {}", _0)]
|
|
|
|
Deserialize(JsonError),
|
2021-04-12 09:30:28 +00:00
|
|
|
|
|
|
|
/// Serialize error
|
|
|
|
#[display(fmt = "Json serialize error: {}", _0)]
|
|
|
|
Serialize(JsonError),
|
|
|
|
|
2019-03-17 07:48:40 +00:00
|
|
|
/// Payload error
|
|
|
|
#[display(fmt = "Error that occur during reading payload: {}", _0)]
|
|
|
|
Payload(PayloadError),
|
|
|
|
}
|
|
|
|
|
2021-04-12 09:30:28 +00:00
|
|
|
impl From<PayloadError> for JsonPayloadError {
|
|
|
|
fn from(err: PayloadError) -> Self {
|
|
|
|
Self::Payload(err)
|
|
|
|
}
|
|
|
|
}
|
2020-03-18 01:51:06 +00:00
|
|
|
|
2019-03-17 07:48:40 +00:00
|
|
|
impl ResponseError for JsonPayloadError {
|
2021-04-09 17:07:10 +00:00
|
|
|
fn status_code(&self) -> StatusCode {
|
2021-04-12 09:30:28 +00:00
|
|
|
match self {
|
2021-06-16 14:52:49 +00:00
|
|
|
Self::OverflowKnownLength {
|
|
|
|
length: _,
|
|
|
|
limit: _,
|
|
|
|
} => StatusCode::PAYLOAD_TOO_LARGE,
|
|
|
|
Self::Overflow { limit: _ } => StatusCode::PAYLOAD_TOO_LARGE,
|
2021-04-12 09:30:28 +00:00
|
|
|
Self::Serialize(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
Self::Payload(err) => err.status_code(),
|
2021-04-09 17:07:10 +00:00
|
|
|
_ => StatusCode::BAD_REQUEST,
|
2019-03-17 07:48:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-12 10:49:56 +00:00
|
|
|
/// A set of errors that can occur during parsing request paths
|
2021-04-12 09:30:28 +00:00
|
|
|
#[derive(Debug, Display, Error)]
|
|
|
|
#[non_exhaustive]
|
2019-06-12 11:02:45 +00:00
|
|
|
pub enum PathError {
|
2019-06-12 10:49:56 +00:00
|
|
|
/// Deserialize error
|
|
|
|
#[display(fmt = "Path deserialize error: {}", _0)]
|
2019-12-18 03:30:14 +00:00
|
|
|
Deserialize(serde::de::value::Error),
|
2019-06-12 10:49:56 +00:00
|
|
|
}
|
|
|
|
|
2019-06-12 11:02:45 +00:00
|
|
|
/// Return `BadRequest` for `PathError`
|
|
|
|
impl ResponseError for PathError {
|
2019-11-26 10:07:39 +00:00
|
|
|
fn status_code(&self) -> StatusCode {
|
|
|
|
StatusCode::BAD_REQUEST
|
2019-06-12 10:49:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-09 13:17:19 +00:00
|
|
|
/// A set of errors that can occur during parsing query strings.
|
|
|
|
#[derive(Debug, Display, Error, From)]
|
2021-04-12 09:30:28 +00:00
|
|
|
#[non_exhaustive]
|
2019-05-14 20:54:30 +00:00
|
|
|
pub enum QueryPayloadError {
|
2021-01-09 13:17:19 +00:00
|
|
|
/// Query deserialize error.
|
2019-05-14 20:54:30 +00:00
|
|
|
#[display(fmt = "Query deserialize error: {}", _0)]
|
2019-12-18 03:30:14 +00:00
|
|
|
Deserialize(serde::de::value::Error),
|
2019-05-14 20:54:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ResponseError for QueryPayloadError {
|
2019-11-26 10:07:39 +00:00
|
|
|
fn status_code(&self) -> StatusCode {
|
|
|
|
StatusCode::BAD_REQUEST
|
2019-05-14 20:54:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-17 07:48:40 +00:00
|
|
|
/// Error type returned when reading body as lines.
|
2021-04-12 09:30:28 +00:00
|
|
|
#[derive(Debug, Display, Error, From)]
|
|
|
|
#[non_exhaustive]
|
2019-03-17 07:48:40 +00:00
|
|
|
pub enum ReadlinesError {
|
|
|
|
#[display(fmt = "Encoding error")]
|
|
|
|
/// Payload size is bigger than allowed. (default: 256kB)
|
|
|
|
EncodingError,
|
2021-04-12 09:30:28 +00:00
|
|
|
|
2019-03-17 07:48:40 +00:00
|
|
|
/// Payload error.
|
|
|
|
#[display(fmt = "Error that occur during reading payload: {}", _0)]
|
|
|
|
Payload(PayloadError),
|
2021-04-12 09:30:28 +00:00
|
|
|
|
2019-03-17 07:48:40 +00:00
|
|
|
/// Line limit exceeded.
|
|
|
|
#[display(fmt = "Line limit exceeded")]
|
|
|
|
LimitOverflow,
|
2021-04-12 09:30:28 +00:00
|
|
|
|
2019-03-17 07:48:40 +00:00
|
|
|
/// ContentType error.
|
|
|
|
#[display(fmt = "Content-type error")]
|
|
|
|
ContentTypeError(ContentTypeError),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ResponseError for ReadlinesError {
|
2019-11-26 10:07:39 +00:00
|
|
|
fn status_code(&self) -> StatusCode {
|
2019-03-17 07:48:40 +00:00
|
|
|
match *self {
|
2019-11-26 10:07:39 +00:00
|
|
|
ReadlinesError::LimitOverflow => StatusCode::PAYLOAD_TOO_LARGE,
|
|
|
|
_ => StatusCode::BAD_REQUEST,
|
2019-03-17 07:48:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-03-17 17:11:10 +00:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_urlencoded_error() {
|
2021-04-09 17:07:10 +00:00
|
|
|
let resp = UrlencodedError::Overflow { size: 0, limit: 0 }.error_response();
|
2019-03-17 17:11:10 +00:00
|
|
|
assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
|
2021-04-09 17:07:10 +00:00
|
|
|
let resp = UrlencodedError::UnknownLength.error_response();
|
2019-03-17 17:11:10 +00:00
|
|
|
assert_eq!(resp.status(), StatusCode::LENGTH_REQUIRED);
|
2021-04-09 17:07:10 +00:00
|
|
|
let resp = UrlencodedError::ContentType.error_response();
|
2019-03-17 17:11:10 +00:00
|
|
|
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_json_payload_error() {
|
2021-06-16 14:52:49 +00:00
|
|
|
let resp = JsonPayloadError::OverflowKnownLength {
|
|
|
|
length: 0,
|
|
|
|
limit: 0,
|
|
|
|
}
|
|
|
|
.error_response();
|
|
|
|
assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
|
|
|
|
let resp = JsonPayloadError::Overflow { limit: 0 }.error_response();
|
2019-03-17 17:11:10 +00:00
|
|
|
assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
|
2021-04-09 17:07:10 +00:00
|
|
|
let resp = JsonPayloadError::ContentType.error_response();
|
2019-03-17 17:11:10 +00:00
|
|
|
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
|
|
|
}
|
|
|
|
|
2019-05-14 20:54:30 +00:00
|
|
|
#[test]
|
|
|
|
fn test_query_payload_error() {
|
2021-04-09 17:07:10 +00:00
|
|
|
let resp = QueryPayloadError::Deserialize(
|
2019-05-15 17:31:40 +00:00
|
|
|
serde_urlencoded::from_str::<i32>("bad query").unwrap_err(),
|
|
|
|
)
|
|
|
|
.error_response();
|
2019-05-14 20:54:30 +00:00
|
|
|
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
|
|
|
}
|
|
|
|
|
2019-03-17 17:11:10 +00:00
|
|
|
#[test]
|
|
|
|
fn test_readlines_error() {
|
2021-04-09 17:07:10 +00:00
|
|
|
let resp = ReadlinesError::LimitOverflow.error_response();
|
2019-03-17 17:11:10 +00:00
|
|
|
assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
|
2021-04-09 17:07:10 +00:00
|
|
|
let resp = ReadlinesError::EncodingError.error_response();
|
2019-03-17 17:11:10 +00:00
|
|
|
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
|
|
|
}
|
|
|
|
}
|