Skip to main content

tower_request_id_nano/
lib.rs

1//! A tiny [tower] ([hyper], [axum], [warp] etc) service to generate a random id for each
2//! incoming request.
3//!
4//! This crate is a fork of [tower-request-id] crate that uses Nano ID instead of ULID.
5//!
6//! [tower]: https://crates.io/crates/tower
7//! [hyper]: https://crates.io/crates/hyper
8//! [axum]: https://crates.io/crates/axum
9//! [warp]: https://crates.io/crates/warp
10//! [tower-request-id]: https://crates.io/crates/tower-request-id
11
12use std::{
13    fmt,
14    task::{Context, Poll},
15};
16
17use http::Request;
18use nid::{alphabet::Base62Alphabet, Nanoid};
19use tower_layer::Layer;
20use tower_service::Service;
21
22/// A newtype around [`nid::Nanoid<21, Base62Alphabet>`]
23#[derive(Debug, Clone)]
24pub struct RequestId(pub Nanoid<21, Base62Alphabet>);
25
26impl RequestId {
27    fn new() -> Self {
28        Self(Nanoid::new())
29    }
30
31    pub fn as_str(&self) -> &str {
32        self.0.as_str()
33    }
34}
35
36impl fmt::Display for RequestId {
37    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
38        self.0.fmt(f)
39    }
40}
41
42#[derive(Clone, Debug)]
43pub struct RequestIdService<S> {
44    inner: S,
45}
46
47/// Middleware to use [`RequestId`]
48impl<S> RequestIdService<S> {
49    pub fn new(inner: S) -> Self {
50        Self { inner }
51    }
52}
53
54impl<B, S> Service<Request<B>> for RequestIdService<S>
55where
56    S: Service<Request<B>>,
57{
58    type Response = S::Response;
59    type Error = S::Error;
60    type Future = S::Future;
61
62    #[inline]
63    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
64        self.inner.poll_ready(cx)
65    }
66
67    fn call(&mut self, mut req: Request<B>) -> Self::Future {
68        let id = RequestId::new();
69        req.extensions_mut().insert(id);
70        self.inner.call(req)
71    }
72}
73
74/// Layer to apply [`RequestIdService`] middleware.
75#[derive(Clone, Debug)]
76pub struct RequestIdLayer;
77
78impl<S> Layer<S> for RequestIdLayer {
79    type Service = RequestIdService<S>;
80
81    fn layer(&self, inner: S) -> Self::Service {
82        RequestIdService { inner }
83    }
84}