1use crate::types::OxiditeResponse;
2use crate::error::Error;
3use http_body_util::{Full, BodyExt};
4use bytes::Bytes;
5use hyper::Response;
6use hyper::header::{HeaderValue, CONTENT_TYPE, SERVER};
7use http::StatusCode;
8
9const SERVER_HEADER_VALUE: &str = concat!("Oxidite/", env!("CARGO_PKG_VERSION"));
10
11impl OxiditeResponse {
12 pub fn json<T: serde::Serialize>(data: T) -> Self {
14 match serde_json::to_vec(&data) {
15 Ok(json_bytes) => {
16 let res = Response::builder()
17 .header(CONTENT_TYPE, HeaderValue::from_static("application/json"))
18 .header(SERVER, HeaderValue::from_static(SERVER_HEADER_VALUE))
19 .body(Full::new(Bytes::from(json_bytes)).map_err(|e| match e {}).boxed())
20 .unwrap();
21 Self(res)
22 },
23 Err(_) => {
24 let res = Response::builder()
25 .status(StatusCode::INTERNAL_SERVER_ERROR)
26 .header(CONTENT_TYPE, HeaderValue::from_static("application/json"))
27 .header(SERVER, HeaderValue::from_static(SERVER_HEADER_VALUE))
28 .body(Full::new(Bytes::from("{\"error\":\"Internal Server Error\"}".as_bytes().to_vec())).map_err(|e| match e {}).boxed())
29 .unwrap();
30 Self(res)
31 },
32 }
33 }
34
35 pub fn html(body: impl Into<String>) -> Self {
37 let res = Response::builder()
38 .header(CONTENT_TYPE, HeaderValue::from_static("text/html"))
39 .header(SERVER, HeaderValue::from_static(SERVER_HEADER_VALUE))
40 .body(Full::new(Bytes::from(body.into())).map_err(|e| match e {}).boxed())
41 .unwrap();
42 Self(res)
43 }
44
45 pub fn text(body: impl Into<String>) -> Self {
47 let res = Response::builder()
48 .header(CONTENT_TYPE, HeaderValue::from_static("text/plain"))
49 .header(SERVER, HeaderValue::from_static(SERVER_HEADER_VALUE))
50 .body(Full::new(Bytes::from(body.into())).map_err(|e| match e {}).boxed())
51 .unwrap();
52 Self(res)
53 }
54
55 pub fn ok() -> Self {
57 let res = Response::builder()
58 .status(StatusCode::OK)
59 .header(SERVER, HeaderValue::from_static(SERVER_HEADER_VALUE))
60 .body(Full::new(Bytes::new()).map_err(|e| match e {}).boxed())
61 .unwrap();
62 Self(res)
63 }
64
65 pub fn no_content() -> Self {
67 let res = Response::builder()
68 .status(StatusCode::NO_CONTENT)
69 .header(SERVER, HeaderValue::from_static(SERVER_HEADER_VALUE))
70 .body(Full::new(Bytes::new()).map_err(|e| match e {}).boxed())
71 .unwrap();
72 Self(res)
73 }
74}
75
76impl From<Error> for OxiditeResponse {
77 fn from(error: Error) -> Self {
78 let status = error.status_code();
79 let body = serde_json::json!({
80 "error": error.to_string()
81 });
82
83 let fallback = format!(r#"{{"error":"{}"}}"#, status);
84 let json_bytes = serde_json::to_vec(&body).unwrap_or_else(|_| fallback.into_bytes());
85
86 let res = Response::builder()
87 .status(status)
88 .header(CONTENT_TYPE, HeaderValue::from_static("application/json"))
89 .header(SERVER, HeaderValue::from_static(SERVER_HEADER_VALUE))
90 .body(Full::new(Bytes::from(json_bytes)).map_err(|e| match e {}).boxed())
91 .unwrap();
92 Self(res)
93 }
94}