aboutsummaryrefslogtreecommitdiffstats
path: root/rust/fatcat-openapi/src/context.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/fatcat-openapi/src/context.rs')
-rw-r--r--rust/fatcat-openapi/src/context.rs135
1 files changed, 135 insertions, 0 deletions
diff --git a/rust/fatcat-openapi/src/context.rs b/rust/fatcat-openapi/src/context.rs
new file mode 100644
index 00000000..1af57be1
--- /dev/null
+++ b/rust/fatcat-openapi/src/context.rs
@@ -0,0 +1,135 @@
+use crate::Api;
+use futures::Future;
+use hyper;
+use hyper::header::HeaderName;
+use hyper::{body::Payload, service::Service, Error, Request, Response, StatusCode};
+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 url::form_urlencoded;
+
+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();
+
+ {
+ use swagger::auth::api_key_from_header;
+
+ if let Some(header) = api_key_from_header(&headers, "Authorization") {
+ let auth_data = AuthData::ApiKey(header);
+ let context = context.push(Some(auth_data));
+ let context = context.push(None::<Authorization>);
+
+ let body = ContextualPayload {
+ inner: body,
+ context: context,
+ };
+
+ return Box::new(self.inner.call(hyper::Request::from_parts(head, body)));
+ }
+ }
+
+ 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)))
+ }
+}