use crate::http; use crate::schemas; use clap::Parser; use http::{HttpError, HttpMethod, HttpRequest, parse_method}; use schemas::{Args, State}; use std::error::Error; use std::sync::Mutex; use std::thread; use std::{ collections::HashMap, io::{BufReader, prelude::*}, net::{TcpListener, TcpStream}, sync::Arc, }; use std::{path::PathBuf, str::FromStr}; type AppState = Arc>; fn parse_http_request(mut buf: BufReader<&TcpStream>) -> Result { let mut request_method: Option = None; let mut uri: Option = None; let mut headers: Vec = Vec::new(); let mut header_map: HashMap = HashMap::new(); let mut method_line: String = String::new(); for (i, line_result) in buf.by_ref().lines().enumerate() { let line = line_result.unwrap(); if i == 0 { method_line.push_str(&line); let http_args = method_line.split(" ").collect::>(); if http_args.len() == 3 { match parse_method(http_args[0]) { Ok(m) => request_method = Some(m), Err(e) => return Err(e), } match PathBuf::from_str(http_args[1]) { Ok(b) => uri = Some(b), Err(_) => return Err(HttpError::InternalServerError), } } else { return Err(HttpError::InternalServerError); } } if line.is_empty() { break; } headers.push(line.clone()); if let Some((key, value)) = line.split_once(": ") { header_map.insert(key.to_string().to_lowercase(), value.to_string()); } } let conten_length = header_map .get("content-length") .and_then(|v| v.parse::().ok()) .unwrap_or(0); println!("Content length: {conten_length:?}"); let mut body: Vec = vec![0 as u8; conten_length]; let res = match buf.read_exact(&mut body) { Ok(_) => body, Err(_) => return Err(HttpError::InternalServerError), }; if uri.is_none() || request_method.is_none() { return Err(HttpError::InternalServerError); } Ok(HttpRequest { method: request_method.unwrap(), uri: uri.unwrap(), headers: header_map, body: res, }) } fn dispatch_connection(mut stream: TcpStream, state: &AppState) -> Result<(), HttpError> { loop { let buf_reader = BufReader::new(&stream); match parse_http_request(buf_reader) { Ok(request) => { println!("Request: {:?}", &request); if request.uri == PathBuf::from("/healthcheck") { } else { } let response = "HTTP/1.1 200 OK\r\nContent-length: 0\r\n\r\n"; stream.write_all(response.as_bytes()).unwrap(); } Err(_) => { println!("Closing connection due to error or client disconnect."); break; } } } Ok(()) } pub struct HttpServer { listener: TcpListener, } impl HttpServer { pub fn new(port: &u32) -> Self { Self { listener: TcpListener::bind(format!("[::]:{}", port)).unwrap(), } } pub fn listen(&self, state: &AppState) { println!("Listening on port 7878"); for stream in self.listener.incoming() { let stream = stream.unwrap(); let _ = dispatch_connection(stream, &state); } } }