rusty_web/request/
mod.rs

1use std::collections::HashMap;
2use std::net::TcpStream;
3use std::sync::{Arc};
4use std::sync::atomic::{AtomicBool, Ordering};
5use tempfile::NamedTempFile;
6use crate::headers;
7use crate::headers::{Headers};
8use crate::parser::{body, multipart, url_encoded};
9use crate::parser::body::Limits;
10use crate::parser::body::reader::BodyReader;
11use crate::parser::multipart::{FormPart, MultipartFormDataError};
12use crate::parser::multipart::reader::FormDataReader;
13use crate::parser::url_encoded::{FormFields, UrlEncodedFormDataError};
14use crate::parser::url_encoded::reader::UrlEncodedReader;
15use crate::request::form::{FormFiles, FormData, FormFile};
16use crate::server::Context;
17
18fn map_first_vec_value(map: &HashMap<String, Vec<String>>, key: &str) -> Option<String> {
19    if let Some(values) = map.get(key) {
20        if values.len() > 0 {
21            let value = values.get(0).unwrap();
22            return Some(value.to_owned());
23        }
24    }
25
26    return None;
27}
28
29pub mod form {
30    use std::collections::HashMap;
31    use tempfile::NamedTempFile;
32    use crate::request::map_first_vec_value;
33
34    pub struct FormFile {
35        pub filename: String,
36        pub temp_file: NamedTempFile,
37    }
38
39    pub type MapFirstString = HashMap<String, Vec<String>>;
40
41    pub trait MapFirstStringMethod {
42        fn value(&self, name: &str) -> Option<String>;
43    }
44
45    impl MapFirstStringMethod for MapFirstString {
46        fn value(&self, name: &str) -> Option<String> {
47            return map_first_vec_value(self, name);
48        }
49    }
50
51    pub type FormData = HashMap<String, Vec<String>>;
52    pub type FormFiles = HashMap<String, Vec<FormFile>>;
53
54    pub trait FormFileMethods {
55        fn value(&self, name: &str) -> Option<&FormFile>;
56    }
57
58    impl FormFileMethods for FormFiles {
59        fn value(&self, name: &str) -> Option<&FormFile> {
60            if let Some(values) = self.get(name) {
61                if values.len() > 0 {
62                    let value = values.get(0).unwrap();
63                    return Some(value);
64                }
65            }
66
67            return None;
68        }
69    }
70
71    pub struct File {
72        pub name: String,
73        pub content_type: String,
74    }
75}
76
77pub type QueryParams = HashMap<String, Vec<String>>;
78
79pub struct Request {
80    pub context: Arc<Context>,
81    pub stream: TcpStream,
82    pub method: String,
83    pub raw_path: String,
84    pub pathname: String,
85    pub query_params: QueryParams,
86    pub headers: Headers,
87    pub partial_body: Option<Vec<u8>>,
88    form_data: FormData,
89    form_files: FormFiles,
90    /// It specifies that body has been read already either some part or all.
91    /// If body read is true, but body parse is false, need to change current connection to "keep-alive: close"
92    /// It is because parsing body is probably failed.
93    pub body_read: Arc<AtomicBool>,
94    pub body_parsed: Arc<AtomicBool>,
95}
96
97impl Request {
98    pub fn new(context: Arc<Context>, stream: TcpStream, request_method: String, raw_path: String,
99               headers: HashMap<String, Vec<String>>, body_read: Arc<AtomicBool>,
100               body_parsed: Arc<AtomicBool>) -> Self {
101        let form_data = FormData::new();
102        let form_files = FormFiles::new();
103
104        let pathname = Self::pathname_from_raw(&raw_path);
105        let query_params = headers::query_params_from_raw(&raw_path);
106
107        return Request {
108            context,
109            stream,
110            method: request_method,
111            raw_path,
112            pathname,
113            query_params,
114            headers,
115            partial_body: None,
116            form_data,
117            form_files,
118            body_read,
119            body_parsed,
120        };
121    }
122
123    fn pathname_from_raw(raw_path: &String) -> String {
124        if let Some(index) = raw_path.find("?") {
125            let slice = &raw_path.as_str()[0..index];
126            return slice.to_string();
127        }
128
129        return raw_path.to_string();
130    }
131
132    pub fn setup(&mut self) {
133        let content_length = headers::content_length(&self.headers);
134        let request_method = self.method.to_uppercase();
135
136        if matches!(request_method.as_str(), "GET" | "HEAD" | "OPTIONS" | "DELETE" | "TRACE" | "CONNECT") {
137            // Same connections can be used fot these requests since there is no request body
138            if !content_length.is_some() {
139                // Content length is missing. Assuming there is no request body
140                self.body_read.store(true, Ordering::Relaxed);
141            }
142        }
143    }
144
145
146    pub fn set_partial_body_bytes(&mut self, bytes: Vec<u8>) {
147        self.partial_body = Some(bytes);
148    }
149
150    pub fn should_close_connection(&self) -> bool {
151        let connection_type = headers::connection_type(&self.headers);
152
153        if let Some(connection_type) = &connection_type {
154            if connection_type.to_lowercase() == "keep-alive" && self.body_read.load(Ordering::Relaxed) {
155                return false;
156            }
157        }
158
159        return true;
160    }
161
162    pub fn body(&mut self) -> Option<NamedTempFile> {
163        if self.body_read.load(Ordering::Relaxed) {
164            eprintln!("Body already read");
165            return None;
166        }
167
168        let content_length = headers::content_length(&self.headers);
169
170        if !content_length.is_some() {
171            eprintln!("Content-Length header is missing");
172            return None;
173        }
174
175        let cloned_stream = self.stream.try_clone();
176        if !cloned_stream.is_ok() {
177            eprintln!("Failed to clone stream");
178            return None;
179        }
180
181        let limits = Limits {
182            max_body_size: 512 * 1024 * 1024, // 512 MiB
183        };
184
185        let mut partial_bytes: Vec<u8> = Vec::new();
186        if let Some(partial) = self.partial_body.as_mut() {
187            partial_bytes.extend(partial.clone());
188            partial.clear();
189        }
190
191        let reader = BodyReader::new(cloned_stream.unwrap(), content_length.unwrap(),
192                                     partial_bytes.len(), limits);
193
194        let parse_result = body::parse(
195            partial_bytes,
196            &self.headers,
197            reader,
198        );
199
200        self.body_read.store(true, Ordering::Relaxed);
201
202        match parse_result {
203            Ok(temp_file) => {
204                self.body_parsed.store(true, Ordering::Relaxed);
205                return Some(temp_file);
206            }
207
208            Err(error) => {
209                eprintln!("Error: {:?}", error);
210            }
211        }
212
213        return None;
214    }
215
216    pub fn form_data(&mut self) -> &mut FormData {
217        if !self.body_read.load(Ordering::Relaxed) {
218            self.parse_request_body();
219        }
220        return &mut self.form_data;
221    }
222
223    pub fn files(&mut self) -> &mut FormFiles {
224        if !self.body_read.load(Ordering::Relaxed) {
225            self.parse_request_body();
226        }
227
228        return &mut self.form_files;
229    }
230
231    pub fn parse_request_body(&mut self) {
232        let content_type = headers::extract_content_type(&self.headers);
233
234        // Silently return success empty form data if it does not have body
235        if !content_type.is_some() {
236            // Empty form data
237            let content_length = headers::content_length(&self.headers);
238
239            if content_length.is_some() && content_length.unwrap() > 0 {
240                eprintln!("Body has content, but missing content type.");
241            }
242
243            return;
244        }
245
246        let content_type_binding = content_type.unwrap();
247        let content_type_value = content_type_binding.trim();
248        let content_length = headers::content_length(&self.headers);
249
250        if content_type_value.starts_with("multipart/form-data;") {
251            const MAX_BODY_SIZE: usize = 512 * 1024 * 1024; // 512 MiB
252            const MAX_HEADER_SIZE: usize = 1024 * 1024; // 1 MiB
253            const MAX_VALUE_SIZE: usize = 2 * 1024; // 1 MiB
254
255            let limits = multipart::Limits {
256                max_body_size: Some(MAX_BODY_SIZE),
257                max_header_size: Some(MAX_HEADER_SIZE),
258                max_value_size: Some(MAX_VALUE_SIZE),
259                form_part_limits: HashMap::new(),
260            };
261
262            let result = self.multipart_form_data(
263                content_type_value.to_string(),
264                content_length,
265                limits,
266            );
267
268            // Body read but yet don't know result.
269            self.body_read.store(true, Ordering::Relaxed);
270
271            match result {
272                Ok(form_parts) => {
273                    let (form_data, form_files) = self.multipart_form_data_and_files(form_parts);
274                    // Set body parsed to true
275                    self.body_parsed.store(true, Ordering::Relaxed);
276                    self.form_data = form_data;
277                    self.form_files = form_files;
278                }
279
280                Err(error) => {
281                    self.body_parsed.store(true, Ordering::Relaxed);
282                    eprintln!("Error: {:?}", error);
283                }
284            }
285        } else if content_type_value.starts_with("application/x-www-form-urlencoded") {
286            let limits = url_encoded::Limits {
287                max_body_size: 2 * 1024 * 1024 // 2 MiB
288            };
289
290            if !content_length.is_some() {
291                // Content-Length header is required for "application/x-www-form-urlencoded"
292                eprintln!("Content-Length is missing.");
293                return;
294            }
295
296            let result = self.parse_url_encoded(
297                content_length.unwrap(),
298                limits,
299            );
300            self.body_read.store(true, Ordering::Relaxed);
301
302            match result {
303                Ok(form_fields) => {
304                    self.body_parsed.store(true, Ordering::Relaxed);
305                    self.form_data = form_fields;
306                }
307
308                Err(error) => {
309                    eprintln!("Error: {:?}", error);
310                }
311            }
312        }
313    }
314
315    pub fn multipart_form_data(&mut self, content_type: String, content_length: Option<usize>,
316                               limits: multipart::Limits) -> Result<Vec<FormPart>, MultipartFormDataError> {
317        let boundary = multipart::extract_boundary(&content_type);
318        if !boundary.is_some() {
319            return Err(MultipartFormDataError::Others("Boundary is missing from Content-Type"));
320        }
321
322        // Copy partial body which was read unintentionally
323        let partial_body;
324        if let Some(partial) = self.partial_body.as_mut() {
325            partial_body = partial.clone();
326            partial.clear();
327        } else {
328            partial_body = Vec::new();
329        }
330
331        return match self.stream.try_clone() {
332            Ok(cloned_stream) => {
333                // This will work as source of data
334                let reader = FormDataReader::new(
335                    cloned_stream,
336                    boundary.unwrap(),
337                    content_length,
338                    partial_body.len(),
339                );
340
341                multipart::parse(
342                    partial_body,
343                    &self.headers,
344                    reader,
345                    limits,
346                )
347            }
348            Err(_) => {
349                Err(MultipartFormDataError::Others("Failed to copy stream"))
350            }
351        };
352    }
353
354    pub fn parse_url_encoded(&mut self, content_length: usize, limits: url_encoded::Limits)
355                             -> Result<FormFields, UrlEncodedFormDataError> {
356        let mut partial_bytes = Vec::new();
357
358        if let Some(partial_body) = self.partial_body.as_mut() {
359            partial_bytes.extend(partial_body.clone());
360            partial_body.clear();
361        }
362
363        let cloned_stream = self.stream.try_clone().expect("Failed to clone stream");
364        let mut reader = UrlEncodedReader::new(
365            cloned_stream,
366            content_length,
367            partial_bytes.len(),
368        );
369
370        return url_encoded::parse(partial_bytes, &self.headers, &mut reader, limits);
371    }
372
373    pub fn multipart_form_data_and_files(&self, form_parts: Vec<FormPart>) -> (FormData, FormFiles) {
374        let mut form_data = FormData::new();
375        let mut form_files = FormFiles::new();
376
377        for form_part in form_parts {
378            if !form_part.name.is_some() {
379                continue;
380            }
381
382
383            if form_part.value.is_some() {
384                // It is field value
385
386                let name = form_part.name.unwrap();
387                if !form_data.contains_key(&name) {
388                    let vec = Vec::new();
389                    form_data.insert(name.clone(), vec);
390                }
391
392                let values = form_data.get_mut(&name).unwrap();
393                let value_bytes = form_part.value.expect("Error in value parsing");
394                let value = String::from_utf8_lossy(value_bytes.as_slice());
395                values.push(value.to_string());
396            } else if form_part.filename.is_some() {
397                // It is file type
398                let name = form_part.name.unwrap();
399                if !form_files.contains_key(&name) {
400                    let vec = Vec::new();
401                    form_files.insert(name.clone(), vec);
402                }
403
404                let values = form_files.get_mut(&name).unwrap();
405                let temp_file = form_part.temp_file;
406
407                let filename = form_part.filename.expect("Error in parsing file body. At least expected filename.");
408                let temp_file = temp_file.expect("Error in parsing file body. At least expected one temp file.");
409                let form_file = FormFile {
410                    filename,
411                    temp_file,
412                };
413
414                values.push(form_file);
415            }
416        }
417
418        return (form_data, form_files);
419    }
420}
421
422impl Clone for Request {
423    fn clone(&self) -> Self {
424        return Request {
425            context: self.context.clone(),
426            stream: self.stream.try_clone().unwrap(),
427            method: self.method.clone(),
428            raw_path: self.raw_path.clone(),
429            pathname: self.pathname.clone(),
430            query_params: self.query_params.clone(),
431            headers: self.headers.clone(),
432            partial_body: self.partial_body.clone(),
433            // We are not copying value field and files
434            form_data: FormData::new(),
435            form_files: FormFiles::new(),
436            body_read: self.body_read.clone(),
437            body_parsed: self.body_parsed.clone(),
438        };
439    }
440}
441
442