1use std::collections::HashMap;
8use std::io::Write;
9
10use crate::shared::HttpVersion;
11
12#[derive(Debug, Copy, Clone)]
14pub enum HttpStatus {
15 Ok,
16 Created,
17 NoContent,
18 BadRequest,
19 Unauthorized,
20 Forbidden,
21 NotFound,
22 InternalServerError,
23 BadGateway,
24 ServiceUnavailable,
25}
26
27impl From<HttpStatus> for u16 {
29 fn from(status: HttpStatus) -> u16 {
30 match status {
31 HttpStatus::Ok => 200,
32 HttpStatus::Created => 201,
33 HttpStatus::NoContent => 204,
34 HttpStatus::BadRequest => 400,
35 HttpStatus::Unauthorized => 401,
36 HttpStatus::Forbidden => 403,
37 HttpStatus::NotFound => 404,
38 HttpStatus::InternalServerError => 500,
39 HttpStatus::BadGateway => 502,
40 HttpStatus::ServiceUnavailable => 503,
41 }
42 }
43}
44
45impl From<HttpStatus> for &'static str {
47 fn from(status: HttpStatus) -> &'static str {
48 match status {
49 HttpStatus::Ok => "OK",
50 HttpStatus::Created => "Created",
51 HttpStatus::NoContent => "No Content",
52 HttpStatus::BadRequest => "Bad Request",
53 HttpStatus::Unauthorized => "Unauthorized",
54 HttpStatus::Forbidden => "Forbidden",
55 HttpStatus::NotFound => "Not Found",
56 HttpStatus::InternalServerError => "Internal Server Error",
57 HttpStatus::BadGateway => "Bad Gateway",
58 HttpStatus::ServiceUnavailable => "Service Unavailable",
59 }
60 }
61}
62
63#[derive(Debug)]
65pub struct HeaderKey(String);
66
67impl AsRef<str> for HeaderKey {
68 fn as_ref(&self) -> &str {
69 &self.0
70 }
71}
72
73impl AsMut<String> for HeaderKey {
74 fn as_mut(&mut self) -> &mut String {
75 &mut self.0
76 }
77}
78
79impl From<String> for HeaderKey {
80 fn from(value: String) -> Self {
81 Self(value)
82 }
83}
84
85#[derive(Debug)]
87pub struct HeaderValue(String);
88
89impl AsRef<str> for HeaderValue {
90 fn as_ref(&self) -> &str {
91 &self.0
92 }
93}
94
95impl AsMut<String> for HeaderValue {
96 fn as_mut(&mut self) -> &mut String {
97 &mut self.0
98 }
99}
100
101impl From<String> for HeaderValue {
102 fn from(value: String) -> Self {
103 Self(value)
104 }
105}
106
107#[derive(Debug)]
109pub struct HttpResponseBuilder {
110 status: HttpStatus,
111 protocal: Option<HttpVersion>,
112 headers: Option<HashMap<HeaderKey, HeaderValue>>,
113 body: Option<String>,
114}
115
116impl HttpResponseBuilder {
117 pub fn new(status: HttpStatus) -> Self {
119 Self {
120 status,
121 protocal: None,
122 headers: None,
123 body: None,
124 }
125 }
126
127 pub fn ok() -> Self {
129 Self::new(HttpStatus::Ok)
130 }
131
132 pub fn created() -> Self {
134 Self::new(HttpStatus::Created)
135 }
136
137 pub fn no_content() -> Self {
139 Self::new(HttpStatus::NoContent)
140 }
141
142 pub fn bad_request() -> Self {
144 Self::new(HttpStatus::BadRequest)
145 }
146
147 pub fn unauthorized() -> Self {
149 Self::new(HttpStatus::Unauthorized)
150 }
151
152 pub fn forbidden() -> Self {
154 Self::new(HttpStatus::Forbidden)
155 }
156
157 pub fn not_found() -> Self {
159 Self::new(HttpStatus::NotFound)
160 }
161
162 pub fn internal_server_error() -> Self {
164 Self::new(HttpStatus::InternalServerError)
165 }
166
167 pub fn bad_gateway() -> Self {
169 Self::new(HttpStatus::BadGateway)
170 }
171
172 pub fn service_unavailable() -> Self {
174 Self::new(HttpStatus::ServiceUnavailable)
175 }
176
177 pub fn protocal(mut self, protocal: HttpVersion) -> Self {
179 self.protocal = Some(protocal);
180 self
181 }
182
183 pub fn headers(mut self, headers: HashMap<HeaderKey, HeaderValue>) -> Self {
185 self.headers = Some(headers);
186 self
187 }
188
189 pub fn get_mut_headers(&mut self) -> Option<&mut HashMap<HeaderKey, HeaderValue>> {
191 self.headers.as_mut()
192 }
193
194 pub fn body(mut self, body: String) -> Self {
196 self.body = Some(body);
197 self
198 }
199
200 pub fn build(self) -> HttpResponse {
202 HttpResponse {
203 status: self.status,
204 protocal: self.protocal.unwrap_or(HttpVersion::OnePointOne),
205 headers: self.headers,
206 body: self.body,
207 }
208 }
209}
210
211#[derive(Debug)]
213pub struct HttpResponse {
214 status: HttpStatus,
215 protocal: HttpVersion,
216 headers: Option<HashMap<HeaderKey, HeaderValue>>,
217 body: Option<String>,
218}
219
220impl HttpResponse {
221 pub fn serialize(self, mut buffer: Vec<u8>) -> Vec<u8> {
223 write!(
225 &mut buffer,
226 "{} {}\r\n",
227 <&str>::from(self.protocal),
228 format!("{} {}", u16::from(self.status), <&str>::from(self.status))
229 )
230 .unwrap();
231
232 if let Some(headers) = self.headers {
234 headers.iter().for_each(|(key, value)| {
235 write!(&mut buffer, "{}: {}\r\n", key.as_ref(), value.as_ref()).unwrap();
236 });
237 }
238
239 write!(&mut buffer, "\r\n").unwrap();
241
242 if let Some(body) = self.body {
244 write!(&mut buffer, "{}", body).unwrap();
245 }
246
247 buffer
248 }
249}