use std::{ io::{BufRead, BufReader, Write}, net::TcpStream, path::PathBuf, }; use crate::routing::routes::{Data, Outcome, Request, Response, Status}; use crate::setup::MountPoint; use super::file_handlers::NamedFile; pub fn handle_connection(mut stream: TcpStream, mountpoints: Vec<MountPoint>) { let buf_reader = BufReader::new(&mut stream); let http_request: Vec<String> = buf_reader .lines() .map(|result| result.unwrap()) .take_while(|line| !line.is_empty()) .collect(); let request_status_line = http_request.get(0); if request_status_line == None { return; } let request_status_line = request_status_line.unwrap(); let request = Request { uri: &request_status_line.split(" ").nth(1).unwrap(), headers: http_request.clone(), method: request_status_line .split(" ") .next() .unwrap() .parse() .unwrap(), }; let data = Data { buffer: vec![], is_complete: true, }; let mut handled_response: Option<Outcome<Response, Status, Data>> = None; for mountpoint in mountpoints { if !request.uri.starts_with(mountpoint.mountpoint) { println!("MOUNTPOINT COMPARISON {}", request.uri); continue; } let mounted_request_uri = request.uri.strip_prefix(mountpoint.mountpoint).unwrap(); for route in mountpoint.routes { if route.method != request.method { println!("METHOD COMPARE {}", request.method); continue; } if !route.compare_uri(mounted_request_uri) { println!("URI COMPARISON {} {}", mounted_request_uri, route.uri); continue; } handled_response = Some((route.handler)( Request { uri: mounted_request_uri, ..request.clone() }, data.clone(), )); } } let response = match handled_response { Some(val) => match val { Outcome::Success(success) => ( format!("HTTP/1.1 {} OK\r\n", success.status.unwrap().code) + &success.headers.join("\r\n") + "\r\n\r\n", success.body.get_data(), ), Outcome::Failure(error) => handler_404(error), Outcome::Forward(_) => handler_404(Status { code: 404 }), }, None => handler_404(Status { code: 404 }), }; stream.write_all(response.0.as_bytes()).unwrap(); stream.write(&response.1).unwrap(); } fn handler_404(status: Status) -> (String, Vec<u8>) { let page_404 = NamedFile::open(PathBuf::from("404.html")).unwrap(); ( format!( "HTTP/1.1 {} NOT FOUND\r\nContent-Length: {}\r\nContent-Type: {}\r\n\r\n", status.code, page_404.content_len, page_404.content_type ), page_404.content, ) }