actix_error/
lib.rs

1use std::fmt::{Display, Formatter, Debug};
2use std::error::Error;
3use serde::Serialize;
4pub use actix_error_derive::AsApiError;
5
6/// Represents a structured error that can be easily serialized and sent as an HTTP response.
7#[derive(Debug, Clone, Serialize)]
8pub struct ApiError {
9    /// A machine-readable error type or category.
10    pub kind: String,
11    /// The HTTP status code associated with this error. This field is not serialized.
12    #[serde(skip_serializing)]
13    pub code: u16,
14    /// A human-readable message describing the error.
15    pub message: String,
16    /// Optional structured details about the error.
17    #[serde(skip_serializing_if = "Option::is_none")]
18    pub details: Option<serde_json::Value>,
19}
20
21impl ApiError {
22    /// Creates a new `ApiError`.
23    ///
24    /// # Arguments
25    ///
26    /// * `code` - The HTTP status code for this error.
27    /// * `kind` - A string slice representing the kind or category of the error.
28    /// * `message` - A `String` containing the descriptive message for the error.
29    /// * `details` - Optional `serde_json::Value` for structured error details.
30    pub fn new(
31        code: u16,
32        kind: &str,
33        message: String,
34        details: Option<serde_json::Value>,
35    ) -> Self {
36        Self {
37            kind: kind.to_string(),
38            message,
39            code,
40            details,
41        }
42    }
43}
44
45/// A trait for types that can be converted into an `ApiError`.
46pub trait AsApiErrorTrait {
47    /// Converts the type into an `ApiError`.
48    fn as_api_error(&self) -> ApiError;
49}
50
51impl Display for ApiError {
52    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
53        write!(f, "{}: {}", self.kind, self.message)
54    }
55}
56
57impl Error for ApiError {}
58
59impl actix_web::ResponseError for ApiError {
60    fn status_code(&self) -> actix_web::http::StatusCode {
61        actix_web::http::StatusCode::from_u16(self.code)
62            .unwrap_or(actix_web::http::StatusCode::INTERNAL_SERVER_ERROR)
63    }
64
65    fn error_response(&self) -> actix_web::HttpResponse {
66        actix_web::HttpResponse::build(self.status_code()).json(self)
67    }
68}