servio_util/
response.rs

1use bytes::Bytes;
2use futures_core::Stream;
3use futures_util::{future::Ready, stream::Iter};
4use http::header::{CONTENT_LENGTH, CONTENT_TYPE};
5use http::{HeaderMap, StatusCode};
6use servio_http::http::{HttpEvent, ResponseChunk, ResponseStart, EVENT_HTTP};
7use servio_service::{Event, Scope, Service};
8use std::borrow::Cow;
9use std::convert::Infallible;
10use std::vec::IntoIter;
11
12#[derive(Default, Clone)]
13pub struct StaticResponse {
14    events: Vec<Event>,
15}
16
17impl StaticResponse {
18    pub fn new(
19        status_code: StatusCode,
20        content: Bytes,
21        media_type: Cow<'static, str>,
22        headers: HeaderMap,
23    ) -> Self {
24        let mut resp = ResponseChunk::default();
25        resp.body = content;
26
27        let mut response_start = ResponseStart::default();
28        response_start.status = status_code;
29        response_start.headers = headers;
30
31        let headers = &mut response_start.headers;
32        headers.insert(CONTENT_LENGTH, resp.body.len().into());
33        headers.insert(CONTENT_TYPE, media_type.as_ref().parse().unwrap());
34
35        Self {
36            events: vec![
37                Event::new(EVENT_HTTP.into(), HttpEvent::ResponseStart(response_start)),
38                Event::new(EVENT_HTTP.into(), HttpEvent::ResponseChunk(resp)),
39            ],
40        }
41    }
42}
43
44impl<ServerStream> Service<ServerStream> for StaticResponse
45where
46    ServerStream: Stream<Item = Event>,
47{
48    type AppStream = Iter<IntoIter<Event>>;
49    type Error = Infallible;
50    type Future = Ready<Result<Self::AppStream, Self::Error>>;
51
52    fn call(&mut self, _scope: Scope, _server_events: ServerStream) -> Self::Future {
53        let stream = futures_util::stream::iter(self.events.clone());
54        futures_util::future::ok(stream)
55    }
56}
57
58macro_rules! simple_pass {
59    ($srv:ident) => {
60        #[derive(Default, Clone)]
61        pub struct $srv {
62            inner: StaticResponse,
63        }
64
65        impl<ServerStream> Service<ServerStream> for $srv
66        where
67            ServerStream: Stream<Item = Event>,
68        {
69            type AppStream = <StaticResponse as Service<ServerStream>>::AppStream;
70            type Error = <StaticResponse as Service<ServerStream>>::Error;
71            type Future = <StaticResponse as Service<ServerStream>>::Future;
72
73            fn call(&mut self, scope: Scope, server_events: ServerStream) -> Self::Future {
74                self.inner.call(scope, server_events)
75            }
76        }
77    };
78}
79
80simple_pass!(HtmlResponse);
81impl HtmlResponse {
82    pub fn new(status_code: StatusCode, content: Bytes, headers: HeaderMap) -> Self {
83        Self {
84            inner: StaticResponse::new(status_code, content, "text/html".into(), headers),
85        }
86    }
87}
88
89simple_pass!(PlainTextResponse);
90impl PlainTextResponse {
91    pub fn new(status_code: StatusCode, content: Cow<'static, str>, headers: HeaderMap) -> Self {
92        Self {
93            inner: StaticResponse::new(
94                status_code,
95                content.to_string().into(),
96                "text/plain".into(),
97                headers,
98            ),
99        }
100    }
101}
102
103#[cfg(feature = "serde")]
104simple_pass!(JsonResponse);
105#[cfg(feature = "serde")]
106impl JsonResponse {
107    pub fn new<S: serde::Serialize>(
108        status_code: StatusCode,
109        content: &S,
110        headers: HeaderMap,
111    ) -> Self {
112        Self {
113            inner: StaticResponse::new(
114                status_code,
115                serde_json::to_vec(content).unwrap().into(),
116                "application/json".into(),
117                headers,
118            ),
119        }
120    }
121}