improv: add a logger (#18) + log client IP (#19)

This commit is contained in:
landrigun 2022-11-07 10:28:58 +00:00
parent 74e8d58b5c
commit 45c9112af2
5 changed files with 163 additions and 28 deletions

135
Cargo.lock generated
View File

@ -297,6 +297,17 @@ dependencies = [
"wasm-bindgen", "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]] [[package]]
name = "concurrent-queue" name = "concurrent-queue"
version = "1.2.4" version = "1.2.4"
@ -781,7 +792,7 @@ dependencies = [
"libc", "libc",
"log", "log",
"wasi", "wasi",
"windows-sys", "windows-sys 0.36.1",
] ]
[[package]] [[package]]
@ -842,6 +853,15 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "num_threads"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.15.0" version = "1.15.0"
@ -902,7 +922,7 @@ dependencies = [
"libc", "libc",
"redox_syscall", "redox_syscall",
"smallvec", "smallvec",
"windows-sys", "windows-sys 0.36.1",
] ]
[[package]] [[package]]
@ -1214,10 +1234,25 @@ dependencies = [
"json", "json",
"jwt-simple", "jwt-simple",
"lazy_static", "lazy_static",
"log",
"regex", "regex",
"simple_logger",
"tokio", "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]] [[package]]
name = "slab" name = "slab"
version = "0.4.7" version = "0.4.7"
@ -1327,6 +1362,35 @@ dependencies = [
"syn", "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]] [[package]]
name = "tokio" name = "tokio"
version = "1.21.2" version = "1.21.2"
@ -1520,43 +1584,100 @@ version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
dependencies = [ dependencies = [
"windows_aarch64_msvc", "windows_aarch64_msvc 0.36.1",
"windows_i686_gnu", "windows_i686_gnu 0.36.1",
"windows_i686_msvc", "windows_i686_msvc 0.36.1",
"windows_x86_64_gnu", "windows_x86_64_gnu 0.36.1",
"windows_x86_64_msvc", "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]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.36.1" version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.36.1" version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
[[package]]
name = "windows_i686_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.36.1" version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
[[package]]
name = "windows_i686_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.36.1" version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" 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]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.36.1" version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" 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]] [[package]]
name = "zeroize" name = "zeroize"
version = "1.5.7" version = "1.5.7"

View File

@ -12,6 +12,8 @@ regex = "1"
tokio = { version = "1.21.1", features = ["full"] } tokio = { version = "1.21.1", features = ["full"] }
async-trait = "0.1.57" async-trait = "0.1.57"
jwt-simple = "0.11.1" jwt-simple = "0.11.1"
simple_logger = "4.0.0"
log = "0.4.17"
# useful for tests (embedded files should be delete in release ?) # useful for tests (embedded files should be delete in release ?)
#rust-embed="6.4.1" #rust-embed="6.4.1"

View File

@ -143,10 +143,7 @@ impl TryFrom<String> for HTTPBody {
let body = body.replace(NULL_CHAR, ""); let body = body.replace(NULL_CHAR, "");
match json::parse(&body) { match json::parse(&body) {
Ok(v) => Ok(HTTPBody::new(v)), Ok(v) => Ok(HTTPBody::new(v)),
Err(e) => Err(format!( Err(e) => Err(format!("during request body parsing details={}", e)),
"error occurred during request body parsing err={}",
e
)),
} }
} }
} }
@ -156,6 +153,8 @@ impl TryFrom<String> for HTTPBody {
pub struct HTTPRequest { pub struct HTTPRequest {
pub start_line: HTTPStartLine, pub start_line: HTTPStartLine,
pub body: Option<HTTPBody>, pub body: Option<HTTPBody>,
// includes the client IP + port (should be in the headers)
pub addr: String,
} }
impl HTTPRequest { impl HTTPRequest {
@ -190,19 +189,19 @@ impl HTTPRequest {
let start_line = HTTPStartLine::parse(&rp.0); let start_line = HTTPStartLine::parse(&rp.0);
match start_line { match start_line {
Ok(v) => request.start_line = v, 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); let body = HTTPBody::try_from(rp.2);
match body { match body {
Ok(v) => request.body = Some(v), Ok(v) => request.body = Some(v),
Err(e) => eprintln!("error occurred during body parsing err={}", e), Err(e) => log::error!("{}", e),
} }
return Ok(request); return Ok(request);
} }
Err(e) => { 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 { pub fn is_valid(&self) -> bool {
return self.start_line.is_valid(); return self.start_line.is_valid();
} }
pub fn set_addr(&mut self, addr: String) {
self.addr = addr;
}
} }
impl Default for HTTPRequest { impl Default for HTTPRequest {
@ -229,6 +232,7 @@ impl Default for HTTPRequest {
HTTPRequest { HTTPRequest {
start_line: HTTPStartLine::default(), start_line: HTTPStartLine::default(),
body: None, body: None,
addr: "".to_string(),
} }
} }
} }
@ -237,8 +241,8 @@ impl From<&str> for HTTPRequest {
fn from(request: &str) -> Self { fn from(request: &str) -> Self {
match Self::parse(request) { match Self::parse(request) {
Ok(v) => v, Ok(v) => v,
Err(v) => { Err(e) => {
eprintln!("{}", format!("[ERR]: {v}")); log::error!("{}", e);
return HTTPRequest::default(); return HTTPRequest::default();
} }
} }

View File

@ -90,8 +90,10 @@ async fn handle_validate(request: HTTPRequest, config: Config) -> HTTPResponse {
pub struct Router; pub struct Router;
impl Router { impl Router {
pub async fn route(&self, request_str: &str, config: Config) -> HTTPResponse { pub async fn route(&self, request_str: &str, addr: String, config: Config) -> HTTPResponse {
let request = HTTPRequest::from(request_str); let mut request = HTTPRequest::from(request_str);
request.set_addr(addr);
let target = request.start_line.get_target(); let target = request.start_line.get_target();
match target.as_str() { match target.as_str() {

View File

@ -24,13 +24,14 @@ struct Cli {
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
simple_logger::init_with_level(log::Level::Info).unwrap();
let args = Cli::parse(); let args = Cli::parse();
let mut config = Ini::new(); let mut config = Ini::new();
match config.load(args.config) { match config.load(args.config) {
Ok(c) => c, Ok(c) => c,
Err(e) => { 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); std::process::exit(1);
} }
}; };
@ -39,11 +40,11 @@ async fn main() {
let listener = { let listener = {
match TcpListener::bind(&server_url).await { match TcpListener::bind(&server_url).await {
Ok(t) => { Ok(t) => {
println!("server is listening on '{}'", server_url); log::info!("server is listening on '{}'", server_url);
t t
} }
Err(e) => { Err(e) => {
eprintln!("error occurred while initializing tcp listener err={}", e); log::error!("while initializing tcp listener details={}", e);
std::process::exit(1); std::process::exit(1);
} }
} }
@ -52,28 +53,31 @@ async fn main() {
let router_config: Config = { let router_config: Config = {
match Config::try_from(config) { match Config::try_from(config) {
Ok(c) => c, Ok(c) => c,
Err(_e) => { Err(e) => {
log::error!("unable to load the configuration details={}", e);
std::process::exit(1); std::process::exit(1);
} }
} }
}; };
loop { loop {
let (stream, _) = listener.accept().await.unwrap(); let (stream, addr) = listener.accept().await.unwrap();
let conf = router_config.clone(); 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 /// 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 message = vec![];
let mut buffer: [u8; 1024] = [0; 1024]; 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 // 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 // after the timeout, the message is "considered" as entirely read
loop { loop {
match timeout(duration, stream.read(&mut buffer)).await { 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 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(); let response_str: String = response.into();
stream.write(response_str.as_bytes()).await.unwrap(); stream.write(response_str.as_bytes()).await.unwrap();
stream.flush().await.unwrap(); stream.flush().await.unwrap();
log::info!("connection closed: {}", addr);
} }