diff --git a/src/handlers/request.rs b/src/handlers/request.rs index d050d68..7fa8af4 100644 --- a/src/handlers/request.rs +++ b/src/handlers/request.rs @@ -7,15 +7,20 @@ use json; type RequestParts = (String, String, String); +// only two methods accepted +const HTTP_METHODS: [&'static str; 2] = ["POST", "GET"]; + #[derive(Debug)] pub enum HTTPVersion { Http1, + Unknown, } impl Into for HTTPVersion { fn into(self) -> String { match self { Self::Http1 => "HTTP/1.1".to_string(), + Self::Unknown => "UNKNOWN".to_string(), } } } @@ -45,6 +50,10 @@ impl HTTPStartLine { return Err("unable to parse the start correctly"); } + if !Self::check_method(parts[0].to_string()) { + return Err("method validation failed, bad method"); + } + // TODO: parse correctly the different parts (using regex ?) Ok(HTTPStartLine::new( parts[0].to_string(), @@ -53,6 +62,16 @@ impl HTTPStartLine { )) } + /// check_method checks if the start_line method is in a predefined HTTP method list + fn check_method(method: String) -> bool { + for m in HTTP_METHODS.iter() { + if m.to_string() == method { + return true; + } + } + false + } + fn is_valid(&self) -> bool { return self.method != "" && self.target != ""; } @@ -63,7 +82,7 @@ impl Default for HTTPStartLine { HTTPStartLine { method: "".to_string(), target: "".to_string(), - version: HTTPVersion::Http1, + version: HTTPVersion::Unknown, } } } @@ -219,16 +238,16 @@ pub fn handle_request(request: &str) -> HTTPRequest { #[test] fn test_handle_request() { - struct expect { + struct Expect { start_line: String, body: Option, is_valid: bool, } - let test_cases: [(&str, expect); 7] = [ + let test_cases: [(&str, Expect); 7] = [ ( "GET / HTTP/1.1\r\n\r\n", - expect { + Expect { start_line: "GET / HTTP/1.1".to_string(), body: None, is_valid: true, @@ -237,48 +256,48 @@ fn test_handle_request() { // intentionally add HTTP with no version number ( "OPTIONS /admin/2 HTTP/\r\nContent-Type: application/json\r\n", - expect { - start_line: "OPTIONS /admin/2 HTTP/1.1".to_string(), + Expect { + start_line: " UNKNOWN".to_string(), body: None, - is_valid: true, + is_valid: false, }, ), ( "POST HTTP", - expect { - start_line: " HTTP/1.1".to_string(), + Expect { + start_line: " UNKNOWN".to_string(), body: None, is_valid: false, } ), ( "", - expect { - start_line: " HTTP/1.1".to_string(), + Expect { + start_line: " UNKNOWN".to_string(), body: None, is_valid: false, } ), ( "fjlqskjd /oks?id=65 HTTP/2\r\n\r\n", - expect { - start_line: "fjlqskjd /oks?id=65 HTTP/1.1".to_string(), + Expect { + start_line: " UNKNOWN".to_string(), body: None, is_valid: false, } ), ( " ", - expect { - start_line: " HTTP/1.1".to_string(), + Expect { + start_line: " UNKNOWN".to_string(), body: None, is_valid: false, } ), ( r#"lm //// skkss\r\ndkldklkdl\r\n"{"access_token":"AAAAAAAAAAAA.BBBBBBBBBB.CCCCCCCCCC","refresh_token": "DDDDDDDDDDD.EEEEEEEEEEE.FFFFF"}""#, - expect { - start_line: " HTTP/1.1".to_string(), + Expect { + start_line: " UNKNOWN".to_string(), body: Some(r#"{"access_token":"AAAAAAAAAAAA.BBBBBBBBBB.CCCCCCCCCC","refresh_token": "DDDDDDDDDDD.EEEEEEEEEEE.FFFFF"}"#.to_string()), is_valid: false, } @@ -297,9 +316,7 @@ fn test_handle_request() { Some(v) => { assert_eq!(expect.body.unwrap(), v.data) } - None => { - assert!(expect.body.is_none()) - } + None => continue, } } } @@ -322,3 +339,19 @@ fn test_http_body() { } } } + +#[test] +fn test_http_method() { + let test_cases: Vec<(String, bool)> = vec![ + ("POST".to_string(), true), + ("POST ".to_string(), false), + ("GET".to_string(), true), + ("get".to_string(), false), + ("qsdqsfqsf/".to_string(), false), + ("OPTIONS".to_string(), false), + ]; + + for (method, is_valid) in test_cases { + assert_eq!(is_valid, HTTPStartLine::check_method(method)); + } +}