Module tower_http::request_id
source · [−]request-id
only.Expand description
Set and propagate request ids.
Example
use http::{Request, Response, header::HeaderName};
use tower::{Service, ServiceExt, ServiceBuilder};
use tower_http::request_id::{
SetRequestIdLayer, PropagateRequestIdLayer, MakeRequestId, RequestId,
};
use hyper::Body;
use std::sync::{Arc, atomic::{AtomicU64, Ordering}};
// A `MakeRequestId` that increments an atomic counter
#[derive(Clone, Default)]
struct MyMakeRequestId {
counter: Arc<AtomicU64>,
}
impl MakeRequestId for MyMakeRequestId {
fn make_request_id<B>(&mut self, request: &Request<B>) -> Option<RequestId> {
let request_id = self.counter
.fetch_add(1, Ordering::SeqCst)
.to_string()
.parse()
.unwrap();
Some(RequestId::new(request_id))
}
}
let x_request_id = HeaderName::from_static("x-request-id");
let mut svc = ServiceBuilder::new()
// set `x-request-id` header on all requests
.layer(SetRequestIdLayer::new(
x_request_id.clone(),
MyMakeRequestId::default(),
))
// propagate `x-request-id` headers from request to response
.layer(PropagateRequestIdLayer::new(x_request_id))
.service(handler);
let request = Request::new(Body::empty());
let response = svc.ready().await?.call(request).await?;
assert_eq!(response.headers()["x-request-id"], "0");
Additional convenience methods are available on ServiceBuilderExt
:
use tower_http::ServiceBuilderExt;
let mut svc = ServiceBuilder::new()
.set_x_request_id(MyMakeRequestId::default())
.propagate_x_request_id()
.service(handler);
let request = Request::new(Body::empty());
let response = svc.ready().await?.call(request).await?;
assert_eq!(response.headers()["x-request-id"], "0");
See SetRequestId
and PropagateRequestId
for more details.
Using Trace
To have request ids show up correctly in logs produced by Trace
you must apply the layers
in this order:
use tower_http::{
ServiceBuilderExt,
trace::{TraceLayer, DefaultMakeSpan, DefaultOnResponse},
};
let svc = ServiceBuilder::new()
// make sure to set request ids before the request reaches `TraceLayer`
.set_x_request_id(MyMakeRequestId::default())
// log requests and responses
.layer(
TraceLayer::new_for_http()
.make_span_with(DefaultMakeSpan::new().include_headers(true))
.on_response(DefaultOnResponse::new().include_headers(true))
)
// propagate the header to the response before the response reaches `TraceLayer`
.propagate_x_request_id()
.service(handler);
Using UUID
s
Generating request ids from Uuid
s can be done like so:
use tower_http::ServiceBuilderExt;
use http::{Request, Response, header::HeaderName};
use tower::{Service, ServiceExt, ServiceBuilder};
use tower_http::request_id::{
SetRequestIdLayer, PropagateRequestIdLayer, MakeRequestId, RequestId,
};
use uuid::Uuid;
#[derive(Clone, Copy)]
struct MakeRequestUuid;
impl MakeRequestId for MakeRequestUuid {
fn make_request_id<B>(&mut self, request: &Request<B>) -> Option<RequestId> {
let request_id = Uuid::new_v4()
.to_string()
.parse()
.unwrap();
Some(RequestId::new(request_id))
}
}
let mut svc = ServiceBuilder::new()
.set_x_request_id(MakeRequestUuid)
.propagate_x_request_id()
.service(handler);
let request = Request::new(Body::empty());
let response = svc.ready().await?.call(request).await?;
assert!(response.headers().get("x-request-id").is_some());
Doesn’t override existing headers
SetRequestId
and PropagateRequestId
wont override request ids if its already present on
requests or responses. Among other things, this allows other middleware to conditionally set
request ids and use the middleware in this module as a fallback.
Structs
Propagate request ids from requests to responses.
Propagate request ids from requests to responses.
Response future for PropagateRequestId
.
An identifier for a request.
Set request id headers and extensions on requests.
Set request id headers and extensions on requests.
Traits
Trait for producing RequestId
s.