diff --git a/Cargo.lock b/Cargo.lock index b6cc47c..39ac65e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -474,12 +474,65 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "futures" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +dependencies = [ + "futures-core", + "futures-sink", +] + [[package]] name = "futures-core" version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" +[[package]] +name = "futures-executor" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" + +[[package]] +name = "futures-macro" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "futures-sink" version = "0.3.21" @@ -498,10 +551,16 @@ version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" dependencies = [ + "futures-channel", "futures-core", + "futures-io", + "futures-macro", + "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", + "slab", ] [[package]] @@ -933,6 +992,7 @@ dependencies = [ "actix-web", "clap", "env_logger", + "futures", "log", ] diff --git a/Cargo.toml b/Cargo.toml index dfd1806..3f36ec2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,8 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -actix-web = "4" log = "0.4.17" env_logger = "0.9.0" -clap = { version = "3.1.15", features = ["derive", "env"] } \ No newline at end of file +clap = { version = "3.1.15", features = ["derive", "env"] } +actix-web = "4" +futures = "0.3.21" diff --git a/src/main.rs b/src/main.rs index 22710f0..2f77c86 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,10 @@ -use actix_web::{App, HttpRequest, HttpResponse, HttpServer, Responder, web}; +use actix_web::{App, Error, error, HttpRequest, HttpResponse, HttpServer, web}; +use actix_web::web::Payload; use clap::Parser; +use futures::StreamExt; + +const MAX_BODY_SIZE: usize = 262_144; // max payload size is 256k + /// Simple HTTP responder #[derive(Parser, Debug)] @@ -10,24 +15,36 @@ struct Args { listen_address: String, } -async fn handler(req: HttpRequest) -> impl Responder { +async fn handler(req: HttpRequest, mut payload: Payload) -> Result { let mut headers = req.headers().iter() .map(|h| format!("{}: {}", h.0.as_str(), h.1.to_str().unwrap_or_default())) .collect::>(); headers.sort(); - let body = format!( - "Remote Peer: {}\nVerb: {}\nPath: {}\nQuery: {}\n\n=== Headers ===\n{}", + let mut body = web::BytesMut::new(); + while let Some(chunk) = payload.next().await { + let chunk = chunk?; + // limit max size of in-memory payload + if (body.len() + chunk.len()) > MAX_BODY_SIZE { + return Err(error::ErrorBadRequest("overflow")); + } + body.extend_from_slice(&chunk); + } + + + let response = format!( + "Remote Peer: {}\nVerb: {}\nPath: {}\nQuery: {}\n\n=== Headers ===\n{}\n\n=== Body ===\n{}", req.peer_addr().expect("Missing remote peer address!"), req.head().method, req.uri().path(), req.uri().query().unwrap_or_default(), - headers.join("\n") + headers.join("\n"), + String::from_utf8_lossy(&body) ); - HttpResponse::Ok() + Ok(HttpResponse::Ok() .content_type("text/plain") - .body(body) + .body(response)) } #[actix_web::main]