diff --git a/src/http/mod.rs b/src/http/mod.rs index 9075124..1a7dace 100644 --- a/src/http/mod.rs +++ b/src/http/mod.rs @@ -2,6 +2,8 @@ use std::collections::HashMap; use tokio::net::TcpStream; use std::fs::File; use std::io::Read; +use std::borrow::Borrow; +use std::hash::{Hash, Hasher}; use crate::config::{DEF_ASSETS, SERVER_CONFIG}; pub mod http_server; @@ -109,3 +111,30 @@ macro_rules! make_route { } }; } + +#[derive(Eq, Debug, Clone)] +pub struct UniCaseString(String); + +impl From for UniCaseString { + fn from(value: String) -> Self { + UniCaseString(value) + } +} + +impl Borrow for UniCaseString { + fn borrow(&self) -> &str { + self.0.as_str() + } +} + +impl PartialEq for UniCaseString { + fn eq(&self, other: &Self) -> bool { + self.0.to_lowercase() == other.0.to_lowercase() + } +} + +impl Hash for UniCaseString { + fn hash(&self, state: &mut H) { + self.0.to_lowercase().hash(state); + } +} \ No newline at end of file diff --git a/src/http/request.rs b/src/http/request.rs index 1eb9a81..ac6fa0d 100644 --- a/src/http/request.rs +++ b/src/http/request.rs @@ -1,10 +1,13 @@ +use std::borrow::Borrow; use std::collections::HashMap; +use std::fmt::Debug; use std::future::Future; +use std::hash::{Hash, Hasher}; use std::pin::Pin; use log::trace; use tokio::io::{AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader, BufWriter}; use crate::config::GARBAGE_DATA; -use crate::http::{Method, MethodStr}; +use crate::http::{Method, MethodStr, UniCaseString}; use crate::http::response::Response; #[derive(Debug)] @@ -13,7 +16,7 @@ pub struct Request { pub method: Method, pub remote_addr : String, pub query_params: HashMap, - pub headers: HashMap, + pub headers: HashMap, pub form_data : HashMap } @@ -189,7 +192,7 @@ fn hex_string_to_int(hex_string: &str) -> Option { } } -pub async fn header_parser(buf_reader: &mut BufReader) -> HashMap +pub async fn header_parser(buf_reader: &mut BufReader) -> HashMap where R: AsyncReadExt + Unpin { @@ -201,7 +204,7 @@ where } else { let mut header_parts = header_line.splitn(2, ':'); if let (Some(header_key),Some(header_val)) = (header_parts.next(),header_parts.next()) { - headers_out.insert(header_key.trim().to_string(),header_val.trim().to_string()); + headers_out.insert(header_key.trim().to_string().into(),header_val.trim().to_string()); } } } else { @@ -211,7 +214,7 @@ where headers_out } -fn check_has_body(headers : &HashMap) -> (Option,Option) { +fn check_has_body(headers : &HashMap) -> (Option,Option) { let content_type_form = if let Some(content_type) = headers.get("Content-Type") { if content_type.starts_with("multipart/form-data;") { Some(BodyType::Form) @@ -279,7 +282,7 @@ fn clear_path_end_slash(input: &str) -> &str { } } -fn trust_addr_proxy(headers : &HashMap,remote_addr : &str) -> String { +fn trust_addr_proxy(headers : &HashMap,remote_addr : &str) -> String { if let Some(remote_ip) = headers.get("X-Real-IP") { remote_ip.to_string() } else {