1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use crate::request;
use std::collections::HashMap;
use std::io::{BufRead, BufReader, Read};
use std::net::TcpStream;
pub struct HttpParser {}
impl HttpParser {
pub fn parse(stream: &TcpStream) -> Result<request::Request, String> {
let mut reader = BufReader::new(stream);
let mut http_request_line = String::new();
let _result = reader.by_ref().read_line(&mut http_request_line);
let http_request_line_split: Vec<&str> = http_request_line.split_whitespace().collect();
if http_request_line_split.len() != 3 {
return Err(format!(
"Request line not correct syntax: {}",
http_request_line
));
}
let mut http_request_headers = HashMap::new();
for line_result in reader.by_ref().lines() {
let line = match line_result {
Ok(line_string) => line_string,
Err(_error) => String::from("ERROR"),
};
if line == "" {
break;
}
if line == "ERROR" {
return Err(String::from("Failed to read line from TCP stream"));
}
let mut iter = line.split(": ");
let key = match iter.next() {
Some(result) => result,
None => "Error: no key",
};
if key == "Error: no key" {
return Err(String::from("Faulty request syntax, could not parse"));
}
let value = match iter.next() {
Some(result) => result,
None => "Error: no value",
};
if value == "Error: no value" {
return Err(String::from("Faulty request syntax, could not parse"));
}
http_request_headers.insert(key.to_lowercase(), String::from(value));
}
let mut body = String::from("");
if http_request_headers.contains_key("content-length") {
let body_length: i32 = match http_request_headers["content-length"].parse() {
Ok(result) => result,
Err(_error) => -1,
};
if body_length < 0 {
return Err(String::from("Invalid content-legth header"));
}
let mut body_bytes = vec![0; body_length as usize];
let result = reader.by_ref().read_exact(&mut body_bytes);
let fail = match result {
Ok(_result) => false,
Err(_error) => true,
};
if fail {
return Err(String::from("Read request body failed"));
}
for char_byte in body_bytes {
body.push(char_byte as char);
}
}
let params_split: Vec<&str> = http_request_line_split[1].split("?").collect();
let mut parameters = HashMap::new();
if params_split.len() > 1 {
let parameters_vec: Vec<&str> = params_split[1].split("&").collect();
for parameter in parameters_vec {
let parameter_split: Vec<&str> = parameter.split("=").collect();
if parameter_split.len() > 1 {
parameters.insert(
String::from(parameter_split[0]),
String::from(parameter_split[1]),
);
}
}
}
let mut http_version = String::from("1.1");
let version_split: Vec<&str> = http_request_line_split[2].split("/").collect();
if version_split.len() > 1 {
http_version = String::from(version_split[1]);
}
Ok(request::Request::new(
String::from(http_request_line_split[1]),
parameters,
body,
http_version,
String::from(http_request_line_split[0]),
http_request_headers,
))
}
}