From 90b8b8c921616264074dbf3d2d9d23952cf2066a Mon Sep 17 00:00:00 2001 From: yggverse Date: Sun, 29 Jun 2025 14:34:21 +0300 Subject: [PATCH] apply minor optimizations --- src/response.rs | 2 +- src/server/connection.rs | 71 ++++++++++++++++++++++------------------ src/session/public.rs | 8 ++--- 3 files changed, 44 insertions(+), 37 deletions(-) diff --git a/src/response.rs b/src/response.rs index 35eeaae..5a5ea18 100644 --- a/src/response.rs +++ b/src/response.rs @@ -3,7 +3,7 @@ pub enum Response<'a> { /// Includes reference to the original request AccessDenied(&'a str), /// Includes query + server-side error description - InternalServerError(&'a str, String), + InternalServerError(Option<&'a str>, String), /// Includes reference to the original request NotFound(&'a str), /// Includes bytes array diff --git a/src/server/connection.rs b/src/server/connection.rs index 57db51e..de50799 100644 --- a/src/server/connection.rs +++ b/src/server/connection.rs @@ -1,7 +1,7 @@ use crate::{response::Response, session::Session}; use anyhow::Result; use std::{ - io::{Read, Write}, + io::{ErrorKind, Read, Write}, net::{SocketAddr, TcpStream}, sync::Arc, }; @@ -41,33 +41,21 @@ impl Connection { self.address.server, self.address.client ) } - if let Some(ref r) = self.session.request { - r.add(&self.address.client, &q) + if let Some(ref request) = self.session.request { + request.add(&self.address.client, &q) } - if self - .session - .clone() - .public - .request(&q, |r| match self.response(r) { - Ok(sent) => { - t += sent; - if self.session.is_debug { - println!( - "[{}] > [{}] sent {sent} ({t} total) bytes response.", - self.address.server, self.address.client - ) - }; - true - } - Err(e) => { - eprintln!( - "[{}] > [{}] `{q}`: error sending response: `{e}`", + if self.session.clone().public.request(&q, |response| { + self.response(response).is_ok_and(|sent| { + t += sent; + if self.session.is_debug { + println!( + "[{}] > [{}] sent {sent} ({t} total) bytes response.", self.address.server, self.address.client - ); - false - } + ) + }; + true }) - { + }) { self.session .access_log .clf(&self.address.client, Some(&q), 0, t); @@ -76,10 +64,16 @@ impl Connection { self.session .access_log .clf(&self.address.client, Some(&q), 1, t); + if self.session.is_debug { + println!( + "[{}] - [{}] connection closed by client.", + self.address.server, self.address.client, + ) + } } } Err(e) => match self.response(Response::InternalServerError( - "", + None, format!( "[{}] < [{}] failed to handle incoming request: `{e}`", self.address.server, self.address.client @@ -118,8 +112,8 @@ impl Connection { Ok(urlencoding::decode(std::str::from_utf8(&b[..n])?.trim())?.to_string()) } - fn response(&mut self, response: Response) -> Result { - let bytes = match response { + fn response(&mut self, response: Response) -> std::io::Result { + let data = match response { Response::File(b) => b, Response::Directory(q, ref s, is_root) => { &if is_root { @@ -138,7 +132,7 @@ impl Connection { } Response::InternalServerError(q, e) => { eprintln!( - "[{}] > [{}] `{q}`: internal server error: `{e}`", + "[{}] > [{}] `{q:?}`: internal server error: `{e}`", self.address.server, self.address.client ); self.session.template.internal_server_error() @@ -158,9 +152,22 @@ impl Connection { self.session.template.not_found() } }; - self.stream.write_all(bytes)?; - self.stream.flush()?; - Ok(bytes.len()) + match self.stream.write_all(data) { + Ok(()) => { + self.stream.flush()?; + Ok(data.len()) + } + Err(e) => { + // client may close the active connection unexpectedly, ignore some kinds + if !matches!(e.kind(), ErrorKind::BrokenPipe | ErrorKind::ConnectionReset) { + eprintln!( + "[{}] > [{}] error sending response: `{e}`", + self.address.server, self.address.client + ) + } + Err(e) + } + } } fn shutdown(self) { diff --git a/src/session/public.rs b/src/session/public.rs index b2ac7f6..83c0f91 100644 --- a/src/session/public.rs +++ b/src/session/public.rs @@ -61,7 +61,7 @@ impl Public { Ok(t) => match (t.is_dir(), t.is_file()) { (true, _) => callback(match self.list(&p) { Ok(list) => Response::Directory(query, list, p == self.public_dir), - Err(e) => Response::InternalServerError(query, e.to_string()), + Err(e) => Response::InternalServerError(Some(query), e.to_string()), }), (_, true) => match fs::File::open(p) { Ok(mut f) => loop { @@ -75,21 +75,21 @@ impl Public { } Err(e) => { return callback(Response::InternalServerError( - query, + Some(query), format!("failed to read response chunk: `{e}`"), )); } } }, Err(e) => callback(Response::InternalServerError( - query, + Some(query), format!("failed to read response: `{e}`"), )), }, _ => panic!(), // unexpected }, Err(e) => callback(Response::InternalServerError( - query, + Some(query), format!("failed to read storage: `{e}`"), )), }