diff --git a/src/body.rs b/src/body.rs index af48615..69ec0f4 100644 --- a/src/body.rs +++ b/src/body.rs @@ -1,20 +1,20 @@ -use json; +use json::JsonValue; const NULL_CHAR: &'static str = "\0"; #[derive(Debug)] pub struct HTTPBody { - data: json::JsonValue, + data: JsonValue, } /// HTTPBody represents an HTTP request body -/// for simplicity, only json body is allowed +/// for simplicity, only JSON body is allowed impl HTTPBody { - fn new(data: json::JsonValue) -> HTTPBody { + fn new(data: JsonValue) -> HTTPBody { HTTPBody { data } } - pub fn get_data(&self) -> &json::JsonValue { + pub fn get_data(&self) -> &JsonValue { &self.data } } diff --git a/src/lib.rs b/src/lib.rs index 29e830f..7febb3a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,9 @@ //! //! see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages //! NOTE: only few parts of the specification has been implemented +//! +//! * Only json body allowed +//! * HTTP Headers not parsed mod body; mod request; diff --git a/src/request.rs b/src/request.rs index c7bd800..a193975 100644 --- a/src/request.rs +++ b/src/request.rs @@ -1,3 +1,4 @@ +use json::{object::Object, JsonValue}; use std::collections::VecDeque; use crate::{HTTPBody, HTTPStartLine}; @@ -9,10 +10,8 @@ const HTTP_REQUEST_SEPARATOR: &'static str = "\r\n"; /// HTTPRequest represents an HTTP request (headers are not parsed) #[derive(Debug)] pub struct HTTPRequest<'a> { - pub start_line: HTTPStartLine<'a>, - pub body: Option, - // includes the client IP + port (should be in the headers) - pub addr: String, + start_line: HTTPStartLine<'a>, + body: Option, } impl<'a> HTTPRequest<'a> { @@ -55,6 +54,25 @@ impl<'a> HTTPRequest<'a> { Err(e) => Err(e.to_string()), } } + + /// get_bodyèvalue retrieves JSON value in `HTTPBody` + pub fn get_body_value(&self, key: &str) -> Option { + match self.body { + Some(ref b) => match &b.get_data() { + JsonValue::Object(d) => extract_json_value(&d, key), + _ => None, + }, + None => None, + } + } + + pub fn get_target(&self) -> &str { + self.start_line.get_target() + } + + pub fn get_method(&self) -> &str { + self.start_line.get_method() + } } impl<'a> Default for HTTPRequest<'a> { @@ -62,7 +80,6 @@ impl<'a> Default for HTTPRequest<'a> { HTTPRequest { start_line: HTTPStartLine::default(), body: None, - addr: "".to_string(), } } } @@ -79,6 +96,17 @@ impl<'a> From<&'a str> for HTTPRequest<'a> { } } +/// extract_json_value extracts JSON value from a key +pub fn extract_json_value(data: &Object, key: &str) -> Option { + match data.get(key) { + Some(u) => match u.as_str() { + Some(s) => return Some(s.to_string()), + None => None, + }, + None => None, + } +} + #[test] fn test_request() { struct Expect<'a> { @@ -189,7 +217,6 @@ fn test_request() { for (request, expect) in test_cases { let http_request = HTTPRequest::from(request); - println!("{}", request); assert_eq!(expect.is_valid, http_request.start_line.is_valid()); let start_line: String = http_request.start_line.into(); @@ -203,3 +230,21 @@ fn test_request() { } } } + +#[test] +fn test_extract_json_value() { + let test_cases: [(JsonValue, bool, bool); 3] = [ + (json::parse(r#"{"test": ""}"#).unwrap(), true, true), + (json::parse(r#"{}"#).unwrap(), true, false), + (json::parse(r#"[]"#).unwrap(), false, false), + ]; + + for (value, is_valid, has_key) in test_cases { + match value { + json::JsonValue::Object(d) => { + assert_eq!(has_key, extract_json_value(&d, "test").is_some()); + } + _ => assert!(!is_valid), + } + } +} diff --git a/src/start_line.rs b/src/start_line.rs index 24315da..43289cb 100644 --- a/src/start_line.rs +++ b/src/start_line.rs @@ -42,6 +42,14 @@ impl<'a> HTTPStartLine<'a> { )) } + pub fn get_target(&self) -> &str { + self.target + } + + pub fn get_method(&self) -> &str { + self.method + } + pub fn is_valid(&self) -> bool { return self.method != "" && self.target != "" && self.version != HTTPVersion::Unknown; }