1use std::{collections::HashMap, io::BufRead};
2
3const HOST: &str = "Host";
4
5#[derive(Debug)]
6pub enum Body {
7 Empty,
8}
9
10#[derive(Debug)]
12pub struct Request {
13 pub method: String,
14 pub version: String,
15 pub headers: HashMap<String, String>,
16 pub url_raw: String,
17 pub url: urlparse::Url,
18 pub body: Body,
19 pub raw_data: Vec<u8>,
20 pub host: String,
21 pub port: i32,
22}
23
24impl Request {
25 pub fn new() -> Self {
26 Request::default()
27 }
28}
29
30impl Default for Request {
31 fn default() -> Self {
32 Request {
33 method: String::default(),
34 version: String::default(),
35 headers: HashMap::default(),
36 url_raw: String::default(),
37 url: urlparse::Url::new(),
38 body: Body::Empty,
39 raw_data: Vec::default(),
40 host: String::default(),
41 port: 0,
42 }
43 }
44}
45
46impl From<Vec<u8>> for Request {
47 fn from(buffer: Vec<u8>) -> Self {
48 let cursor = std::io::Cursor::new(&buffer);
51 let mut lines_iter = cursor.lines().map(|l| l.unwrap());
52 let first_line = lines_iter.next().unwrap();
53 let first_line_vec: Vec<&str> = first_line.split(' ').collect();
54 let method = first_line_vec.get(0).unwrap().to_string();
55 let url_raw = first_line_vec.get(1).unwrap().to_string();
56 let version = first_line_vec.get(2).unwrap().to_string();
57 let headers = get_request_headers(&mut lines_iter);
58 let body = Body::Empty;
59 let url = urlparse::urlparse(&url_raw);
60 let mut host: String = headers.get(HOST).unwrap().into();
61 let mut port = if method == "CONNECT" { 443 } else { 80 };
62
63 if host.contains(':') {
64 let index = host.find(':').unwrap();
65 host = host[..index].to_string();
66 port = host[index + 1..].parse().unwrap(); }
68
69 Request {
70 method,
71 url_raw,
72 url,
73 version,
74 headers,
75 body,
76 raw_data: buffer,
77 host,
78 port,
79 }
80 }
81}
82
83pub fn get_request_headers(
84 lines_iter: &mut impl Iterator<Item = String>,
85) -> HashMap<String, String> {
86 let mut headers = HashMap::new();
87
88 loop {
89 match lines_iter.next() {
90 None => break,
91 Some(line) => {
92 if line.is_empty() {
94 break;
95 }
96 let header_line_vec: Vec<String> = line.split(':').map(|x| x.to_string()).collect();
97 let header_key = header_line_vec.get(0).unwrap().to_string();
98 let header_value = header_line_vec.get(1).unwrap().trim().to_string();
99 headers.insert(header_key, header_value);
100 }
101 }
102 }
103 headers
104}