http_server_rs/
httpreader.rs

1use std::{collections::BTreeMap, io::{Error, Read, Write}, net::{SocketAddr, TcpStream}, time::Duration};
2use crate::httperror::*;
3
4use crate::{httpconstants::HttpConstants, httperror::HttpErrorWrapper};
5
6pub struct HttpReader {
7    req_method : String,
8    req_path : String,
9    req_protocol : String,
10    req_headers : BTreeMap<String, String>,
11    req_lines : BTreeMap<i32, String>,
12    req_body : BTreeMap<i32, u8>,
13    response_headers : BTreeMap<String, String>,
14    sent_headers : bool,
15    tcpstream : TcpStream,
16    max_client_timeout_ms : u64,
17}
18
19#[allow(dead_code)]
20impl HttpReader {
21    pub fn new(tcpstream : TcpStream, max_client_timeout_ms : u64) -> Result<HttpReader, HttpErrorWrapper> {
22        let mut this = HttpReader {
23            req_method: String::from(""),
24            req_path : String::from(""),
25            req_protocol : String::from(""),
26            req_headers : BTreeMap::new(),
27            req_lines : BTreeMap::new(),
28            req_body : BTreeMap::new(),
29            response_headers : BTreeMap::new(),
30            sent_headers : false,
31            tcpstream,
32            max_client_timeout_ms,
33        };
34        let result = this.read_lines();
35        if result.is_some() {
36            return Result::Err(result.unwrap());
37        } else {
38            return Result::Ok(this);   
39        }
40
41    }
42
43    fn read_lines(&mut self) -> Option<HttpErrorWrapper> {
44        
45        let mut had_first_line = false;
46        let mut current_str : Vec<u8> = Vec::new();
47        let mut index = 0;
48        let mut buf = [0u8];
49        let stream = &mut self.tcpstream;
50        stream.set_read_timeout(Some(Duration::from_millis(self.max_client_timeout_ms))).unwrap();
51        loop {
52
53            let result = stream.read(&mut buf);
54            if result.is_err() {
55                return Option::Some(INCOMPLETE_REQUEST.to_wrapped_respond(stream));
56            } else if result.unwrap() == 0 {
57                return Option::Some(CLIENT_TIMEOUT.to_wrapped_respond(stream));
58            }
59
60            let character = buf[0];
61            current_str.push(character);
62            if character as char != '\n' {
63                continue;
64            }
65
66            if current_str.len() == 2 {// empty line after http headers or before first line
67                current_str.clear();
68                if !had_first_line {
69                    continue;
70                } else {
71                    break;
72                }
73            } else {
74                let str = String::from_utf8_lossy(current_str.clone().as_slice()).to_string();
75                self.req_lines.insert(index, str);
76                index = index + 1;
77                current_str.clear();
78                had_first_line = true;
79            }
80            
81        }
82        
83        let mut start_line_iterator = self.req_lines.get(&0).unwrap().split_whitespace();
84        let mut had_request_error = false;
85        let method = start_line_iterator.next();
86        if method.is_none() {
87            had_request_error = true;
88        } else {
89            self.req_method = method.unwrap().to_string();
90        }
91        let path = start_line_iterator.next();
92        if path.is_none() {
93            had_request_error = true;
94        } else {
95            self.req_path = path.unwrap().to_string();
96        }
97        let protocol = start_line_iterator.next();
98        if protocol.is_none() {
99            had_request_error = true;
100        } else {
101            self.req_protocol = protocol.unwrap().to_string();
102        }
103        if had_request_error {
104            return Option::Some(BAD_REQUEST_LINE.to_wrapped_respond(stream));
105        }
106
107        let mut i = 1;
108        let len = self.req_lines.len();
109        while i < len {
110            let unsafe_header = self.req_lines.get(&(i as i32))
111                .unwrap()
112                .split_once(": ");
113            if unsafe_header.is_none() {
114                return Option::Some(INCORRECT_HEADER_FORMAT.to_wrapped_respond(stream));
115            }
116            let header = unsafe_header
117                .unwrap();
118            
119            let key = header.0;
120            
121            let value = header.1;
122            let value = value.split_at(value.len() - 2).0; // remove newline
123            
124            self.req_headers.insert(key.to_string().to_lowercase(), value.to_string());
125            i += 1;
126        }        
127        
128        let content_length = self.req_headers.get("content-length");
129        if content_length.is_some() {
130            let unwrapped_length = content_length.unwrap();
131            let parsed = usize::from_str_radix(unwrapped_length, 10);
132            if parsed.is_err() { // this checks for negative values as well
133                return Option::Some(INCORRECT_CONTENT_LENGTH.to_wrapped_respond(stream));
134            }
135            let amount_to_read = parsed.unwrap();
136            if amount_to_read != 0 {
137                let mut buf: Vec<u8> = Vec::new();
138                buf.resize(amount_to_read, 0);
139                let buf = buf.as_mut_slice();
140                
141                let result = stream.read(buf);
142                
143                if result.is_err() || result.unwrap() != amount_to_read {
144                    return Option::Some(INCOMPLETE_BODY.to_wrapped_respond(stream));
145                }
146                
147                for i in 0..amount_to_read  {
148                    self.req_body.insert(i as i32, *buf.get(i).unwrap());
149                }
150            }            
151        }
152        
153        let _body = String::from_utf8_lossy(self.get_request_body().as_slice()).to_string();
154        
155        return Option::None;
156        
157    }
158    
159    pub fn get_peer_address(&self) -> Result<SocketAddr, Error> {
160        return self.tcpstream.peer_addr();
161    }
162        
163    pub fn get_local_address(&self) -> Result<SocketAddr, Error> {
164        return self.tcpstream.local_addr();
165    }
166    
167    pub fn borrow_stream(&mut self) -> &mut TcpStream {
168        return &mut self.tcpstream;
169    }
170    
171    pub fn consume_stream(self) -> TcpStream {
172        return self.tcpstream;
173    }
174    
175    pub fn respond_404(&self) {
176        ENDPOINT_NOT_FOUND.to_wrapped_respond(&self.tcpstream);
177    }
178    
179    // request
180    pub fn get_request_method(&self) -> String {
181        return self.req_method.to_string();
182    }
183
184    pub fn get_request_path(&self) -> String {
185        return self.req_path.to_string();
186    }
187
188    pub fn get_request_protocol(&self) -> String {
189        return self.req_protocol.to_string();
190    }
191
192    pub fn get_request_headers(&mut self) -> &mut BTreeMap<String, String> {
193        return &mut self.req_headers;
194    }
195    
196    pub fn get_request_body(&self) -> Vec<u8> {
197        return self.req_body.values().cloned().collect();
198    }
199    
200    // response
201    pub fn get_response_headers(&mut self) -> &mut BTreeMap<String, String> {
202        return &mut self.response_headers;
203    }
204    
205    pub fn add_cross_origin_resource_sharing_headers(&mut self) {
206        let response = self.get_response_headers();
207        response.insert(String::from("Access-Control-Allow-Origin"), String::from("*"));
208        response.insert(String::from("Access-Control-Allow-Headers"), String::from("Origin, X-Requested-With, Content-Type, Accept, Authorization"));
209        response.insert(String::from("Access-Control-Allow-Methods"), String::from("GET, OPTIONS, HEAD, PUT, POST"));
210        response.insert(String::from("Access-Control-Allow-Credentials"), String::from("true"));
211    }
212    
213    pub fn write_response_headers(&mut self, response_code : i32, body_length : usize) -> Result<usize, Error> {
214        
215        if self.sent_headers {
216            return Ok(0);
217        }
218        
219        let start_line = "HTTP/1.1 ".to_owned() + response_code.to_string().as_str() + HttpConstants::get_code_text(response_code) + "\r\n";
220        
221        let response_headers = self.get_response_headers();
222        response_headers.insert("Content-Length".to_string(), body_length.to_string());
223        response_headers.insert("Date".to_string(), HttpConstants::get_current_formatted_date());
224        
225        let mut response_bytes : Vec<u8> = Vec::new();
226        response_bytes.append(&mut start_line.clone().into_bytes());
227        for entry in response_headers {
228            response_bytes.append(&mut entry.0.clone().into_bytes());
229            response_bytes.append(&mut ": ".to_string().into_bytes());
230            response_bytes.append(&mut entry.1.clone().into_bytes());
231            response_bytes.append(&mut "\r\n".to_string().into_bytes());
232        }
233        response_bytes.append(&mut "\r\n".to_string().into_bytes());
234        
235        let result = self.tcpstream.write(response_bytes.as_mut_slice());
236        
237        self.sent_headers = true;
238        
239        return result;
240    }
241    
242    pub fn write_response_body(&mut self, body : &[u8]) -> Result<usize, Error> {
243        return self.tcpstream.write(body);
244    }
245    
246    pub fn get_tcpstream(&mut self) -> &mut TcpStream {
247        return &mut self.tcpstream;
248    }
249    
250}