refactor: remove &ownership issues
This commit is contained in:
parent
b9c51fc657
commit
1b19b2b935
1 changed files with 56 additions and 13 deletions
|
@ -1,38 +1,81 @@
|
||||||
use std::collections::HashMap;
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
io::{prelude::*, BufReader},
|
||||||
|
net::TcpStream,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct URL<'a> {
|
pub struct URL {
|
||||||
pub raw: &'a str,
|
raw: String,
|
||||||
pub path: &'a str,
|
pub path: String,
|
||||||
pub query: HashMap<&'a str, &'a str>,
|
pub query: HashMap<String, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> URL<'a> {
|
impl URL {
|
||||||
pub fn new(url: &'a str) -> Option<Self> {
|
pub fn new(url: String) -> Option<Self> {
|
||||||
let raw = url;
|
let raw = url;
|
||||||
|
let mut split = raw.split('?');
|
||||||
|
|
||||||
// Query string parsing
|
// Query string parsing
|
||||||
let mut query = HashMap::new();
|
let mut query = HashMap::new();
|
||||||
let mut split = url.split('?');
|
let path = split.next()?.to_string();
|
||||||
let path = split.nth(0)?;
|
|
||||||
let query_string = split.next();
|
let query_string = split.next();
|
||||||
|
|
||||||
for pair in query_string.unwrap_or("").split('&') {
|
for pair in query_string.unwrap_or("").split('&') {
|
||||||
let mut key_value = pair.split('=');
|
let mut key_value = pair.split('=');
|
||||||
let key = match key_value.next() {
|
let key = match key_value.next() {
|
||||||
Some(key) => key,
|
Some(key) => key.to_string(),
|
||||||
None => continue,
|
None => continue,
|
||||||
};
|
};
|
||||||
let value = key_value.next().unwrap_or("");
|
let value = key_value.next().unwrap_or("").to_string();
|
||||||
query.insert(key, value);
|
query.insert(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drop trailing slash but not for root path
|
// Drop trailing slash but not for root path
|
||||||
let path = if path.ends_with("/") && path.len() > 1 {
|
let path = if path.ends_with("/") && path.len() > 1 {
|
||||||
&path[..path.len() - 1]
|
path[..path.len() - 1].to_string()
|
||||||
} else {
|
} else {
|
||||||
path
|
path
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(URL { raw, path, query })
|
Some(URL { path, query, raw })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Request {
|
||||||
|
stream: TcpStream,
|
||||||
|
pub method: String,
|
||||||
|
pub url: URL,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum RequestStatus {
|
||||||
|
Ok(Request),
|
||||||
|
MalformedHTTP,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Request {
|
||||||
|
pub fn parse_stream(stream: TcpStream) -> RequestStatus {
|
||||||
|
let reader = BufReader::new(&stream);
|
||||||
|
let mut lines = reader.lines();
|
||||||
|
|
||||||
|
let request_line = match lines.next() {
|
||||||
|
Some(Ok(line)) => line,
|
||||||
|
_ => return RequestStatus::MalformedHTTP,
|
||||||
|
};
|
||||||
|
|
||||||
|
let request_line_parts = request_line.split(" ").collect::<Vec<_>>();
|
||||||
|
if request_line_parts.len() != 3 {
|
||||||
|
return RequestStatus::MalformedHTTP;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (method, url_str) = (
|
||||||
|
request_line_parts[0].to_string().clone(),
|
||||||
|
request_line_parts[1].to_string().clone(),
|
||||||
|
);
|
||||||
|
let url = match URL::new(url_str) {
|
||||||
|
Some(path) => path,
|
||||||
|
None => return RequestStatus::MalformedHTTP,
|
||||||
|
};
|
||||||
|
|
||||||
|
RequestStatus::Ok(Request { stream, method, url })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue