All checks were successful
continuous-integration/drone/push Build is passing
71 lines
2.0 KiB
Rust
71 lines
2.0 KiB
Rust
use actix_web::web::Payload;
|
|
use actix_web::{App, Error, HttpRequest, HttpResponse, HttpServer, error, web};
|
|
use clap::Parser;
|
|
use futures::StreamExt;
|
|
|
|
const MAX_BODY_SIZE: usize = 262_144; // max payload size is 256k
|
|
|
|
/// Simple HTTP responder
|
|
#[derive(Parser, Debug)]
|
|
#[clap(author, version, about, long_about = None)]
|
|
struct Args {
|
|
/// Listen address
|
|
#[clap(short, long, env, default_value = "0.0.0.0:8000")]
|
|
listen_address: String,
|
|
}
|
|
|
|
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 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"),
|
|
String::from_utf8_lossy(&body)
|
|
);
|
|
|
|
Ok(HttpResponse::Ok().content_type("text/plain").body(response))
|
|
}
|
|
|
|
#[actix_web::main]
|
|
async fn main() -> std::io::Result<()> {
|
|
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
|
|
|
let args: Args = Args::parse();
|
|
|
|
log::info!("Will listen on {}...", args.listen_address);
|
|
|
|
HttpServer::new(|| App::new().route("{tail:.*}", web::route().to(handler)))
|
|
.bind(args.listen_address)?
|
|
.run()
|
|
.await
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use crate::Args;
|
|
#[test]
|
|
fn verify_cli() {
|
|
use clap::CommandFactory;
|
|
Args::command().debug_assert()
|
|
}
|
|
}
|