openapi_context/
add_context.rs

1//! Hyper service that adds a context to an incoming request and passes it on
2//! to a wrapped service.
3
4use crate::{ContextualPayload, Push, XSpanId};
5use std::marker::PhantomData;
6use std::task::{Context, Poll};
7
8/// Middleware wrapper service, that should be used as the outermost layer in a
9/// stack of hyper services. Adds a context to a plain `hyper::Request` that can be
10/// used by subsequent layers in the stack.
11#[derive(Debug)]
12pub struct AddContextMakeService<C> {
13    phantom: PhantomData<C>
14}
15
16impl<C> AddContextMakeService<C> {
17    /// Create a new AddContextMakeService struct wrapping a value
18    pub fn new() -> Self {
19        AddContextMakeService {
20            phantom: PhantomData,
21        }
22    }
23}
24
25impl<T, C> hyper::service::Service<T> for AddContextMakeService<C> {
26    type Response = AddContextService<T, C>;
27    type Error = std::io::Error;
28    type Future = futures::future::Ready<Result<Self::Response, Self::Error>>;
29
30    fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
31        Ok(()).into()
32    }
33
34    fn call(&mut self, inner: T) -> Self::Future {
35        futures::future::ok(AddContextService::new(inner))
36    }
37}
38
39/// Middleware wrapper service, that should be used as the outermost layer in a
40/// stack of hyper services. Adds a context to a plain `hyper::Request` that can be
41/// used by subsequent layers in the stack. The `AddContextService` struct should
42/// not usually be used directly - when constructing a hyper stack use
43/// `AddContextMakeService`, which will create `AddContextService` instances as needed.
44#[derive(Debug)]
45pub struct AddContextService<T, C> {
46    inner: T,
47    marker: PhantomData<C>,
48}
49
50impl<T, C> AddContextService<T, C> {
51    /// Create a new AddContextService struct wrapping a value
52    pub fn new(inner: T) -> Self {
53        AddContextService {
54            inner,
55            marker: PhantomData,
56        }
57    }
58}
59
60impl<T, C> hyper::service::Service<hyper::Request<hyper::Body>> for AddContextService<T, C>
61    where
62        C: Default + Push<XSpanId> + Send + Sync + 'static,
63        C::Result: Send + Sync + 'static,
64        T: hyper::service::Service<ContextualPayload<C::Result>>,
65{
66    type Response = T::Response;
67    type Error = T::Error;
68    type Future = T::Future;
69
70    fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
71        Ok(()).into()
72    }
73
74    fn call(&mut self, req: hyper::Request<hyper::Body>) -> Self::Future {
75        let x_span_id = XSpanId::get_or_generate(&req);
76        let context = C::default().push(x_span_id);
77
78        self.inner.call(ContextualPayload {
79            inner: req,
80            context: context,
81        })
82    }
83}
84
85