Files
warren/backend/src/lib/inbound/http/responses.rs
2025-07-16 08:24:58 +02:00

80 lines
1.9 KiB
Rust

use axum::{
Json,
http::StatusCode,
response::{IntoResponse, Response},
};
use serde::Serialize;
/// Generic response structure shared by all API responses.
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct ResponseBody<T: Serialize + PartialEq> {
#[serde(rename = "status")]
status_code: u16,
data: T,
}
impl<T: Serialize + PartialEq> ResponseBody<T> {
pub fn new(status: StatusCode, data: T) -> Self {
Self {
status_code: status.as_u16(),
data,
}
}
}
#[derive(Debug, Clone)]
pub struct ApiSuccess<T: Serialize + PartialEq>(StatusCode, Json<ResponseBody<T>>);
impl<T> PartialEq for ApiSuccess<T>
where
T: Serialize + PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.0 == other.0 && self.1.0 == other.1.0
}
}
impl<T: Serialize + PartialEq> ApiSuccess<T> {
pub fn new(status: StatusCode, data: T) -> Self {
Self(status, Json(ResponseBody::new(status, data)))
}
}
impl<T: Serialize + PartialEq> IntoResponse for ApiSuccess<T> {
fn into_response(self) -> Response {
(self.0, self.1).into_response()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ApiError {
BadRequest(String),
NotFound(String),
InternalServerError(String),
}
impl From<anyhow::Error> for ApiError {
fn from(e: anyhow::Error) -> Self {
Self::InternalServerError(e.to_string())
}
}
impl IntoResponse for ApiError {
fn into_response(self) -> Response {
use ApiError::*;
match self {
BadRequest(e) => (StatusCode::BAD_REQUEST, e).into_response(),
NotFound(e) => (StatusCode::NOT_FOUND, e).into_response(),
InternalServerError(e) => {
tracing::error!("{}", e);
(
StatusCode::INTERNAL_SERVER_ERROR,
"Internal Server Error".to_string(),
)
.into_response()
}
}
}
}