diff --git a/src/http/requests.rs b/src/http/requests.rs index 2e0258b..6111a3e 100644 --- a/src/http/requests.rs +++ b/src/http/requests.rs @@ -1,12 +1,38 @@ use std::collections::HashMap; -struct Path<'a> { - pub query: HashMap<&'a str, &'a str> +pub struct URL<'a> { + pub raw: &'a str, + pub path: &'a str, + pub query: HashMap<&'a str, &'a str>, } -impl Path { - pub fn new<'a>(path: &'a str) -> Self { - let query = path.split("?").collect(); - Path { query } - } -} \ No newline at end of file +impl<'a> URL<'a> { + pub fn new(url: &'a str) -> Option { + let raw = url; + + // Query string parsing + let mut query = HashMap::new(); + let mut split = url.split('?'); + let path = split.nth(0)?; + let query_string = split.next(); + + for pair in query_string.unwrap_or("").split('&') { + let mut key_value = pair.split('='); + let key = match key_value.next() { + Some(key) => key, + None => continue, + }; + let value = key_value.next().unwrap_or(""); + query.insert(key, value); + } + + // Drop trailing slash but not for root path + let path = if path.ends_with("/") && path.len() > 1 { + &path[..path.len() - 1] + } else { + path + }; + + Some(URL { raw, path, query }) + } +} diff --git a/src/main.rs b/src/main.rs index 1734f9e..9322b4c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,7 @@ use std::{ }; use ctrlc; +use http::requests::URL; mod http; @@ -49,19 +50,26 @@ fn handle_connection(mut stream: TcpStream) { return; } - let (method, path) = (request_line_parts[0], request_line_parts[1]); + let (method, url_str) = (request_line_parts[0], request_line_parts[1]); if method != "GET" { http::responses::send_405(stream).unwrap_or_else(|_| error("Failed to send 405 response")); return; } - let path = if path.ends_with("/") { - &path[..path.len() - 1] - } else { - path + let url = match http::requests::URL::new(url_str) { + Some(path) => path, + None => { + http::responses::send_400(stream) + .unwrap_or_else(|_| error("Failed to send 400 response")); + return; + } }; - match path { + handle_request(url, stream); +} + +fn handle_request(url: URL, stream: TcpStream) { + match url.path { "/" => http::responses::ok(stream, "OK - luciders is working!") .unwrap_or_else(|_| error("Failed to send 200 response")), _ => http::responses::send_404(stream)