use crate::{pkg::error::Error, types::http::*}; use http::header::{HeaderMap, HeaderName, HeaderValue}; use std::collections::HashMap; pub fn parse_query_string(query: &str) -> HashMap { query .split('&') .filter(|s| !s.is_empty()) .filter_map(|s| { let mut parts = s.splitn(2, '='); Some((parts.next()?.to_string(), parts.next().unwrap_or("").to_string())) }) .collect() } pub fn extract_params(request_path: &str, route_path: &str) -> HashMap { let mut params = HashMap::new(); let req_segments: Vec<&str> = request_path.split('/').collect(); let route_segments: Vec<&str> = route_path.split('/').collect(); for (req_seg, route_seg) in req_segments.iter().zip(route_segments.iter()) { if route_seg.starts_with('{') && route_seg.ends_with('}') { let param_name = &route_seg[1..route_seg.len() - 1]; params.insert(param_name.to_string(), req_seg.to_string()); } } params } pub fn paths_match(request_path: &str, route_path: &str) -> bool { let req_segments: Vec<&str> = request_path.split('/').collect(); let route_segments: Vec<&str> = route_path.split('/').collect(); if req_segments.len() != route_segments.len() { return false; } for (req_seg, route_seg) in req_segments.iter().zip(route_segments.iter()) { if !route_seg.starts_with('{') && req_seg != route_seg { return false; } } true } pub fn parse_headers<'a, I>(lines: I) -> Result where I: Iterator, { let mut headers = HeaderMap::new(); for line in lines { if line.is_empty() { break; } if let Some((key, value)) = line.split_once(':') { let header_name = HeaderName::from_bytes(key.trim().as_bytes()).map_err(|e| Error(format!("Invalid header name: {}", e)))?; let header_value = HeaderValue::from_str(value.trim()).map_err(|e| Error(format!("Invalid header value: {}", e)))?; headers.insert(header_name, header_value); } } Ok(headers) } pub fn parse_request(buffer: &[u8]) -> Result { let request_str = String::from_utf8_lossy(buffer); let mut parts = request_str.splitn(2, "\r\n\r\n"); let headers_part = parts.next().ok_or_else(|| Error("Invalid request".into()))?; let body_part = parts.next().unwrap_or(""); let mut lines = headers_part.lines(); let first_line = lines.next().ok_or_else(|| Error("Invalid request".into()))?; let mut parts = first_line.split_whitespace(); let method = match parts.next() { Some("GET") => Method::GET, Some("POST") => Method::POST, Some("PUT") => Method::PUT, Some("DELETE") => Method::DELETE, _ => return Err(Error("Invalid method".into())), }; let full_path = parts.next().ok_or_else(|| Error("Invalid path".into()))?; let (path, query) = full_path.split_once('?').unwrap_or((full_path, "")); let query_params = parse_query_string(query); let headers = parse_headers(lines)?; let body = body_part.as_bytes().to_vec(); Ok(Request { method, headers, query: query_params, body, params: HashMap::new(), path: path.to_string(), }) }