Skip to main content

nestforge_core/
error.rs

1use axum::{
2    http::StatusCode,
3    response::{IntoResponse, Response},
4    Json,
5};
6use serde::Serialize;
7
8/**
9* ErrorBody = standard JSON error response shape.
10* 
11* Keeping this simple and clean for now:
12* {
13*   "statusCode": 500,
14*   "error": "Internal Server Error",
15*   "message": "Something went wrong"
16* }
17*/
18#[derive(Serialize)]
19struct ErrorBody {
20    #[serde(rename = "statusCode")]
21    status_code: u16,
22    error: String,
23    message: String,
24}
25
26/**
27* HttpException = framework error type
28* This lets controllers return proper HTTP errors without manually building responses.
29*/
30#[derive(Debug, Clone)]
31pub struct HttpException {
32    pub status: StatusCode,
33    pub message: String,
34}
35
36impl HttpException {
37    /*
38    Generic constructor
39    */
40    pub fn new(status: StatusCode, message: impl Into<String>) -> Self {
41        Self {
42            status,
43            message: message.into(),
44        }
45    }
46
47    /*
48    Helper constructors (clean DX for controllers)
49    */
50    pub fn bad_request(message: impl Into<String>) -> Self {
51        Self::new(StatusCode::BAD_REQUEST, message)
52    }
53
54    pub fn unauthorized(message: impl Into<String>) -> Self {
55        Self::new(StatusCode::UNAUTHORIZED, message)
56    }
57
58    pub fn not_found(message: impl Into<String>) -> Self {
59        Self::new(StatusCode::NOT_FOUND, message)
60    }
61
62    pub fn internal_server_error(message: impl Into<String>) -> Self {
63        Self::new(StatusCode::INTERNAL_SERVER_ERROR, message)
64    }
65}
66
67/**
68* IntoResponse makes HttpException directly returnable from axum handlers.
69* 
70* So handlers can return:
71* Result<Json<T>, HttpException>
72* and axum knows how to turn the error into a real HTTP response.
73*/
74impl IntoResponse for HttpException {
75    fn into_response(self) -> Response {
76        let error_name = self
77            .status
78            .canonical_reason()
79            .unwrap_or("Error")
80            .to_string();
81
82        let body = ErrorBody {
83            status_code: self.status.as_u16(),
84            error: error_name,
85            message: self.message,
86        };
87
88        (self.status, Json(body)).into_response()
89    }
90}