tela/response/
json.rs

1use bytes::Bytes;
2use http_body_util::Full;
3use hyper::{Method, Uri};
4use serde::{Deserialize, Serialize};
5
6use crate::errors::default_error_page;
7
8use super::{File, Result, ToErrorResponse, ToResponse};
9
10pub type Raw = serde_json::Value;
11
12pub struct JSON<T: Serialize>(pub T);
13
14impl<T: Deserialize<'static> + Serialize> JSON<T> {
15    pub fn from_str(value: String) -> Result<Self> {
16        match serde_json::from_str::<T>(Box::leak(value.into_boxed_str())) {
17            Ok(obj) => Ok(JSON(obj)),
18            _ => Err((500, "Failed to parse json from string".to_string())),
19        }
20    }
21
22    pub fn from_file<U: Into<String> + Clone>(value: File<U>) -> Result<Self> {
23        let path = Into::<String>::into(value.0.clone());
24        match serde_json::from_str::<T>(Box::leak(Into::<String>::into(value).into_boxed_str())) {
25            Ok(obj) => Ok(JSON(obj)),
26            Err(err) => Err((
27                500,
28                format!("Failed to parse json from file {:?}: {}", path, err),
29            )),
30        }
31    }
32}
33
34impl<T: serde::Serialize> ToResponse for JSON<T> {
35    fn to_response(
36        self,
37        method: &Method,
38        uri: &Uri,
39        body: String,
40    ) -> Result<hyper::Response<Full<Bytes>>> {
41        match serde_json::to_string(&self.0) {
42            Ok(result) => Ok(hyper::Response::builder()
43                .status(200)
44                .header("Content-Type", "application/json")
45                .body(Full::new(Bytes::from(result)))
46                .unwrap()),
47            Err(_) => Ok(default_error_page(
48                &500,
49                &"Failed to parse json in response".to_string(),
50                method,
51                uri,
52                body,
53            )),
54        }
55    }
56}
57
58impl<T: serde::Serialize> ToErrorResponse for JSON<T> {
59    fn to_error_response(self, code: u16, reason: String) -> Result<hyper::Response<Full<Bytes>>> {
60        match serde_json::to_string(&self.0) {
61            Ok(result) => Ok(hyper::Response::builder()
62                .status(code)
63                .header("Content-Type", "application/json")
64                .header("Wayfinder-Reason", reason)
65                .body(Full::new(Bytes::from(result)))
66                .unwrap()),
67            Err(_) => Ok(hyper::Response::builder()
68                .status(500)
69                .header("Content-Type", "text/html")
70                .header(
71                    "Wayfinder-Reason",
72                    format!("{}{}", reason, "; Failed to parse json response"),
73                )
74                .body(Full::new(Bytes::new()))
75                .unwrap()),
76        }
77    }
78}