http_rust/
httpresponse.rs

1use std::collections::HashMap;
2use::std::io::{Result, Write};
3
4#[derive(Debug, PartialEq, Clone)]
5pub struct HttpResponse<'a>
6{
7	version: &'a str,
8	status_code: &'a str,
9	status_text: &'a str,
10	headers: Option<HashMap<&'a str, &'a str>>,
11	body: Option<String>,
12}
13
14impl<'a> Default for HttpResponse<'a>{
15	fn default () -> Self{
16		Self{
17			version: "HTTP/1.1".into(),
18			status_code: "200".into(),
19			status_text: "OK".into(),
20			headers: None,
21			body: None,
22		}
23	}
24}
25
26impl<'a> HttpResponse<'a>{
27	pub fn new(
28			status_code: &'a str,
29			headers: Option<HashMap<&'a str, &'a str>>,
30			body: Option<String>
31		) -> HttpResponse<'a>{
32		let mut response: HttpResponse<'a> = HttpResponse::default();
33		if status_code != "200"
34		{
35			response.status_code = status_code.into();
36		};
37		response.headers = match &headers{
38			Some(_h) => headers,
39			None =>{
40				let mut h = HashMap::new();
41				h.insert("Content-Type", "text/html");
42				Some(h)
43			}
44		};
45
46		response.status_text = match response.status_code{
47
48			"200" => "OK".into(),
49			"400" => "Bad Request".into(),
50			"404" => "Not Found".into(),
51			"500" => "Internal Server Error".into(),
52			_ => "Not Found".into(),
53		};
54		response.body = body;
55		response
56	}
57
58	pub fn send_response(&self, write_stream:&mut impl Write) -> Result<()>
59	{
60		let res = self.clone();
61		let response_string:String = String::from(res);
62		let _ = write!(write_stream, "{}", response_string);
63		Ok(())
64	}
65
66	//Getter methods
67	fn version(&self) -> &str
68	{
69		self.version
70	}
71	fn status_code(&self) -> &str
72	{
73		self.status_code
74	}
75	fn status_text(&self) -> &str
76	{
77		self.status_text
78	}
79	fn headers(&self)-> String
80	{
81		let map: HashMap<&str, &str>  = self.headers.clone().unwrap();
82		let mut header_string:String = "".into();
83		for (k, v) in map.iter()
84		{
85			header_string = format!("{}{}:{}\r\n", header_string, k, v);
86		}
87		header_string
88	}
89	pub fn body(&self) ->&str
90	{
91		match &self.body{
92			Some(b) => b.as_str(),
93			None => ""
94		}
95	}
96}
97
98impl<'a> From <HttpResponse <'a>> for String{
99	fn from(res:HttpResponse) ->String
100	{
101		let res1 = res.clone();
102		format!("{} {} {}\r\n{}Content-Length: {}\r\n\r\n{}",
103			&res1.version(),
104			&res1.status_code(),
105			&res1.status_text(),
106			&res1.headers(),
107			&res.body.unwrap_or("".to_string()).len(),
108			&res1.body()
109			)
110	}
111}
112
113#[cfg(test)]
114mod tests{
115	use super::*;
116	#[test]
117	fn test_response_struct_creation_200()
118	{
119		let response_actual = HttpResponse::new(
120			"200",
121			None,
122			Some("Ifedayo is the best".into())
123		);
124		let response_expected = HttpResponse{
125			version: "HTTP/1.1",
126			status_code: "200",
127			status_text: "OK",
128			headers:{
129				let mut h = HashMap::new();
130				h.insert("Content-Type", "text/html");
131				Some(h)
132			},
133			body: Some("Ifedayo is the best".into())
134		};
135		assert_eq!(response_actual, response_expected)
136	}
137	#[test]
138	fn test_response_struct_creation_404()
139	{
140		let response_actual = HttpResponse::new(
141			"404",
142			None,
143			Some("Ifedayo is the best".into())
144		);
145		let response_expected = HttpResponse{
146			version: "HTTP/1.1",
147			status_code: "404",
148			status_text: "Not Found",
149			headers:{
150				let mut h = HashMap::new();
151				h.insert("Content-Type", "text/html");
152				Some(h)
153			},
154			body: Some("Ifedayo is the best".into())
155		};
156		assert_eq!(response_actual, response_expected)
157	}
158	#[test]
159	fn test_http_response_creation()
160	{
161		let response_expected = HttpResponse{
162			version: "HTTP/1.1",
163			status_code: "404",
164			status_text: "Not Found",
165			headers:{
166				let mut h = HashMap::new();
167				h.insert("Content-Type", "text/html");
168				Some(h)
169			},
170			body: Some("Ifedayo is the best".into())
171		};
172
173		let http_string:String = response_expected.into();
174		let response_actual = "HTTP/1.1 404 Not Found\r\nContent-Type:text/html\r\nContent-Length: 19\r\n\r\nIfedayo is the best";
175		assert_eq!(http_string, response_actual );
176	}
177
178}