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}