milstian_http/
response.rs1use std::collections::HashMap;
4use std::str;
5
6pub struct Message {
8    pub protocol: String,
9    pub status: String,
10    pub headers: HashMap<String, String>,
11    pub body: Vec<u8>,
12}
13
14impl Message {
15    pub fn new(
17        protocol: String,
18        status: String,
19        headers: HashMap<String, String>,
20        body: Vec<u8>,
21    ) -> Message {
22        Message {
23            protocol,
24            status,
25            headers,
26            body,
27        }
28    }
29
30    pub fn header_to_string(&self) -> String {
45        let mut response = format!("{} {}\r\n", &self.protocol, &self.status);
46
47        if !&self.headers.is_empty() {
48            let mut headers: Vec<(&String, &String)> = self.headers.iter().collect();
49            headers.sort_by(|a, b| a.cmp(b));
50            for (key, value) in headers {
51                response.push_str(&format!("{}: {}\r\n", &key, &value));
52            }
53        }
54        response.push_str("\r\n");
55
56        response
57    }
58
59    pub fn to_string(&mut self) -> String {
74        let mut response = format!("{} {}\r\n", &self.protocol, &self.status);
75
76        if !&self.headers.is_empty() {
77            let mut headers: Vec<(&String, &String)> = self.headers.iter().collect();
78            headers.sort_by(|a, b| a.cmp(b));
79            for (key, value) in headers {
80                response.push_str(&format!("{}: {}\r\n", &key, &value));
81            }
82        }
83        response.push_str("\r\n");
84
85        if !&self.body.is_empty() {
86            if let Ok(body_string) = str::from_utf8(&self.body) {
87                response.push_str(body_string);
88            }
89        }
90
91        response
92    }
93
94    pub fn to_bytes(&mut self) -> Vec<u8> {
109        let mut response = format!("{} {}\r\n", &self.protocol, &self.status).into_bytes();
110
111        if !&self.headers.is_empty() {
112            let mut headers: Vec<(&String, &String)> = self.headers.iter().collect();
113            headers.sort_by(|a, b| a.cmp(b));
114            for (key, value) in headers {
115                response.append(&mut format!("{}: {}\r\n", &key, &value).into_bytes());
116            }
117        }
118        response.append(&mut "\r\n".to_string().into_bytes());
119
120        if !&self.body.is_empty() {
121            response.append(&mut self.body);
122        }
123
124        response
125    }
126}
127
128#[cfg(test)]
129mod tests {
130    use super::*;
131
132    #[test]
133    fn test_to_string() {
134        let mut message = Message::new(
135            "HTTP/1.0".to_string(),
136            "200 OK".to_string(),
137            HashMap::new(),
138            b"<html><body>Nothing here</body></html>".to_vec(),
139        );
140        assert_eq!(
141            message.to_string(),
142            "HTTP/1.0 200 OK\r\n\r\n<html><body>Nothing here</body></html>".to_string()
143        );
144    }
145
146    #[test]
147    fn test_to_bytes() {
148        let mut message = Message::new(
149            "HTTP/1.0".to_string(),
150            "200 OK".to_string(),
151            HashMap::new(),
152            b"<html><body>Nothing here</body></html>".to_vec(),
153        );
154        assert_eq!(
155            message.to_bytes(),
156            b"HTTP/1.0 200 OK\r\n\r\n<html><body>Nothing here</body></html>".to_vec()
157        );
158    }
159
160}