diff --git a/src/main.rs b/src/main.rs index f029ea7..a0e1a3d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -52,7 +52,7 @@ fn main() { } } - context.handle_connection(&path, stream, &pool); + handle_connection(&mut context, &path, stream, &pool); } } @@ -133,112 +133,110 @@ struct Context { infos: HashMap, Arc>>, } -impl Context { - fn handle_connection(&mut self, path: &Path, mut stream: TcpStream, pool: &ThreadPool) { - let Some(request) = Request::from(&stream) else { - eprintln!("Invalid request!"); - return; - }; +fn handle_connection(context: &mut Context, path: &Path, mut stream: TcpStream, pool: &ThreadPool) { + let Some(request) = Request::from(&stream) else { + eprintln!("Invalid request!"); + return; + }; - eprintln!(); - eprintln!("Request:"); - eprintln!("- Method: {}", request.method); - eprintln!("- Path: {}", request.path); - eprintln!("- Version: {}", request.version); - eprintln!("- Headers:"); - for header in request.headers { - eprintln!(" - {header}"); - } - eprintln!("- Body: {}", request.body); - eprintln!(); - - let (mut relative_path, _) = request - .path - .split_once('?') - .unwrap_or((&request.path, Default::default())); - - if relative_path.contains("//") { - fail(stream); - return; - } - - if let Some(path) = relative_path.strip_prefix('/') { - relative_path = path; - } - - let mut pk_path = path.to_path_buf(); - let mut data_path = path.to_path_buf(); - - let (pki_path, start_level, relative_path) = if relative_path.is_empty() { - pk_path.push("index.pk"); - data_path.push("index.dat"); - - (None, 0, String::new()) - } else { - let mut pki_path = path.to_path_buf(); - - let path = percent_decode_str(relative_path).decode_utf8_lossy(); - if path.contains('_') { - let path = path.replace('_', " "); - let _ = write!(stream, "HTTP/1.1 308 Permanent Redirect\r\n"); - let _ = write!(stream, "Location: /{path}\r\n\r\n"); - return; - } - - pk_path.push(format!("{path}.pk")); - pki_path.push(format!("{path}.pki")); - data_path.push(format!("{path}.dat")); - - (Some(pki_path), 1, path.to_string()) - }; - - if relative_path.split('/').any(|name| name == "Images") { - let path = path.to_path_buf(); - pool.execute(move || reply_image(stream, &relative_path, path)); - return; - } - - if !Path::is_file(&pk_path) { - fail(stream); - return; - } - - if let Some(pki_path) = &pki_path { - if !Path::is_file(pki_path) { - fail(stream); - return; - } - } - - use Entry::*; - let info = match self.infos.entry(relative_path.clone().into_boxed_str()) { - Occupied(o) => o.get().clone(), - Vacant(v) => v - .insert(Arc::new(Mutex::new( - File::open(&data_path) - .map(|mut file| { - from_stream::(&mut file).unwrap_or_default() - }) - .unwrap_or_default(), - ))) - .clone(), - }; - - let path = path.to_path_buf(); - pool.execute(move || { - handle_relative_connection( - info, - stream, - &request.body, - &relative_path, - &path, - &pk_path, - pki_path.as_ref().map(|path| path.as_ref()), - &data_path, - start_level, - ) - }); + eprintln!(); + eprintln!("Request:"); + eprintln!("- Method: {}", request.method); + eprintln!("- Path: {}", request.path); + eprintln!("- Version: {}", request.version); + eprintln!("- Headers:"); + for header in request.headers { + eprintln!(" - {header}"); } + eprintln!("- Body: {}", request.body); + eprintln!(); + + let (mut relative_path, _) = request + .path + .split_once('?') + .unwrap_or((&request.path, Default::default())); + + if relative_path.contains("//") { + fail(stream); + return; + } + + if let Some(path) = relative_path.strip_prefix('/') { + relative_path = path; + } + + let mut pk_path = path.to_path_buf(); + let mut data_path = path.to_path_buf(); + + let (pki_path, start_level, relative_path) = if relative_path.is_empty() { + pk_path.push("index.pk"); + data_path.push("index.dat"); + + (None, 0, String::new()) + } else { + let mut pki_path = path.to_path_buf(); + + let path = percent_decode_str(relative_path).decode_utf8_lossy(); + if path.contains('_') { + let path = path.replace('_', " "); + let _ = write!(stream, "HTTP/1.1 308 Permanent Redirect\r\n"); + let _ = write!(stream, "Location: /{path}\r\n\r\n"); + return; + } + + pk_path.push(format!("{path}.pk")); + pki_path.push(format!("{path}.pki")); + data_path.push(format!("{path}.dat")); + + (Some(pki_path), 1, path.to_string()) + }; + + if relative_path.split('/').any(|name| name == "Images") { + let path = path.to_path_buf(); + pool.execute(move || reply_image(stream, &relative_path, path)); + return; + } + + if !Path::is_file(&pk_path) { + fail(stream); + return; + } + + if let Some(pki_path) = &pki_path { + if !Path::is_file(pki_path) { + fail(stream); + return; + } + } + + use Entry::*; + let info = match context.infos.entry(relative_path.clone().into_boxed_str()) { + Occupied(o) => o.get().clone(), + Vacant(v) => v + .insert(Arc::new(Mutex::new( + File::open(&data_path) + .map(|mut file| { + from_stream::(&mut file).unwrap_or_default() + }) + .unwrap_or_default(), + ))) + .clone(), + }; + + let path = path.to_path_buf(); + pool.execute(move || { + handle_relative_connection( + info, + stream, + &request.body, + &relative_path, + &path, + &pk_path, + pki_path.as_ref().map(|path| path.as_ref()), + &data_path, + start_level, + ) + }); } fn reply_image(mut stream: TcpStream, relative_path: &str, mut path: PathBuf) {