1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use futures::Future;
use hyper;
use hyper::header::HeaderName;
use hyper::{Error, Request, Response, StatusCode, service::Service, body::Payload};
use url::form_urlencoded;
use std::default::Default;
use std::io;
use std::marker::PhantomData;
use swagger::auth::{AuthData, Authorization, Bearer, Scopes};
use swagger::context::ContextualPayload;
use swagger::{EmptyContext, Has, Pop, Push, XSpanIdString};
use crate::Api;

pub struct MakeAddContext<T, A> {
    inner: T,
    marker: PhantomData<A>,
}

impl<T, A, B, C, D> MakeAddContext<T, A>
where
    A: Default + Push<XSpanIdString, Result = B>,
    B: Push<Option<AuthData>, Result = C>,
    C: Push<Option<Authorization>, Result = D>,
{
    pub fn new(inner: T) -> MakeAddContext<T, A> {
        MakeAddContext {
            inner,
            marker: PhantomData,
        }
    }
}

// Make a service that adds context.
impl<'a, T, SC, A, B, C, D, E, ME, S, OB, F> hyper::service::MakeService<&'a SC> for
    MakeAddContext<T, A>
where
    A: Default + Push<XSpanIdString, Result = B>,
    B: Push<Option<AuthData>, Result = C>,
    C: Push<Option<Authorization>, Result = D>,
    D: Send + 'static,
    T: hyper::service::MakeService<
            &'a SC,
            Error = E,
            MakeError = ME,
            Service = S,
            ReqBody = ContextualPayload<hyper::Body, D>,
            ResBody = OB,
            Future = F
    >,
    S: Service<
            Error = E,
            ReqBody = ContextualPayload<hyper::Body, D>,
            ResBody = OB> + 'static,
    ME: swagger::ErrorBound,
    E: swagger::ErrorBound,
    F: Future<Item=S, Error=ME> + Send + 'static,
    S::Future: Send,
    OB: Payload,
{
    type ReqBody = hyper::Body;
    type ResBody = OB;
    type Error = E;
    type MakeError = ME;
    type Service = AddContext<S, A>;
    type Future = Box<dyn Future<Item = Self::Service, Error = ME> + Send + 'static>;

    fn make_service(&mut self, ctx: &'a SC) -> Self::Future {
        Box::new(self.inner.make_service(ctx).map(|s| AddContext::new(s)))
    }
}

/// Middleware to extract authentication data from request
pub struct AddContext<T, A> {
    inner: T,
    marker: PhantomData<A>,
}

impl<T, A, B, C, D> AddContext<T, A>
where
    A: Default + Push<XSpanIdString, Result = B>,
    B: Push<Option<AuthData>, Result = C>,
    C: Push<Option<Authorization>, Result = D>,
    T: Service,
{
    pub fn new(inner: T) -> AddContext<T, A> {
        AddContext {
            inner,
            marker: PhantomData,
        }
    }
}

impl<T, A, B, C, D> Service for AddContext<T, A>
    where
        A: Default + Push<XSpanIdString, Result=B>,
        B: Push<Option<AuthData>, Result=C>,
        C: Push<Option<Authorization>, Result=D>,
        D: Send + 'static,
        T: Service<ReqBody = ContextualPayload<hyper::Body, D>>,
        T::Future: Future<Item=Response<T::ResBody>, Error=T::Error> + Send + 'static
{
    type ReqBody = hyper::Body;
    type ResBody = T::ResBody;
    type Error = T::Error;
    type Future = Box<dyn Future<Item=Response<T::ResBody>, Error=T::Error> + Send + 'static>;

    fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future {
        let context = A::default().push(XSpanIdString::get_or_generate(&req));
        let (head, body) = req.into_parts();
        let headers = head.headers.clone();


        let context = context.push(None::<AuthData>);
        let context = context.push(None::<Authorization>);
        let body = ContextualPayload {
            inner: body,
            context: context,
        };

        Box::new(self.inner.call(hyper::Request::from_parts(head, body)))
    }
}