#![cfg_attr(not(feature = "request-id"), allow(unused_imports, dead_code, unreachable_code))]
use aws_smithy_http_server::{
body::{boxed, BoxBody},
routing::IntoMakeService,
serve::serve,
};
#[cfg(feature = "request-id")]
use aws_smithy_http_server::request::request_id::{ServerRequestId, ServerRequestIdProviderLayer};
use http::{header::HeaderName, Request, Response};
use http_body_util::Full;
use hyper::body::{Bytes, Incoming};
use std::convert::Infallible;
use tokio::net::TcpListener;
use tower::{service_fn, ServiceBuilder};
use tracing::info;
#[cfg(feature = "request-id")]
async fn handler(req: Request<Incoming>) -> Result<Response<BoxBody>, Infallible> {
let request_id = req
.extensions()
.get::<ServerRequestId>()
.expect("ServerRequestId should be present");
info!(request_id = %request_id, "Handling request");
let body = boxed(Full::new(Bytes::from(format!(
"Request processed with ID: {request_id}\n"
))));
Ok(Response::new(body))
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
#[cfg(not(feature = "request-id"))]
{
eprintln!("ERROR: This example requires the 'request-id' feature.");
eprintln!();
eprintln!("Please run:");
eprintln!(" cargo run --example request_id --features request-id");
std::process::exit(1);
}
#[cfg(feature = "request-id")]
{
tracing_subscriber::fmt::init();
info!("Starting server with request ID tracking...");
let listener = TcpListener::bind("0.0.0.0:3000").await?;
let app = ServiceBuilder::new()
.layer(ServerRequestIdProviderLayer::new_with_response_header(
HeaderName::from_static("x-request-id"),
))
.service(service_fn(handler));
info!("Server listening on http://0.0.0.0:3000");
info!("Each request will receive a unique x-request-id header");
info!("");
info!("Try:");
info!(" curl -v http://localhost:3000/");
info!(" # Check the x-request-id header in the response");
serve(listener, IntoMakeService::new(app)).await?;
}
Ok(())
}