1use axum::{
2 http::StatusCode,
3 response::{IntoResponse, Response},
4 Json,
5};
6use serde::Serialize;
7
8#[derive(Serialize)]
19struct ErrorBody {
20 #[serde(rename = "statusCode")]
21 status_code: u16,
22 error: String,
23 message: String,
24}
25
26#[derive(Debug, Clone)]
31pub struct HttpException {
32 pub status: StatusCode,
33 pub message: String,
34}
35
36impl HttpException {
37 pub fn new(status: StatusCode, message: impl Into<String>) -> Self {
41 Self {
42 status,
43 message: message.into(),
44 }
45 }
46
47 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
67impl 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}