r1_api_layer/
context.rs

1use futures::future::BoxFuture;
2use hyper::header::HeaderName;
3use hyper::{Error, Request, Response, StatusCode, service::Service};
4use url::form_urlencoded;
5use std::default::Default;
6use std::io;
7use std::marker::PhantomData;
8use std::task::{Poll, Context};
9use swagger::auth::{AuthData, Authorization, Bearer, Scopes};
10use swagger::{EmptyContext, Has, Pop, Push, XSpanIdString};
11use crate::{Api, AuthenticationApi};
12use log::error;
13
14pub struct MakeAddContext<T, A> {
15    inner: T,
16    marker: PhantomData<A>,
17}
18
19impl<T, A, B, C, D> MakeAddContext<T, A>
20where
21    A: Default + Push<XSpanIdString, Result = B>,
22    B: Push<Option<AuthData>, Result = C>,
23    C: Push<Option<Authorization>, Result = D>,
24{
25    pub fn new(inner: T) -> MakeAddContext<T, A> {
26        MakeAddContext {
27            inner,
28            marker: PhantomData,
29        }
30    }
31}
32
33// Make a service that adds context.
34impl<Target, T, A, B, C, D> Service<Target> for
35    MakeAddContext<T, A>
36where
37    Target: Send,
38    A: Default + Push<XSpanIdString, Result = B> + Send,
39    B: Push<Option<AuthData>, Result = C>,
40    C: Push<Option<Authorization>, Result = D>,
41    D: Send + 'static,
42    T: Service<Target> + Send,
43    T::Future: Send + 'static
44{
45    type Error = T::Error;
46    type Response = AddContext<T::Response, A, B, C, D>;
47    type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
48
49    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
50        self.inner.poll_ready(cx)
51    }
52
53    fn call(&mut self, target: Target) -> Self::Future {
54        let service = self.inner.call(target);
55
56        Box::pin(async move {
57            Ok(AddContext::new(service.await?))
58        })
59    }
60}
61
62/// Middleware to add context data from the request
63pub struct AddContext<T, A, B, C, D>
64where
65    A: Default + Push<XSpanIdString, Result = B>,
66    B: Push<Option<AuthData>, Result = C>,
67    C: Push<Option<Authorization>, Result = D>
68{
69    inner: T,
70    marker: PhantomData<A>,
71}
72
73impl<T, A, B, C, D> AddContext<T, A, B, C, D>
74where
75    A: Default + Push<XSpanIdString, Result = B>,
76    B: Push<Option<AuthData>, Result = C>,
77    C: Push<Option<Authorization>, Result = D>,
78{
79    pub fn new(inner: T) -> Self {
80        AddContext {
81            inner,
82            marker: PhantomData,
83        }
84    }
85}
86
87impl<T, A, B, C, D, ReqBody> Service<Request<ReqBody>> for AddContext<T, A, B, C, D>
88    where
89        A: Default + Push<XSpanIdString, Result=B>,
90        B: Push<Option<AuthData>, Result=C>,
91        C: Push<Option<Authorization>, Result=D>,
92        D: Send + 'static,
93        T: Service<(Request<ReqBody>, D)> + AuthenticationApi
94{
95    type Error = T::Error;
96    type Future = T::Future;
97    type Response = T::Response;
98
99    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
100        self.inner.poll_ready(cx)
101    }
102
103
104    fn call(&mut self, request: Request<ReqBody>) -> Self::Future {
105        let context = A::default().push(XSpanIdString::get_or_generate(&request));
106        let headers = request.headers();
107
108
109        let context = context.push(None::<AuthData>);
110        let context = context.push(None::<Authorization>);
111
112        self.inner.call((request, context))
113    }
114}