Include request body in response

This commit is contained in:
Pierre HUBERT 2022-05-04 15:34:05 +02:00
parent 65d54a9264
commit f363ed1ff0
3 changed files with 87 additions and 9 deletions

60
Cargo.lock generated
View File

@ -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",
]

View File

@ -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"] }
clap = { version = "3.1.15", features = ["derive", "env"] }
actix-web = "4"
futures = "0.3.21"

View File

@ -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<HttpResponse, Error> {
let mut headers = req.headers().iter()
.map(|h| format!("{}: {}", h.0.as_str(), h.1.to_str().unwrap_or_default()))
.collect::<Vec<_>>();
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]