xitca_web/handler/types/
html.rs

1//! response generator for Html
2
3use core::{convert::Infallible, fmt};
4
5use xitca_http::util::service::router::{PathGen, RouteGen, RouterMapErr};
6
7use crate::{
8    body::ResponseBody,
9    context::WebContext,
10    error::Error,
11    handler::Responder,
12    http::{WebResponse, const_header_value::TEXT_HTML_UTF8, header::CONTENT_TYPE},
13    service::Service,
14};
15
16#[derive(Clone)]
17pub struct Html<T>(pub T);
18
19impl<T> fmt::Debug for Html<T>
20where
21    T: fmt::Debug,
22{
23    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24        f.debug_struct("Html").field("value", &self.0).finish()
25    }
26}
27
28impl<'r, C, B, T> Responder<WebContext<'r, C, B>> for Html<T>
29where
30    T: Into<ResponseBody>,
31{
32    type Response = WebResponse;
33    type Error = Error;
34
35    #[inline]
36    async fn respond(self, ctx: WebContext<'r, C, B>) -> Result<Self::Response, Self::Error> {
37        let mut res = ctx.into_response(self.0);
38        res.headers_mut().insert(CONTENT_TYPE, TEXT_HTML_UTF8);
39        Ok(res)
40    }
41
42    fn map(self, mut res: Self::Response) -> Result<Self::Response, Self::Error> {
43        res.headers_mut().insert(CONTENT_TYPE, TEXT_HTML_UTF8);
44        Ok(res.map(|_| self.0.into()))
45    }
46}
47
48impl<T> PathGen for Html<T> {}
49
50impl<T> RouteGen for Html<T> {
51    type Route<R> = RouterMapErr<R>;
52
53    fn route_gen<R>(route: R) -> Self::Route<R> {
54        RouterMapErr(route)
55    }
56}
57
58impl<T> Service for Html<T>
59where
60    T: Clone,
61{
62    type Response = Self;
63    type Error = Infallible;
64
65    async fn call(&self, _: ()) -> Result<Self::Response, Self::Error> {
66        Ok(self.clone())
67    }
68}
69
70impl<'r, C, B, T> Service<WebContext<'r, C, B>> for Html<T>
71where
72    T: Clone + Into<ResponseBody>,
73{
74    type Response = WebResponse;
75    type Error = Error;
76
77    #[inline]
78    async fn call(&self, ctx: WebContext<'r, C, B>) -> Result<Self::Response, Self::Error> {
79        self.clone().respond(ctx).await
80    }
81}
82
83#[cfg(test)]
84mod test {
85    use xitca_unsafe_collection::futures::NowOrPanic;
86
87    use crate::{App, http::WebRequest};
88
89    use super::*;
90
91    #[test]
92    fn service() {
93        let res = App::new()
94            .at("/", Html("hello,world!"))
95            .finish()
96            .call(())
97            .now_or_panic()
98            .unwrap()
99            .call(WebRequest::default())
100            .now_or_panic()
101            .unwrap();
102        assert_eq!(res.status().as_u16(), 200);
103    }
104}