new module to handle parsing parameters from requests

This commit is contained in:
shockrah 2020-06-18 20:10:35 -07:00
parent 63c1fa1137
commit 0b6b5e51c6

84
server/src/http_params.rs Normal file
View File

@ -0,0 +1,84 @@
use hyper::body::{to_bytes, Bytes, HttpBody};
use hyper::Body;
use std::collections::HashMap;
use std::u8;
fn bytes_to_string(bytes: &Bytes) -> String{
let mut ret = String::new();
for b in bytes.iter() {
ret.push(*b as char);
}
ret
}
fn map_qs(query_string_raw: Option<&str>) -> HashMap<&str, &str> {
/*
* Parse a given query string and build a hashmap from it
*/
let mut map: HashMap<&str, &str> = HashMap::new();
if let Some(qs) = query_string_raw {
let raw_pairs: Vec<&str> = qs.split('&').collect();
for raw_pair in raw_pairs.iter() {
let sub_segment: Vec<&str> = raw_pair.split('=').collect();
match sub_segment.len() {
2 => map.insert(sub_segment[0], sub_segment[1]),
_ => continue
};
}
}
map
}
fn parse_body(map: &mut HashMap<&str, &str>, data: String) {
// Line delimited and 1 key value pair per line
//
}
async fn map_body(map: &mut HashMap<&str, &str>, body_raw: &mut Body) {
/*
* Given an http body from Hyper we take the body data and parse out all the
* Parameters given to us up to the first non valid http character
*/
// First we grab a slice of the body data
// next we get a slice up to the first invalid char or the end of the body
// TODO: add some kind of .env limiter so we don't ingest too much data
const NEWLINE: u8 = 0x10;
const PRINTABLE_MIN: u8 = 0x20;
const PRINTABLE_MAX: u8 = 0x7e;
match to_bytes(body_raw).await {
Ok(data) => {
if data.len() == 0 || data.len() > 4096 {
println!("EMPTY BODY");
return;
}
// Assuming we havea reasonable sized body we check
println!("START BODY");
let mut valid = true;
for byte in data.iter() {
match byte {
// only new lines and printable ascii chars are valid in our body
// delete characters are not valid however
&NEWLINE | PRINTABLE_MIN ..= PRINTABLE_MAX => {}
_ => {
valid = false;
break;
}
}
}
if valid {
parse_body(map, bytes_to_string(&data));
}
println!("\nEND BODY")
},
Err(_) => {}
}
}
// NOTE: we only need an async call because map body itself makes asynchronous calls
pub async fn parse_params<'q>(qs_raw: Option<&'q str>, body_raw: &mut Body) -> HashMap<&'q str, &'q str> {
let mut qs_map = map_qs(qs_raw);
map_body(&mut qs_map, body_raw).await;
qs_map
}