tela 0.1.3

Web framework that focuses on ease of use and simplicity
Documentation
use bytes::Bytes;
use http_body_util::Full;
use hyper::{Method, Uri};
use serde::{Deserialize, Serialize};

use crate::errors::default_error_page;

use super::{File, Result, ToErrorResponse, ToResponse};

pub type Raw = serde_json::Value;

pub struct JSON<T: Serialize>(pub T);

impl<T: Deserialize<'static> + Serialize> JSON<T> {
    pub fn from_str(value: String) -> Result<Self> {
        match serde_json::from_str::<T>(Box::leak(value.into_boxed_str())) {
            Ok(obj) => Ok(JSON(obj)),
            _ => Err((500, "Failed to parse json from string".to_string())),
        }
    }

    pub fn from_file<U: Into<String> + Clone>(value: File<U>) -> Result<Self> {
        let path = Into::<String>::into(value.0.clone());
        match serde_json::from_str::<T>(Box::leak(Into::<String>::into(value).into_boxed_str())) {
            Ok(obj) => Ok(JSON(obj)),
            Err(err) => Err((
                500,
                format!("Failed to parse json from file {:?}: {}", path, err),
            )),
        }
    }
}

impl<T: serde::Serialize> ToResponse for JSON<T> {
    fn to_response(
        self,
        method: &Method,
        uri: &Uri,
        body: String,
    ) -> Result<hyper::Response<Full<Bytes>>> {
        match serde_json::to_string(&self.0) {
            Ok(result) => Ok(hyper::Response::builder()
                .status(200)
                .header("Content-Type", "application/json")
                .body(Full::new(Bytes::from(result)))
                .unwrap()),
            Err(_) => Ok(default_error_page(
                &500,
                &"Failed to parse json in response".to_string(),
                method,
                uri,
                body,
            )),
        }
    }
}

impl<T: serde::Serialize> ToErrorResponse for JSON<T> {
    fn to_error_response(self, code: u16, reason: String) -> Result<hyper::Response<Full<Bytes>>> {
        match serde_json::to_string(&self.0) {
            Ok(result) => Ok(hyper::Response::builder()
                .status(code)
                .header("Content-Type", "application/json")
                .header("Wayfinder-Reason", reason)
                .body(Full::new(Bytes::from(result)))
                .unwrap()),
            Err(_) => Ok(hyper::Response::builder()
                .status(500)
                .header("Content-Type", "text/html")
                .header(
                    "Wayfinder-Reason",
                    format!("{}{}", reason, "; Failed to parse json response"),
                )
                .body(Full::new(Bytes::new()))
                .unwrap()),
        }
    }
}