rs_express/
response.rs

1use hyper::{
2    http::header::{HeaderName, HeaderValue},
3    http::StatusCode,
4    Body,
5};
6use std::collections::HashMap;
7use std::str::FromStr;
8
9pub struct Response {
10    pub(crate) ended: bool,
11    pub(crate) status: StatusCode,
12    headers: HashMap<String, String>,
13    data: String,
14}
15
16impl Response {
17    pub fn new() -> Response {
18        Response {
19            ended: false,
20            data: String::from(""),
21            headers: HashMap::new(),
22            status: StatusCode::OK,
23        }
24    }
25
26    /// Sets the given header in the response.
27    pub fn set_header(&mut self, name: &str, value: &str) {
28        self.headers.insert(name.to_string(), value.to_string());
29    }
30
31    pub fn status(&mut self, status: StatusCode) -> &mut Self {
32        self.status = status;
33
34        self
35    }
36
37    pub fn send<S: AsRef<str>>(&mut self, data: S) {
38        self.data = data.as_ref().to_string();
39
40        self.end();
41    }
42
43    /// End the response processing.
44    pub fn end(&mut self) {
45        self.ended = true;
46    }
47}
48
49impl Into<hyper::Response<Body>> for Response {
50    fn into(self) -> hyper::Response<Body> {
51        let mut response = hyper::Response::new(Body::from(self.data));
52        *response.status_mut() = self.status;
53
54        self.headers
55            .into_iter()
56            .for_each(|(header_name, header_value)| {
57                response.headers_mut().insert(
58                    HeaderName::from_str(&header_name).unwrap(),
59                    HeaderValue::from_str(&header_value).unwrap(),
60                );
61            });
62
63        response
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    #[test]
72    fn test_set_header() {
73        let mut response = Response::new();
74
75        response.set_header("my-custom-header", "a-b-c");
76
77        let res: hyper::Response<Body> = response.into();
78
79        assert_eq!(
80            res.headers().get("my-custom-header"),
81            Some(&HeaderValue::from_str("a-b-c").unwrap())
82        );
83    }
84
85    #[test]
86    fn status() {
87        let mut response = Response::new();
88
89        response.status(StatusCode::BAD_REQUEST);
90
91        let res: hyper::Response<Body> = response.into();
92
93        assert_eq!(res.status(), StatusCode::BAD_REQUEST);
94    }
95
96    #[test]
97    fn test_end() {
98        let mut response = Response::new();
99
100        assert_eq!(response.ended, false);
101
102        response.end();
103
104        assert_eq!(response.ended, true);
105    }
106
107    #[tokio::test]
108    async fn test_send() {
109        let mut response = Response::new();
110
111        response.send("Hello");
112
113        assert_eq!(response.ended, true);
114
115        let mut res: hyper::Response<Body> = response.into();
116
117        let bytes = hyper::body::to_bytes(res.body_mut()).await.unwrap();
118        let body = String::from_utf8(bytes.into_iter().collect()).unwrap();
119
120        assert_eq!(body, String::from("Hello"),);
121    }
122}