harden_file_transfer_rs/
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;
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
34    MakeAddContext<T, A>
35where
36    Target: Send,
37    A: Default + Push<XSpanIdString, Result = B> + Send,
38    B: Push<Option<AuthData>, Result = C>,
39    C: Push<Option<Authorization>, Result = D>,
40    D: Send + 'static,
41    T: Service<Target> + Send,
42    T::Future: Send + 'static
43{
44    type Error = T::Error;
45    type Response = AddContext<T::Response, A, B, C, D>;
46    type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
47
48    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
49        self.inner.poll_ready(cx)
50    }
51
52    fn call(&mut self, target: Target) -> Self::Future {
53        let service = self.inner.call(target);
54
55        Box::pin(async move {
56            Ok(AddContext::new(service.await?))
57        })
58    }
59}
60
61/// Middleware to add context data from the request
62pub struct AddContext<T, A, B, C, D>
63where
64    A: Default + Push<XSpanIdString, Result = B>,
65    B: Push<Option<AuthData>, Result = C>,
66    C: Push<Option<Authorization>, Result = D>
67{
68    inner: T,
69    marker: PhantomData<A>,
70}
71
72impl<T, A, B, C, D> AddContext<T, A, B, C, D>
73where
74    A: Default + Push<XSpanIdString, Result = B>,
75    B: Push<Option<AuthData>, Result = C>,
76    C: Push<Option<Authorization>, Result = D>,
77{
78    pub fn new(inner: T) -> Self {
79        AddContext {
80            inner,
81            marker: PhantomData,
82        }
83    }
84}
85
86impl<T, A, B, C, D, ReqBody> Service<Request<ReqBody>> for AddContext<T, A, B, C, D>
87    where
88        A: Default + Push<XSpanIdString, Result=B>,
89        B: Push<Option<AuthData>, Result=C>,
90        C: Push<Option<Authorization>, Result=D>,
91        D: Send + 'static,
92        T: Service<(Request<ReqBody>, D)>
93{
94    type Error = T::Error;
95    type Future = T::Future;
96    type Response = T::Response;
97
98    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
99        self.inner.poll_ready(cx)
100    }
101
102
103    fn call(&mut self, request: Request<ReqBody>) -> Self::Future {
104        let context = A::default().push(XSpanIdString::get_or_generate(&request));
105        let headers = request.headers();
106
107
108        let context = context.push(None::<AuthData>);
109        let context = context.push(None::<Authorization>);
110
111        self.inner.call((request, context))
112    }
113}