ecli_server_codegen/
context.rs

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