feat: URL handling

This commit is contained in:
Compositr 2024-10-30 13:49:27 +11:00
parent 09fc6c1307
commit 952908292b
Signed by: compositr
GPG key ID: 91E3DE20129A0B4A
2 changed files with 48 additions and 14 deletions

View file

@ -1,12 +1,38 @@
use std::collections::HashMap; use std::collections::HashMap;
struct Path<'a> { pub struct URL<'a> {
pub query: HashMap<&'a str, &'a str> pub raw: &'a str,
pub path: &'a str,
pub query: HashMap<&'a str, &'a str>,
} }
impl Path { impl<'a> URL<'a> {
pub fn new<'a>(path: &'a str) -> Self { pub fn new(url: &'a str) -> Option<Self> {
let query = path.split("?").collect(); let raw = url;
Path { query }
} // 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 })
}
} }

View file

@ -5,6 +5,7 @@ use std::{
}; };
use ctrlc; use ctrlc;
use http::requests::URL;
mod http; mod http;
@ -49,19 +50,26 @@ fn handle_connection(mut stream: TcpStream) {
return; 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" { if method != "GET" {
http::responses::send_405(stream).unwrap_or_else(|_| error("Failed to send 405 response")); http::responses::send_405(stream).unwrap_or_else(|_| error("Failed to send 405 response"));
return; return;
} }
let path = if path.ends_with("/") { let url = match http::requests::URL::new(url_str) {
&path[..path.len() - 1] Some(path) => path,
} else { None => {
path 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!") "/" => http::responses::ok(stream, "OK - luciders is working!")
.unwrap_or_else(|_| error("Failed to send 200 response")), .unwrap_or_else(|_| error("Failed to send 200 response")),
_ => http::responses::send_404(stream) _ => http::responses::send_404(stream)