use std::{ collections::HashMap, io::{Read, Write}, net::TcpListener, str::from_utf8, sync::{Arc, Mutex}, thread, }; use crate::{ http::{request::RequestLine, Request, Response}, Client, }; pub struct Server { listener: TcpListener, on_request: Arc Response + Send + 'static>>>>, } impl Server { pub fn new(ip: &str, port: i32) -> Self { let addr = format!("{}:{}", ip, port); let listener = TcpListener::bind(addr).unwrap(); Server { listener, on_request: Arc::new(Mutex::new(None)), } } pub fn run(&mut self) { for stream in self.listener.incoming() { let stream = stream.unwrap(); let on_request = Arc::clone(&self.on_request); thread::spawn(move || { let mut client = Client::new(stream); let mut buffer = vec![0; 1024]; let bytes_read = client.read(&mut buffer).unwrap(); if bytes_read > 0 { if let Ok(request_str) = from_utf8(&buffer[..bytes_read]) { if let Some(on_request) = &*on_request.lock().unwrap() { let request; { let mut lines = request_str.lines(); let request_line = RequestLine::from_str(lines.next().unwrap()); let mut headers = HashMap::new(); for line in lines { if let Some((k, v)) = line.split_once(": ") { headers.insert(k, v); } } request = Request { request_line, headers, }; } let response = on_request(request); { let response_line = response.response_line.to_string(); client.write_string(response_line).unwrap(); if let Some(headers) = response.headers { for (k, v) in headers { client.write_string(format!("{}: {}", k, v)).unwrap(); } } else { client.write(b"\r\n").unwrap(); } if let Some(content) = response.content { client.write(b"\r\n").unwrap(); client.write(&content).unwrap(); } else { client.write(b"\r\n").unwrap(); } } client.flush().unwrap(); } } } }); } } pub fn on_request(&mut self, f: F) where F: Fn(Request) -> Response + Send + 'static, { *self.on_request.lock().unwrap() = Some(Box::new(f)) } }