pub use actix_http::error::*;
use derive_more::{Display, From};
use serde_json::error::Error as JsonError;
use url::ParseError as UrlParseError;
use crate::http::StatusCode;
use crate::HttpResponse;
#[derive(Debug, PartialEq, Display, From)]
pub enum UrlGenerationError {
#[display(fmt = "Resource not found")]
ResourceNotFound,
#[display(fmt = "Not all path pattern covered")]
NotEnoughElements,
#[display(fmt = "{}", _0)]
ParseError(UrlParseError),
}
impl std::error::Error for UrlGenerationError {}
impl ResponseError for UrlGenerationError {}
#[derive(Debug, Display, From)]
pub enum UrlencodedError {
#[display(fmt = "Can not decode chunked transfer encoding")]
Chunked,
#[display(
fmt = "Urlencoded payload size is bigger ({} bytes) than allowed (default: {} bytes)",
size,
limit
)]
Overflow { size: usize, limit: usize },
#[display(fmt = "Payload size is now known")]
UnknownLength,
#[display(fmt = "Content type error")]
ContentType,
#[display(fmt = "Parse error")]
Parse,
#[display(fmt = "Error that occur during reading payload: {}", _0)]
Payload(PayloadError),
}
impl std::error::Error for UrlencodedError {}
impl ResponseError for UrlencodedError {
fn status_code(&self) -> StatusCode {
match *self {
UrlencodedError::Overflow { .. } => StatusCode::PAYLOAD_TOO_LARGE,
UrlencodedError::UnknownLength => StatusCode::LENGTH_REQUIRED,
_ => StatusCode::BAD_REQUEST,
}
}
}
#[derive(Debug, Display, From)]
pub enum JsonPayloadError {
#[display(fmt = "Json payload size is bigger than allowed")]
Overflow,
#[display(fmt = "Content type error")]
ContentType,
#[display(fmt = "Json deserialize error: {}", _0)]
Deserialize(JsonError),
#[display(fmt = "Error that occur during reading payload: {}", _0)]
Payload(PayloadError),
}
impl std::error::Error for JsonPayloadError {}
impl ResponseError for JsonPayloadError {
fn error_response(&self) -> HttpResponse {
match *self {
JsonPayloadError::Overflow => {
HttpResponse::new(StatusCode::PAYLOAD_TOO_LARGE)
}
_ => HttpResponse::new(StatusCode::BAD_REQUEST),
}
}
}
#[derive(Debug, Display, From)]
pub enum PathError {
#[display(fmt = "Path deserialize error: {}", _0)]
Deserialize(serde::de::value::Error),
}
impl std::error::Error for PathError {}
impl ResponseError for PathError {
fn status_code(&self) -> StatusCode {
StatusCode::BAD_REQUEST
}
}
#[derive(Debug, Display, From)]
pub enum QueryPayloadError {
#[display(fmt = "Query deserialize error: {}", _0)]
Deserialize(serde::de::value::Error),
}
impl std::error::Error for QueryPayloadError {}
impl ResponseError for QueryPayloadError {
fn status_code(&self) -> StatusCode {
StatusCode::BAD_REQUEST
}
}
#[derive(From, Display, Debug)]
pub enum ReadlinesError {
#[display(fmt = "Encoding error")]
EncodingError,
#[display(fmt = "Error that occur during reading payload: {}", _0)]
Payload(PayloadError),
#[display(fmt = "Line limit exceeded")]
LimitOverflow,
#[display(fmt = "Content-type error")]
ContentTypeError(ContentTypeError),
}
impl std::error::Error for ReadlinesError {}
impl ResponseError for ReadlinesError {
fn status_code(&self) -> StatusCode {
match *self {
ReadlinesError::LimitOverflow => StatusCode::PAYLOAD_TOO_LARGE,
_ => StatusCode::BAD_REQUEST,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_urlencoded_error() {
let resp: HttpResponse =
UrlencodedError::Overflow { size: 0, limit: 0 }.error_response();
assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
let resp: HttpResponse = UrlencodedError::UnknownLength.error_response();
assert_eq!(resp.status(), StatusCode::LENGTH_REQUIRED);
let resp: HttpResponse = UrlencodedError::ContentType.error_response();
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
}
#[test]
fn test_json_payload_error() {
let resp: HttpResponse = JsonPayloadError::Overflow.error_response();
assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
let resp: HttpResponse = JsonPayloadError::ContentType.error_response();
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
}
#[test]
fn test_query_payload_error() {
let resp: HttpResponse = QueryPayloadError::Deserialize(
serde_urlencoded::from_str::<i32>("bad query").unwrap_err(),
)
.error_response();
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
}
#[test]
fn test_readlines_error() {
let resp: HttpResponse = ReadlinesError::LimitOverflow.error_response();
assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE);
let resp: HttpResponse = ReadlinesError::EncodingError.error_response();
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
}
}