From 45c9112af24ac865ce2107a256065c47f885423e Mon Sep 17 00:00:00 2001 From: landrigun Date: Mon, 7 Nov 2022 10:28:58 +0000 Subject: [PATCH] improv: add a logger (#18) + log client IP (#19) --- Cargo.lock | 135 +++++++++++++++++++++++++++++++++++++++++--- Cargo.toml | 2 + src/http/request.rs | 22 +++++--- src/http/router.rs | 6 +- src/main.rs | 26 +++++---- 5 files changed, 163 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c9a5d07..07f2c40 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -297,6 +297,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "colored" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" +dependencies = [ + "atty", + "lazy_static", + "winapi", +] + [[package]] name = "concurrent-queue" version = "1.2.4" @@ -781,7 +792,7 @@ dependencies = [ "libc", "log", "wasi", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -842,6 +853,15 @@ dependencies = [ "libc", ] +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + [[package]] name = "once_cell" version = "1.15.0" @@ -902,7 +922,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -1214,10 +1234,25 @@ dependencies = [ "json", "jwt-simple", "lazy_static", + "log", "regex", + "simple_logger", "tokio", ] +[[package]] +name = "simple_logger" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e190a521c2044948158666916d9e872cbb9984f755e9bb3b5b75a836205affcd" +dependencies = [ + "atty", + "colored", + "log", + "time", + "windows-sys 0.42.0", +] + [[package]] name = "slab" version = "0.4.7" @@ -1327,6 +1362,35 @@ dependencies = [ "syn", ] +[[package]] +name = "time" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" +dependencies = [ + "itoa", + "libc", + "num_threads", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + +[[package]] +name = "time-macros" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" +dependencies = [ + "time-core", +] + [[package]] name = "tokio" version = "1.21.2" @@ -1520,43 +1584,100 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", ] +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.0", + "windows_i686_gnu 0.42.0", + "windows_i686_msvc 0.42.0", + "windows_x86_64_gnu 0.42.0", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + [[package]] name = "windows_aarch64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" + [[package]] name = "windows_i686_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +[[package]] +name = "windows_i686_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" + [[package]] name = "windows_i686_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +[[package]] +name = "windows_i686_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" + [[package]] name = "windows_x86_64_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" + [[package]] name = "windows_x86_64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" + [[package]] name = "zeroize" version = "1.5.7" diff --git a/Cargo.toml b/Cargo.toml index 4121298..0514ec3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,8 @@ regex = "1" tokio = { version = "1.21.1", features = ["full"] } async-trait = "0.1.57" jwt-simple = "0.11.1" +simple_logger = "4.0.0" +log = "0.4.17" # useful for tests (embedded files should be delete in release ?) #rust-embed="6.4.1" diff --git a/src/http/request.rs b/src/http/request.rs index 2d1bc4c..087c3e2 100644 --- a/src/http/request.rs +++ b/src/http/request.rs @@ -143,10 +143,7 @@ impl TryFrom for HTTPBody { let body = body.replace(NULL_CHAR, ""); match json::parse(&body) { Ok(v) => Ok(HTTPBody::new(v)), - Err(e) => Err(format!( - "error occurred during request body parsing err={}", - e - )), + Err(e) => Err(format!("during request body parsing details={}", e)), } } } @@ -156,6 +153,8 @@ impl TryFrom for HTTPBody { pub struct HTTPRequest { pub start_line: HTTPStartLine, pub body: Option, + // includes the client IP + port (should be in the headers) + pub addr: String, } impl HTTPRequest { @@ -190,19 +189,19 @@ impl HTTPRequest { let start_line = HTTPStartLine::parse(&rp.0); match start_line { Ok(v) => request.start_line = v, - Err(e) => eprintln!("error occurred while parsing start_line err={}", e), + Err(e) => log::error!("while parsing start_line details={}", e), } let body = HTTPBody::try_from(rp.2); match body { Ok(v) => request.body = Some(v), - Err(e) => eprintln!("error occurred during body parsing err={}", e), + Err(e) => log::error!("{}", e), } return Ok(request); } Err(e) => { - return Err(format!("error occurred getting request parts err={}", e)); + return Err(e); } } } @@ -222,6 +221,10 @@ impl HTTPRequest { pub fn is_valid(&self) -> bool { return self.start_line.is_valid(); } + + pub fn set_addr(&mut self, addr: String) { + self.addr = addr; + } } impl Default for HTTPRequest { @@ -229,6 +232,7 @@ impl Default for HTTPRequest { HTTPRequest { start_line: HTTPStartLine::default(), body: None, + addr: "".to_string(), } } } @@ -237,8 +241,8 @@ impl From<&str> for HTTPRequest { fn from(request: &str) -> Self { match Self::parse(request) { Ok(v) => v, - Err(v) => { - eprintln!("{}", format!("[ERR]: {v}")); + Err(e) => { + log::error!("{}", e); return HTTPRequest::default(); } } diff --git a/src/http/router.rs b/src/http/router.rs index d1f60ca..36a9f68 100644 --- a/src/http/router.rs +++ b/src/http/router.rs @@ -90,8 +90,10 @@ async fn handle_validate(request: HTTPRequest, config: Config) -> HTTPResponse { pub struct Router; impl Router { - pub async fn route(&self, request_str: &str, config: Config) -> HTTPResponse { - let request = HTTPRequest::from(request_str); + pub async fn route(&self, request_str: &str, addr: String, config: Config) -> HTTPResponse { + let mut request = HTTPRequest::from(request_str); + request.set_addr(addr); + let target = request.start_line.get_target(); match target.as_str() { diff --git a/src/main.rs b/src/main.rs index 87eb6cd..d16c45a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,13 +24,14 @@ struct Cli { #[tokio::main] async fn main() { + simple_logger::init_with_level(log::Level::Info).unwrap(); let args = Cli::parse(); let mut config = Ini::new(); match config.load(args.config) { Ok(c) => c, Err(e) => { - eprintln!("error while loading the config file, err={}", e); + log::error!("error while loading the config file details={}", e); std::process::exit(1); } }; @@ -39,11 +40,11 @@ async fn main() { let listener = { match TcpListener::bind(&server_url).await { Ok(t) => { - println!("server is listening on '{}'", server_url); + log::info!("server is listening on '{}'", server_url); t } Err(e) => { - eprintln!("error occurred while initializing tcp listener err={}", e); + log::error!("while initializing tcp listener details={}", e); std::process::exit(1); } } @@ -52,28 +53,31 @@ async fn main() { let router_config: Config = { match Config::try_from(config) { Ok(c) => c, - Err(_e) => { + Err(e) => { + log::error!("unable to load the configuration details={}", e); std::process::exit(1); } } }; loop { - let (stream, _) = listener.accept().await.unwrap(); + let (stream, addr) = listener.accept().await.unwrap(); let conf = router_config.clone(); - tokio::spawn(handle_connection(stream, conf.clone())); + tokio::spawn(handle_connection(stream, addr.to_string(), conf.clone())); } } /// parses the incoming request (partial spec implementation) and build an HTTP response -async fn handle_connection(mut stream: TcpStream, config: Config) { +async fn handle_connection(mut stream: TcpStream, addr: String, config: Config) { + log::info!("client connected: {}", addr); + let mut message = vec![]; let mut buffer: [u8; 1024] = [0; 1024]; - let duration = Duration::from_micros(500); + let duration = Duration::from_millis(5); // loop until the message is read - // the stream can be fragmented so, using a timeout (500um should be enough) for the future for completion + // the stream can be fragmented so, using a timeout (5ms should be far enough) for the future for completion // after the timeout, the message is "considered" as entirely read loop { match timeout(duration, stream.read(&mut buffer)).await { @@ -86,9 +90,11 @@ async fn handle_connection(mut stream: TcpStream, config: Config) { } let request_string = std::str::from_utf8(&message).unwrap(); - let response = ROUTER.route(request_string, config).await; + let response = ROUTER.route(request_string, addr.clone(), config).await; let response_str: String = response.into(); stream.write(response_str.as_bytes()).await.unwrap(); stream.flush().await.unwrap(); + + log::info!("connection closed: {}", addr); }