nidus_http/middleware/
request_context.rs1use std::task::{Context, Poll};
2
3use axum::extract::Request;
4use tower::{Layer, Service};
5
6use crate::context::{RequestContext, header_to_string};
7
8pub fn request_context_layer() -> RequestContextLayer {
20 RequestContextLayer
21}
22
23#[derive(Clone, Copy, Debug, Default)]
32pub struct RequestContextLayer;
33
34impl<S> Layer<S> for RequestContextLayer {
35 type Service = RequestContextService<S>;
36
37 fn layer(&self, inner: S) -> Self::Service {
38 RequestContextService { inner }
39 }
40}
41
42#[derive(Clone, Debug)]
44pub struct RequestContextService<S> {
45 inner: S,
46}
47
48impl<S> Service<Request> for RequestContextService<S>
49where
50 S: Service<Request> + Send + 'static,
51 S::Future: Send + 'static,
52 S::Error: Send + 'static,
53{
54 type Response = S::Response;
55 type Error = S::Error;
56 type Future = S::Future;
59
60 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
61 self.inner.poll_ready(cx)
62 }
63
64 fn call(&mut self, request: Request) -> Self::Future {
65 let (mut parts, body) = request.into_parts();
66 let request_id = parts
67 .extensions
68 .remove::<RequestContext>()
69 .map(RequestContext::into_request_id)
70 .or_else(|| header_to_string(&parts.headers, "x-request-id"))
71 .unwrap_or_else(|| "unknown".to_owned());
72 let context = RequestContext::from_parts(&parts, request_id);
73 parts.extensions.insert(context);
74 self.inner.call(Request::from_parts(parts, body))
75 }
76}