proxy_server/http/
headers.rs1use crate::http::CRLF;
3#[cfg(feature = "napi")]
4use napi_derive::napi;
5use regex::Regex;
6use serde::{Deserialize, Serialize};
7use std::{
8 fmt,
9 io::{Error, ErrorKind, Result},
10 str,
11};
12
13use super::status::Status;
14
15#[cfg_attr(feature = "napi", napi(object))]
17#[derive(Debug, Serialize, Clone, Deserialize)]
18pub struct Header {
19 pub name: String,
20 pub value: String,
21}
22
23#[cfg_attr(feature = "napi", napi(object))]
25#[derive(Debug, Serialize, Clone, Deserialize)]
26pub struct Headers {
27 pub raw: String,
28 pub list: Vec<Header>,
29}
30
31impl fmt::Display for Header {
32 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
33 write!(f, "{}: {}", self.name, self.value)
34 }
35}
36
37impl Headers {
38 pub fn new() -> Self {
39 Headers::from_string("".to_string())
40 }
41
42 pub fn new_request(prefix: &str, list: Vec<Header>) -> Self {
44 let postfix = Headers::to_string(list);
45 let raw = format!(
46 "{}{CRLF}{postfix}",
47 Regex::new(r"\s*$")
48 .unwrap()
49 .replace_all(prefix, "")
50 .to_string()
51 );
52 Headers::from_string(raw)
53 }
54
55 pub fn new_response(status: &Status, list: Vec<Header>) -> Self {
57 let postfix = Headers::to_string(list);
58 let prefix = status.to_full_string();
59 let raw = format!("{prefix}{CRLF}{postfix}");
60 Headers::from_string(raw)
61 }
62
63 pub fn from_string(raw: String) -> Self {
65 let mut res: Headers = Headers {
66 raw: raw.clone(),
67 list: vec![],
68 };
69 let heads = raw.split(CRLF);
70 for h in heads {
71 let reg_name = Regex::new(r"^.+: ").unwrap();
72 let capts_name = reg_name.captures(h);
73 if let None = capts_name {
74 continue;
75 }
76 let capts_name = capts_name.unwrap();
77 let name = capts_name
78 .get(0)
79 .unwrap()
80 .as_str()
81 .to_string()
82 .replace(": ", "");
83
84 let reg_value = Regex::new(r": *.*$").unwrap();
85 let capts_value = reg_value.captures(h);
86 if let None = capts_value {
87 res.list.push(Header {
88 name,
89 value: "".to_string(),
90 });
91 continue;
92 }
93 let capts_value = capts_value.unwrap();
94 let value = capts_value
95 .get(0)
96 .unwrap()
97 .as_str()
98 .to_string()
99 .replace(": ", "");
100 res.list.push(Header { name, value });
101 }
102 res
103 }
104
105 pub fn to_string(list: Vec<Header>) -> String {
107 let mut result = "".to_string();
108 for h in list {
109 result = format!("{result}{}: {}{CRLF}", h.name, h.value);
110 }
111 result = format!("{result}{CRLF}");
112 result
113 }
114
115 pub fn from_bytes(heads: &Vec<u8>) -> Result<Self> {
117 let res = str::from_utf8(heads);
118 if let Err(err) = res {
119 return Err(Error::new(ErrorKind::InvalidInput, err));
120 }
121 let res = res.unwrap().to_string();
122 Ok(Headers::from_string(res))
123 }
124
125 fn change_header(&self, name: &str, value: &str) -> (Vec<Header>, bool) {
126 let mut check = false;
127 let mut new_list: Vec<Header> = vec![];
128 for h in self.list.clone() {
129 if name.to_lowercase() == h.name.as_str().to_lowercase() {
130 new_list.push(Header {
131 name: name.to_string(),
132 value: value.to_string(),
133 });
134 check = true;
135 } else {
136 new_list.push(Header {
137 name: h.name.to_string(),
138 value: h.value.to_string(),
139 });
140 }
141 }
142 (new_list, check)
143 }
144
145 pub fn set_header(&self, name: &str, value: &str) -> Result<Self> {
147 let (mut new_list, check) = self.change_header(name, value);
148 if !check {
149 new_list.push(Header {
150 name: name.to_string(),
151 value: value.to_string(),
152 });
153 }
154
155 let new_h = match self.is_response() {
156 true => {
157 let status = Headers::get_status(&self.raw)?;
158 Headers::new_response(&status, new_list)
159 }
160 false => {
161 let prefix = Headers::get_headers_prefix(&self.raw)?;
162 Headers::new_request(prefix.as_str(), new_list)
163 }
164 };
165
166 Ok(Headers {
167 list: new_h.list,
168 raw: new_h.raw,
169 })
170 }
171
172 pub fn get_content_length(raw: &String) -> Option<u32> {
174 let raw = raw.to_lowercase();
175 let low = Regex::new(r"content-length: *\d+").unwrap().captures(&raw);
176
177 let mut check: Option<&str> = None;
178 if let Some(v) = low {
179 let low = v.get(0).unwrap();
180 check = Some(low.as_str());
181 }
182
183 if let None = check {
184 return None;
185 }
186
187 let cont_len = check.unwrap();
188
189 let num = Regex::new(r"\d+").unwrap().captures(cont_len);
190 if let None = num {
191 return None;
192 }
193 let capts = num.unwrap();
194 let num = capts.get(0);
195 let num_str = num.unwrap().as_str();
196 let num = num_str.parse::<u32>();
197 if let Err(e) = num {
198 println!("Failed parse content lenght from str: {}: {}", num_str, e);
199 return None;
200 }
201 Some(num.unwrap())
202 }
203
204 pub fn get_url(raw: &String) -> String {
206 let reg = Regex::new(r"\/[a-zA-Z0-9_\-\/]*").unwrap();
207 let capts = reg.captures(raw.as_str());
208 if let None = capts {
209 return "/".to_string();
210 }
211 let capts = capts.unwrap();
212 let res = capts.get(0).unwrap().as_str();
213 res.to_string()
214 }
215
216 pub fn get_query(raw: &String) -> String {
218 let reg = Regex::new(r"\?[a-zA-Z0-9_\-&=\.]*").unwrap();
219 let capts = reg.captures(raw.as_str());
220 if let None = capts {
221 return "".to_string();
222 }
223 let capts = capts.unwrap();
224 let res = capts.get(0).unwrap().as_str();
225 res.to_string()
226 }
227
228 pub fn get_chunked(raw: &String) -> bool {
230 let reg = Regex::new(r"transfer-encoding: *chunked").unwrap();
231 let raw = raw.to_lowercase();
232 let capts = reg.captures(raw.as_str());
233
234 if let None = capts {
235 return false;
236 }
237 return true;
238 }
239
240 pub fn get_protocol(raw: &String) -> String {
242 let reg = Regex::new(r"HTTPS?\/\d+\.\d+").unwrap();
243 let capts = reg.captures(raw.as_str());
244 if let None = capts {
245 return "OPTIONS".to_string();
246 }
247 let capts = capts.unwrap();
248 let protocol = capts.get(0).unwrap().as_str();
249 protocol.to_string()
250 }
251
252 fn get_status(raw: &String) -> Result<Status> {
254 let reg = Regex::new(format!(r".+{CRLF}").as_str()).unwrap();
255 let capts = reg.captures(raw.as_str());
256 if let None = capts {
257 return Err(Error::new(
258 ErrorKind::InvalidInput,
259 "Headers prefix didn't find",
260 ));
261 }
262 let capts = capts.unwrap();
263 let result = capts.get(0).unwrap().as_str();
264
265 let result = Regex::new(format!(r"^HTTPS?\/\d+\.\d+ ").as_str())
266 .unwrap()
267 .replace_all(result, "")
268 .to_string();
269
270 let reg = Regex::new(format!(r"^\d+").as_str()).unwrap();
271 let capts = reg.captures(result.as_str());
272 if let None = capts {
273 return Err(Error::new(
274 ErrorKind::InvalidInput,
275 "Headers prefix didn't find",
276 ));
277 }
278 let capts = capts.unwrap();
279 let code = capts.get(0).unwrap().as_str().parse::<u16>();
280 if let Err(err) = code {
281 return Err(Error::new(
282 ErrorKind::InvalidInput,
283 format!("Failed parse status code {:?}", err),
284 ));
285 }
286 let code = code.unwrap();
287
288 let text = Regex::new(format!(r"^\d+ ").as_str())
289 .unwrap()
290 .replace_all(result.as_str(), "")
291 .to_string();
292
293 Ok(Status { code, text })
294 }
295
296 pub fn get_method(raw: &String) -> String {
298 let reg = Regex::new(r"\w+").unwrap();
299 let capts = reg.captures(raw.as_str());
300 if let None = capts {
301 return "OPTIONS".to_string();
302 }
303 let capts = capts.unwrap();
304 let method = capts.get(0).unwrap().as_str();
305 method.to_string()
306 }
307
308 fn get_headers_prefix(raw: &String) -> Result<String> {
310 let reg = Regex::new(format!(r".+{CRLF}").as_str()).unwrap();
311 let capts = reg.captures(raw.as_str());
312 if let None = capts {
313 return Err(Error::new(
314 ErrorKind::InvalidInput,
315 "Headers prefix didn't find",
316 ));
317 }
318 let capts = capts.unwrap();
319 let result = capts.get(0).unwrap().as_str();
320 let result = Regex::new(format!(r"{CRLF}+$").as_str())
321 .unwrap()
322 .replace_all(result, "");
323 Ok(result.to_string())
324 }
325
326 fn is_response(&self) -> bool {
327 let reg = Regex::new(r"^HTTPS?/\d+\.\d+").unwrap();
328 let capts = reg.captures(self.raw.as_str());
329 if let None = capts {
330 return false;
331 }
332 true
333 }
334}