From 39a0c26795097f35e3128d95b20b7d83df89524c Mon Sep 17 00:00:00 2001 From: David Pedersen <david.pdrsn@gmail.com> Date: Fri, 20 Aug 2021 09:26:31 +0200 Subject: [PATCH] Add `print-request-response` example (#216) * Add `print-request-response` example Someone asked about this on Discord. I think its worth adding as an example. * add missing feature --- examples/print-request-response/Cargo.toml | 13 +++++ examples/print-request-response/src/main.rs | 64 +++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 examples/print-request-response/Cargo.toml create mode 100644 examples/print-request-response/src/main.rs diff --git a/examples/print-request-response/Cargo.toml b/examples/print-request-response/Cargo.toml new file mode 100644 index 00000000..8a7f5b59 --- /dev/null +++ b/examples/print-request-response/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "example-print-request-response" +version = "0.1.0" +edition = "2018" +publish = false + +[dependencies] +axum = { path = "../.." } +tokio = { version = "1.0", features = ["full"] } +tracing = "0.1" +tracing-subscriber = "0.2" +tower = { version = "0.4", features = ["util", "filter"] } +hyper = { version = "0.14", features = ["full"] } diff --git a/examples/print-request-response/src/main.rs b/examples/print-request-response/src/main.rs new file mode 100644 index 00000000..d2b68e56 --- /dev/null +++ b/examples/print-request-response/src/main.rs @@ -0,0 +1,64 @@ +//! Run with +//! +//! ```not_rust +//! cargo run -p example-print-request-response +//! ``` + +use axum::{ + body::{Body, BoxBody, Bytes}, + handler::post, + http::{Request, Response}, + Router, +}; +use std::net::SocketAddr; +use tower::{filter::AsyncFilterLayer, util::AndThenLayer, BoxError}; + +#[tokio::main] +async fn main() { + // Set the RUST_LOG, if it hasn't been explicitly defined + if std::env::var("RUST_LOG").is_err() { + std::env::set_var( + "RUST_LOG", + "example_print_request_response=debug,tower_http=debug", + ) + } + tracing_subscriber::fmt::init(); + + let app = Router::new() + .route("/", post(|| async move { "Hello from `POST /`" })) + .layer(AsyncFilterLayer::new(map_request)) + .layer(AndThenLayer::new(map_response)); + + let addr = SocketAddr::from(([127, 0, 0, 1], 3000)); + tracing::debug!("listening on {}", addr); + axum::Server::bind(&addr) + .serve(app.into_make_service()) + .await + .unwrap(); +} + +async fn map_request(req: Request<Body>) -> Result<Request<Body>, BoxError> { + let (parts, body) = req.into_parts(); + let bytes = buffer_and_print("request", body).await?; + let req = Request::from_parts(parts, Body::from(bytes)); + Ok(req) +} + +async fn map_response(res: Response<BoxBody>) -> Result<Response<Body>, BoxError> { + let (parts, body) = res.into_parts(); + let bytes = buffer_and_print("response", body).await?; + let res = Response::from_parts(parts, Body::from(bytes)); + Ok(res) +} + +async fn buffer_and_print<B>(direction: &str, body: B) -> Result<Bytes, BoxError> +where + B: axum::body::HttpBody<Data = Bytes>, + B::Error: Into<BoxError>, +{ + let bytes = hyper::body::to_bytes(body).await.map_err(Into::into)?; + if let Ok(body) = std::str::from_utf8(&bytes) { + tracing::debug!("{} body = {:?}", direction, body); + } + Ok(bytes) +}