Skip to main content

adminx_core/
response.rs

1// adminx-core/src/response.rs
2//
3// A neutral HTTP response. Adapters translate it into `actix_web::HttpResponse`
4// or `axum::response::Response`. This is the boundary that lets one Resource
5// implementation serve any framework.
6
7use crate::error::CoreError;
8use serde_json::{json, Value};
9
10#[derive(Debug, Clone)]
11pub enum ApiBody {
12    Json(Value),
13    Bytes { content_type: String, data: Vec<u8> },
14    Empty,
15}
16
17#[derive(Debug, Clone)]
18pub struct ApiResponse {
19    pub status: u16,
20    pub headers: Vec<(String, String)>,
21    pub body: ApiBody,
22}
23
24impl ApiResponse {
25    pub fn new(status: u16, body: ApiBody) -> Self {
26        Self {
27            status,
28            headers: Vec::new(),
29            body,
30        }
31    }
32
33    pub fn json(status: u16, value: Value) -> Self {
34        Self::new(status, ApiBody::Json(value))
35    }
36
37    pub fn ok(value: Value) -> Self {
38        Self::json(200, value)
39    }
40
41    pub fn created(value: Value) -> Self {
42        Self::json(201, value)
43    }
44
45    pub fn error(err: CoreError) -> Self {
46        Self::json(err.status(), json!({ "error": err.message() }))
47    }
48
49    /// HTML body with a `text/html` content type.
50    pub fn html(status: u16, markup: String) -> Self {
51        Self::new(
52            status,
53            ApiBody::Bytes {
54                content_type: "text/html; charset=utf-8".to_string(),
55                data: markup.into_bytes(),
56            },
57        )
58    }
59
60    /// See-other redirect (303) to `location`.
61    pub fn redirect(location: impl Into<String>) -> Self {
62        Self::new(303, ApiBody::Empty).with_header("Location", location)
63    }
64
65    pub fn with_header(mut self, name: impl Into<String>, value: impl Into<String>) -> Self {
66        self.headers.push((name.into(), value.into()));
67        self
68    }
69}
70
71impl From<CoreError> for ApiResponse {
72    fn from(err: CoreError) -> Self {
73        ApiResponse::error(err)
74    }
75}