fix encapsulation by adding getters + add json extraction value function

This commit is contained in:
landrigun 2023-02-15 13:34:02 +00:00
parent 0c7b0bec12
commit ad4fdc300d
4 changed files with 67 additions and 11 deletions

View File

@ -1,20 +1,20 @@
use json; use json::JsonValue;
const NULL_CHAR: &'static str = "\0"; const NULL_CHAR: &'static str = "\0";
#[derive(Debug)] #[derive(Debug)]
pub struct HTTPBody { pub struct HTTPBody {
data: json::JsonValue, data: JsonValue,
} }
/// HTTPBody represents an HTTP request body /// HTTPBody represents an HTTP request body
/// for simplicity, only json body is allowed /// for simplicity, only JSON body is allowed
impl HTTPBody { impl HTTPBody {
fn new(data: json::JsonValue) -> HTTPBody { fn new(data: JsonValue) -> HTTPBody {
HTTPBody { data } HTTPBody { data }
} }
pub fn get_data(&self) -> &json::JsonValue { pub fn get_data(&self) -> &JsonValue {
&self.data &self.data
} }
} }

View File

@ -3,6 +3,9 @@
//! //!
//! see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages //! see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages
//! NOTE: only few parts of the specification has been implemented //! NOTE: only few parts of the specification has been implemented
//!
//! * Only json body allowed
//! * HTTP Headers not parsed
mod body; mod body;
mod request; mod request;

View File

@ -1,3 +1,4 @@
use json::{object::Object, JsonValue};
use std::collections::VecDeque; use std::collections::VecDeque;
use crate::{HTTPBody, HTTPStartLine}; 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) /// HTTPRequest represents an HTTP request (headers are not parsed)
#[derive(Debug)] #[derive(Debug)]
pub struct HTTPRequest<'a> { pub struct HTTPRequest<'a> {
pub start_line: HTTPStartLine<'a>, start_line: HTTPStartLine<'a>,
pub body: Option<HTTPBody>, body: Option<HTTPBody>,
// includes the client IP + port (should be in the headers)
pub addr: String,
} }
impl<'a> HTTPRequest<'a> { impl<'a> HTTPRequest<'a> {
@ -55,6 +54,25 @@ impl<'a> HTTPRequest<'a> {
Err(e) => Err(e.to_string()), Err(e) => Err(e.to_string()),
} }
} }
/// get_bodyèvalue retrieves JSON value in `HTTPBody`
pub fn get_body_value(&self, key: &str) -> Option<String> {
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> { impl<'a> Default for HTTPRequest<'a> {
@ -62,7 +80,6 @@ impl<'a> Default for HTTPRequest<'a> {
HTTPRequest { HTTPRequest {
start_line: HTTPStartLine::default(), start_line: HTTPStartLine::default(),
body: None, 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<String> {
match data.get(key) {
Some(u) => match u.as_str() {
Some(s) => return Some(s.to_string()),
None => None,
},
None => None,
}
}
#[test] #[test]
fn test_request() { fn test_request() {
struct Expect<'a> { struct Expect<'a> {
@ -189,7 +217,6 @@ fn test_request() {
for (request, expect) in test_cases { for (request, expect) in test_cases {
let http_request = HTTPRequest::from(request); let http_request = HTTPRequest::from(request);
println!("{}", request);
assert_eq!(expect.is_valid, http_request.start_line.is_valid()); assert_eq!(expect.is_valid, http_request.start_line.is_valid());
let start_line: String = http_request.start_line.into(); 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),
}
}
}

View File

@ -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 { pub fn is_valid(&self) -> bool {
return self.method != "" && self.target != "" && self.version != HTTPVersion::Unknown; return self.method != "" && self.target != "" && self.version != HTTPVersion::Unknown;
} }