1use 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 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 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}