rserver/
request.rs

1use std::{collections::HashMap, io::BufRead};
2
3const HOST: &str = "Host";
4
5#[derive(Debug)]
6pub enum Body {
7    Empty,
8}
9
10/// RServer's Request struct.
11#[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 reader = buffer.reader();
49        // let mut lines = reader.lines();
50        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(); //  skip colon (':') char
67        }
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                // println!("line: {:?}", line);
93                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}