2 unstable releases

0.2.0 May 5, 2023
0.1.0 Aug 15, 2022

#1601 in Web programming

50 downloads per month

MIT/Apache

11KB
71 lines

actix-web-error

Error responses for actix-web made easy. This crate will make it easy implementing actix_web::ResponseError for errors by providing a thiserror-like API for specifying an HTTP status. It's best used in combination with thiserror.

Currently, only a JSON response is supported.

Thanks to the aforementioned thiserror project, I used the core structure and core utilities.

Error Responses

  • Json will respond with JSON in the form of { "error": <Display representation> } (application/json).
  • Text will respond with the Display representation of the error (text/plain).

Example

#[derive(Debug, thiserror::Error, actix_web_error::Json)]
#[status(BAD_REQUEST)] // default status for all variants
enum MyError {
    #[error("Missing: {0}")]
    MissingField(&'static str),
    #[error("Malformed Date")]
    MalformedDate,
    #[error("Internal Server Error")]
    #[status(500)] // specific override
    Internal,
}

#[derive(Debug, thiserror::Error, actix_web_error::Text)]
#[error("Item not found")]
#[status(404)]
struct MyOtherError;

This will roughly expand to:

use actix_web::{ResponseError, HttpResponse, HttpResponseBuilder, http::StatusCode};

#[derive(Debug, thiserror::Error)]
enum MyError {
    #[error("Missing: {0}")]
    MissingField(&'static str),
    #[error("Malformed Date")]
    MalformedDate,
    #[error("Internal Server Error")]
    Internal,
}

#[derive(Debug, thiserror::Error)]
#[error("Item not found")]
struct MyOtherError;

impl ResponseError for MyError {
    fn status_code(&self) -> StatusCode {
        match self {
            Self::Internal => StatusCode::from_u16(500).unwrap(),
            _ => StatusCode::BAD_REQUEST,
        }
    }

    fn error_response(&self) -> HttpResponse {
        HttpResponseBuilder::new(self.status_code())
            .json(serde_json::json!({ "error": self.to_string() }))
    }
}

impl ResponseError for MyOtherError {
    fn status_code(&self) -> StatusCode {
        // With at least opt-level=1, this unwrap will be removed,
        // so this function will essentially return a constant.
        StatusCode::from_u16(404).unwrap()
    }
}

Dependencies

~0.9–1.5MB
~31K SLoC