http_rust/
httprequest.rs

1use std::collections::HashMap;
2#[derive(PartialEq, Debug)]
3pub enum Resource{
4    Path(String)
5}
6
7#[derive(PartialEq, Debug)]
8pub struct HttpRequest{
9    pub method: Method,
10    pub version: Version,
11    pub resource: Resource,
12    pub headers: HashMap<String, String>,
13    pub msg_body: String,
14}
15impl From<String> for HttpRequest{
16    fn from(req:String) -> Self
17    {
18        let mut parsed_method = Method::Uninitialized;
19        let mut parsed_version = Version::V1_1;
20        let mut parsed_resource = Resource::Path("".to_string());
21        let mut parsed_headers = HashMap::new();
22        let mut parsed_msg_body = "";
23
24        for line in req.lines()
25        {
26            if line.contains("HTTP")
27            {
28                let (method, resource, version) = process_req_line(line);
29                parsed_method = method;
30                parsed_resource = resource;
31                parsed_version = version;
32            }
33            else if line.contains(":")
34            {
35                let (key, value) = process_req_header(line);
36                parsed_headers.insert(key, value);
37            }
38            else if line.len() == 0
39            {
40
41            }
42            else{
43                parsed_msg_body = line;
44            }
45
46        }
47        HttpRequest{
48            method: parsed_method,
49            version: parsed_version,
50            resource: parsed_resource,
51            headers: parsed_headers,
52            msg_body: parsed_msg_body.to_string(),
53        }
54    }
55}
56
57fn process_req_line(s: &str) ->(Method, Resource, Version)
58{
59    let mut word = s.split_whitespace();
60    let method = word.next().unwrap();
61    let resource = word.next().unwrap();
62    let version = word.next().unwrap();
63    (
64        method.into(),
65        Resource::Path(resource.to_string()),
66        version.into()
67    )
68}
69
70fn process_req_header(s: &str) -> (String, String)
71{
72    let mut header_items = s.split(":");
73    let mut key = String::from("");
74    let mut value = String::from("");
75
76    if let Some(k) = header_items.next(){
77        key = k.to_string();  
78    }
79
80    if let Some(v) = header_items.next()
81    {
82            value = v.to_string();
83    }
84    (key, value)
85}
86
87#[derive(PartialEq)]
88#[derive(Debug)]
89pub enum Method{
90    Get,
91    Post,
92    Uninitialized
93}
94impl From<&str> for Method{
95    fn from(s: &str) -> Method{
96        match s {
97            "GET" => Method::Get,
98            "POST" => Method::Post,
99            _ => Method::Uninitialized,
100        }
101    }
102}
103
104
105#[derive(PartialEq, Debug)]
106pub enum Version{
107    V1_1,
108    V2_0,
109    Uninitialized,
110}
111impl From<&str> for Version{
112    fn from(s: &str) -> Version{
113        match s{
114            "HTTP/1.1" => Version::V1_1,
115            _ => Version::Uninitialized,
116        }
117    }
118}
119
120
121#[cfg(test)]
122
123mod tests{
124    use super::*;
125    #[test]
126    fn test_method_into()
127    {
128        let m: Method = "GET".into();
129        assert_eq!(m, Method::Get);
130    }
131    #[test]
132    fn test_version_into()
133    {
134        let m:Version = "HTTP/1.1".into();
135        assert_eq!(m, Version::V1_1);
136    }
137    #[test]
138    fn test_incoming_http_request()
139    {
140        let s: String = String::from("GET /greeting HTTP/1.1\r\nHost: localhost:3000\r\nUser-Agent: curl/7.64.1\r\nAccept: */*\r\n\r\n");
141    let mut headers_expected = HashMap::new(); 
142    headers_expected.insert("Host".into(), " localhost".into()); 
143    headers_expected.insert("Accept".into(), " */*".into()); 
144    headers_expected.insert("User-Agent".into(), " curl/7.64.1".into());  
145    let req: HttpRequest = s.into();
146        assert_eq!(Method::Get, req.method);
147        assert_eq!(Version::V1_1, req.version);
148        assert_eq!(Resource::Path("/greeting".to_string()), req.resource);
149        assert_eq!(headers_expected, req.headers);
150    }
151}