#![allow(unused_imports, dead_code)]
use std::fmt;
use crate::{Error, FnTemplate, Result, Template};
pub struct Response(pub Result<String>);
pub trait TemplateExt<Ctx: ?Sized = ()>: Template<Ctx> {
fn response(self, ctx: &Ctx) -> Response;
}
impl<Ctx: ?Sized, T: Template<Ctx>> TemplateExt<Ctx> for T {
fn response(self, ctx: &Ctx) -> TemplrResp {
Response(self.render(ctx))
}
}
use Response as TemplrResp;
const HTML_MIME_TYPE: &str = "text/html; charset=utf-8";
impl fmt::Display for TemplrResp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.0.as_ref().map_err(|_| fmt::Error)?, f)
}
}
#[cfg(feature = "axum")]
mod resp_axum {
use axum_core::response::{IntoResponse, Response};
use http::{header, HeaderValue, StatusCode};
use super::*;
impl IntoResponse for TemplrResp {
fn into_response(self) -> Response {
match self.0 {
Ok(body) => IntoResponse::into_response((
[(
header::CONTENT_TYPE,
HeaderValue::from_static(HTML_MIME_TYPE),
)],
body,
)),
Err(_) => StatusCode::INTERNAL_SERVER_ERROR.into_response(),
}
}
}
impl<F> IntoResponse for FnTemplate<F>
where
F: Fn(&mut dyn fmt::Write, &(), &dyn Template<()>) -> crate::Result<()> + Send,
{
fn into_response(self) -> Response {
self.response(&()).into_response()
}
}
}
#[cfg(feature = "actix-web")]
mod resp_actix_web {
use actix_web::{
body::BoxBody,
http::{header::HeaderValue, StatusCode},
HttpRequest, HttpResponse, HttpResponseBuilder, Responder, ResponseError,
};
use super::*;
struct AnyhowErr(Error);
impl fmt::Display for AnyhowErr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
impl fmt::Debug for AnyhowErr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}
impl ResponseError for AnyhowErr {}
impl Responder for TemplrResp {
type Body = BoxBody;
fn respond_to(self, _req: &HttpRequest) -> HttpResponse {
match self.0 {
Ok(body) => HttpResponseBuilder::new(StatusCode::OK)
.content_type(HeaderValue::from_static(HTML_MIME_TYPE))
.body(body),
Err(err) => HttpResponse::from_error(AnyhowErr(err)),
}
}
}
impl<F> Responder for FnTemplate<F>
where
F: Fn(&mut dyn fmt::Write, &(), &dyn Template<()>) -> crate::Result<()>,
{
type Body = BoxBody;
fn respond_to(self, req: &HttpRequest) -> HttpResponse {
self.response(&()).respond_to(req)
}
}
}
#[cfg(feature = "hyper")]
mod resp_hyper {
use hyper::{
header::{self, HeaderValue},
Response, StatusCode,
};
use super::*;
impl From<TemplrResp> for Response<String> {
fn from(slf: TemplrResp) -> Self {
match slf.0 {
Ok(body) => Response::builder()
.status(StatusCode::OK)
.header(
header::CONTENT_TYPE,
HeaderValue::from_static(HTML_MIME_TYPE),
)
.body(body.into())
.unwrap(),
Err(_) => Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.body(Default::default())
.unwrap(),
}
}
}
impl<F> From<FnTemplate<F>> for Response<String>
where
F: Fn(&mut dyn fmt::Write, &(), &dyn Template<()>) -> crate::Result<()>,
{
fn from(slf: FnTemplate<F>) -> Self {
slf.response(&()).into()
}
}
}
#[cfg(feature = "warp")]
mod resp_warp {
use warp::{
http::{self, header, StatusCode},
reply::{Reply, Response},
};
use super::*;
impl Reply for TemplrResp {
fn into_response(self) -> Response {
match self.0 {
Ok(body) => http::Response::builder()
.status(StatusCode::OK)
.header(header::CONTENT_TYPE, HTML_MIME_TYPE)
.body(body.into()),
Err(_) => http::Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.body("".into()),
}
.unwrap()
}
}
impl<F> Reply for FnTemplate<F>
where
F: Fn(&mut dyn fmt::Write, &(), &dyn Template<()>) -> crate::Result<()> + Send,
{
fn into_response(self) -> Response {
self.response(&()).into_response()
}
}
}
#[cfg(feature = "tide")]
mod resp_tide {
use tide::{Body, Response};
use super::*;
impl From<TemplrResp> for Response {
fn from(slf: TemplrResp) -> Self {
match slf.0 {
Ok(body) => {
let mut body = Body::from_string(body);
body.set_mime(HTML_MIME_TYPE);
let mut response = Response::new(200);
response.set_body(body);
response
}
Err(error) => {
let mut response = Response::new(500);
response.set_error(error);
response
}
}
}
}
impl<F> From<FnTemplate<F>> for Response
where
F: Fn(&mut dyn fmt::Write, &(), &dyn Template<()>) -> crate::Result<()>,
{
fn from(slf: FnTemplate<F>) -> Self {
slf.response(&()).into()
}
}
}
#[cfg(feature = "gotham")]
mod resp_gotham {
use gotham::{
handler::IntoResponse,
hyper::{
header::{self, HeaderValue},
Body, Response, StatusCode,
},
state::State,
};
use super::*;
impl IntoResponse for TemplrResp {
fn into_response(self, _state: &State) -> Response<Body> {
match self.0 {
Ok(body) => Response::builder()
.status(StatusCode::OK)
.header(
header::CONTENT_TYPE,
HeaderValue::from_static(HTML_MIME_TYPE),
)
.body(body.into())
.unwrap(),
Err(_) => Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.body(vec![].into())
.unwrap(),
}
}
}
impl<F> IntoResponse for FnTemplate<F>
where
F: Fn(&mut dyn fmt::Write, &(), &dyn Template<()>) -> crate::Result<()>,
{
fn into_response(self, state: &State) -> Response<Body> {
self.response(&()).into_response(state)
}
}
}
#[cfg(feature = "rocket")]
mod resp_rocket {
use std::io::Cursor;
use rocket::{
http::{Header, Status},
response::Response,
response::{Responder, Result},
Request,
};
use super::*;
impl<'r, 'o: 'r> Responder<'r, 'o> for TemplrResp {
fn respond_to(self, _req: &'r Request<'_>) -> Result<'o> {
let body = self.0.map_err(|_| Status::InternalServerError)?;
Response::build()
.header(Header::new("content-type", HTML_MIME_TYPE))
.sized_body(body.len(), Cursor::new(body))
.ok()
}
}
impl<'r, 'o: 'r, F> Responder<'r, 'o> for FnTemplate<F>
where
F: Fn(&mut dyn fmt::Write, &(), &dyn Template<()>) -> crate::Result<()>,
{
fn respond_to(self, req: &'r Request<'_>) -> Result<'o> {
self.response(&()).respond_to(req)
}
}
}
#[cfg(feature = "salvo")]
mod resp_salvo {
use salvo_core::{
http::{
header::{self, HeaderValue},
StatusCode,
},
Response, Scribe,
};
use super::*;
impl Scribe for TemplrResp {
fn render(self, res: &mut Response) {
match self.0 {
Ok(body) => {
res.status_code(StatusCode::OK);
res.body(body);
res.headers_mut().insert(
header::CONTENT_TYPE,
HeaderValue::from_static(HTML_MIME_TYPE),
);
}
Err(_) => {
res.status_code(StatusCode::INTERNAL_SERVER_ERROR);
}
}
}
}
impl<F> Scribe for FnTemplate<F>
where
F: Fn(&mut dyn fmt::Write, &(), &dyn Template<()>) -> crate::Result<()>,
{
fn render(self, res: &mut Response) {
self.response(&()).render(res)
}
}
}