From 3966435fbefd2bf944b9373e31da8616bbcfeb07 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Mon, 26 Mar 2018 16:22:49 +0100 Subject: [PATCH 01/98] defined Has and ExtendsWith traits --- src/context.rs | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/context.rs b/src/context.rs index 77c8d3bc11..4a9375ae81 100644 --- a/src/context.rs +++ b/src/context.rs @@ -2,6 +2,7 @@ use hyper; use auth::{Authorization, AuthData}; +use std::marker::Sized; extern crate slog; /// Request context, both as received in a server handler or as sent in a @@ -19,6 +20,41 @@ pub struct Context { logger: Option, } +pub trait Has { + fn set(&mut self, T); + fn get(&self) -> &T; + fn get_mut(&mut self) -> &mut T; +} + +pub trait ExtendsWith: Has { + fn new(inner: C, item: T) -> Self; +} + +pub struct ContextExtension { + inner: C, + item: T, +} + +impl Has for ContextExtension { + fn set(&mut self, item: T) { + self.item = item; + } + + fn get(&self) -> &T { + &self.item + } + + fn get_mut(&mut self) -> &mut T { + &mut self.item + } +} + +impl ExtendsWith for ContextExtension { + fn new(inner: C, item: T) -> Self { + ContextExtension { inner, item } + } +} + /// Trait for retrieving a logger from a struct. pub trait HasLogger { /// Retrieve the context logger From cd7dab4e57417ab54f31b34580356ab8b04c0c2e Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Tue, 27 Mar 2018 09:45:27 +0100 Subject: [PATCH 02/98] parametrised context type on ContextWrapper and ContextWrapperExt --- src/context.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/context.rs b/src/context.rs index 4a9375ae81..623969bd3c 100644 --- a/src/context.rs +++ b/src/context.rs @@ -111,14 +111,14 @@ impl Context { /// Context wrapper, to bind an API with a context. #[derive(Debug)] -pub struct ContextWrapper<'a, T: 'a> { +pub struct ContextWrapper<'a, T: 'a, C> { api: &'a T, - context: Context, + context: C, } -impl<'a, T> ContextWrapper<'a, T> { +impl<'a, T, C> ContextWrapper<'a, T, C> { /// Create a new ContextWrapper, binding the API and context. - pub fn new(api: &'a T, context: Context) -> ContextWrapper<'a, T> { + pub fn new(api: &'a T, context: C) -> ContextWrapper<'a, T, C> { ContextWrapper { api, context } } @@ -128,18 +128,18 @@ impl<'a, T> ContextWrapper<'a, T> { } /// Borrows the context. - pub fn context(&self) -> &Context { + pub fn context(&self) -> &C { &self.context } } /// Trait to extend an API to make it easy to bind it to a context. -pub trait ContextWrapperExt<'a> +pub trait ContextWrapperExt<'a, C> where Self: Sized, { /// Binds this API to a context. - fn with_context(self: &'a Self, context: Context) -> ContextWrapper<'a, Self> { - ContextWrapper::::new(self, context) + fn with_context(self: &'a Self, context: C) -> ContextWrapper<'a, Self, C> { + ContextWrapper::::new(self, context) } } From 5f6f66cc1e7c6789dcc5845444762a017662c332 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Tue, 27 Mar 2018 12:30:45 +0100 Subject: [PATCH 03/98] added Has impl for Context --- src/context.rs | 21 +++++++++++++++++++-- src/lib.rs | 2 +- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/context.rs b/src/context.rs index 623969bd3c..116a522b76 100644 --- a/src/context.rs +++ b/src/context.rs @@ -11,7 +11,7 @@ extern crate slog; #[derive(Clone, Debug, Default)] pub struct Context { /// Tracking ID when passing a request to another microservice. - pub x_span_id: Option, + pub x_span_id: XSpanIdString, /// Authorization data, filled in from middlewares. pub authorization: Option, @@ -20,6 +20,9 @@ pub struct Context { logger: Option, } +#[derive(Debug, Clone, Default)] +pub struct XSpanIdString(String); + pub trait Has { fn set(&mut self, T); fn get(&self) -> &T; @@ -74,6 +77,20 @@ impl HasLogger for Context { } } +impl Has for Context { + fn set(&mut self, item: XSpanIdString) { + self.x_span_id = item; + } + + fn get(&self) -> &XSpanIdString{ + &self.x_span_id + } + + fn get_mut(&mut self) -> &mut XSpanIdString { + &mut self.x_span_id + } +} + impl Context { /// Create a new, empty, `Context`. pub fn new() -> Context { @@ -83,7 +100,7 @@ impl Context { /// Create a `Context` with a given span ID. pub fn new_with_span_id>(x_span_id: S) -> Context { Context { - x_span_id: Some(x_span_id.into()), + x_span_id: XSpanIdString(x_span_id.into()), ..Context::default() } } diff --git a/src/lib.rs b/src/lib.rs index b6b60b5bf1..522d992bec 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,7 +33,7 @@ pub mod auth; pub use auth::{Authorization, AuthData}; pub mod context; -pub use context::{Context, ContextWrapper}; +pub use context::{Context, ContextWrapper, Has, ExtendsWith, ContextExtension, XSpanIdString}; /// Module with utilities for creating connectors with hyper. pub mod connector; From 5229a5a75035dddd39a0f9eb32e3d32e129747a9 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Tue, 27 Mar 2018 15:22:49 +0100 Subject: [PATCH 04/98] made wrapped value in XSpanIdString public --- src/context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/context.rs b/src/context.rs index 116a522b76..d50f10c8c8 100644 --- a/src/context.rs +++ b/src/context.rs @@ -21,7 +21,7 @@ pub struct Context { } #[derive(Debug, Clone, Default)] -pub struct XSpanIdString(String); +pub struct XSpanIdString(pub String); pub trait Has { fn set(&mut self, T); From e875407949beb5cae0e7739038e21c9c1c4a2050 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Wed, 28 Mar 2018 10:56:28 +0100 Subject: [PATCH 05/98] added extensions of Has implementations for wrapped contexts --- src/context.rs | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/src/context.rs b/src/context.rs index d50f10c8c8..a8cc6bd1f7 100644 --- a/src/context.rs +++ b/src/context.rs @@ -58,6 +58,90 @@ impl ExtendsWith for ContextExtension { } } +impl> Has for ContextExtension> { + fn set(&mut self, item: XSpanIdString) { + self.inner.set(item); + } + + fn get(&self) -> &XSpanIdString { + self.inner.get() + } + + fn get_mut(&mut self) -> &mut XSpanIdString { + self.inner.get_mut() + } +} + +impl>> Has> for ContextExtension { + fn set(&mut self, item: Option) { + self.inner.set(item); + } + + fn get(&self) -> &Option { + self.inner.get() + } + + fn get_mut(&mut self) -> &mut Option { + self.inner.get_mut() + } +} + +impl> Has for ContextExtension { + fn set(&mut self, item: XSpanIdString) { + self.inner.set(item); + } + + fn get(&self) -> &XSpanIdString { + self.inner.get() + } + + fn get_mut(&mut self) -> &mut XSpanIdString { + self.inner.get_mut() + } +} + +impl> Has for ContextExtension { + fn set(&mut self, item: AuthData) { + self.inner.set(item); + } + + fn get(&self) -> &AuthData { + self.inner.get() + } + + fn get_mut(&mut self) -> &mut AuthData { + self.inner.get_mut() + } +} + +impl> Has for ContextExtension> { + fn set(&mut self, item: AuthData) { + self.inner.set(item); + } + + fn get(&self) -> &AuthData { + self.inner.get() + } + + fn get_mut(&mut self) -> &mut AuthData { + self.inner.get_mut() + } +} + +impl>> Has> for ContextExtension { + fn set(&mut self, item: Option) { + self.inner.set(item); + } + + fn get(&self) -> &Option { + self.inner.get() + } + + fn get_mut(&mut self) -> &mut Option { + self.inner.get_mut() + } +} + /// Trait for retrieving a logger from a struct. pub trait HasLogger { /// Retrieve the context logger From ba2c38995d1e39a0cd702e36513a89aef2c17768 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Wed, 28 Mar 2018 11:11:48 +0100 Subject: [PATCH 06/98] made AuthData in context an Option --- src/context.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/context.rs b/src/context.rs index a8cc6bd1f7..59c75a3771 100644 --- a/src/context.rs +++ b/src/context.rs @@ -86,7 +86,7 @@ impl>> Has> for ContextExtens } } -impl> Has for ContextExtension { +impl> Has for ContextExtension> { fn set(&mut self, item: XSpanIdString) { self.inner.set(item); } @@ -100,35 +100,35 @@ impl> Has for ContextExtension } } -impl> Has for ContextExtension { - fn set(&mut self, item: AuthData) { +impl>> Has> for ContextExtension { + fn set(&mut self, item: Option) { self.inner.set(item); } - fn get(&self) -> &AuthData { + fn get(&self) -> &Option { self.inner.get() } - fn get_mut(&mut self) -> &mut AuthData { + fn get_mut(&mut self) -> &mut Option { self.inner.get_mut() } } -impl> Has for ContextExtension> { - fn set(&mut self, item: AuthData) { +impl>> Has> for ContextExtension> { + fn set(&mut self, item: Option) { self.inner.set(item); } - fn get(&self) -> &AuthData { + fn get(&self) -> &Option { self.inner.get() } - fn get_mut(&mut self) -> &mut AuthData { + fn get_mut(&mut self) -> &mut Option { self.inner.get_mut() } } -impl>> Has> for ContextExtension { +impl>> Has> for ContextExtension> { fn set(&mut self, item: Option) { self.inner.set(item); } From f0ff20150f303232d56c92b34cc937b95ee4a419 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Wed, 28 Mar 2018 17:30:13 +0100 Subject: [PATCH 07/98] added macro for defining new context types --- src/context.rs | 165 ++++++++++++++++++++----------------------------- 1 file changed, 67 insertions(+), 98 deletions(-) diff --git a/src/context.rs b/src/context.rs index 59c75a3771..96de881b86 100644 --- a/src/context.rs +++ b/src/context.rs @@ -33,114 +33,83 @@ pub trait ExtendsWith: Has { fn new(inner: C, item: T) -> Self; } -pub struct ContextExtension { - inner: C, - item: T, -} - -impl Has for ContextExtension { - fn set(&mut self, item: T) { - self.item = item; - } - - fn get(&self) -> &T { - &self.item - } - - fn get_mut(&mut self) -> &mut T { - &mut self.item - } -} - -impl ExtendsWith for ContextExtension { - fn new(inner: C, item: T) -> Self { - ContextExtension { inner, item } - } -} - -impl> Has for ContextExtension> { - fn set(&mut self, item: XSpanIdString) { - self.inner.set(item); - } - - fn get(&self) -> &XSpanIdString { - self.inner.get() - } - - fn get_mut(&mut self) -> &mut XSpanIdString { - self.inner.get_mut() - } -} - -impl>> Has> for ContextExtension { - fn set(&mut self, item: Option) { - self.inner.set(item); - } - - fn get(&self) -> &Option { - self.inner.get() - } - - fn get_mut(&mut self) -> &mut Option { - self.inner.get_mut() - } -} - -impl> Has for ContextExtension> { - fn set(&mut self, item: XSpanIdString) { - self.inner.set(item); - } - - fn get(&self) -> &XSpanIdString { - self.inner.get() - } +macro_rules! extend_has_impls_helper { + ($context_name:ident , $type:ty, $($types:ty),+ ) => { + $( + impl> Has<$type> for $context_name { + fn set(&mut self, item: $type) { + self.inner.set(item); + } + + fn get(&self) -> &$type { + self.inner.get() + } + + fn get_mut(&mut self) -> &mut $type { + self.inner.get_mut() + } + } + + impl> Has<$types> for $context_name { + fn set(&mut self, item: $types) { + self.inner.set(item); + } + + fn get(&self) -> &$types { + self.inner.get() + } + + fn get_mut(&mut self) -> &mut $types { + self.inner.get_mut() + } + } + )+ + } +} + +macro_rules! extend_has_impls { + ($context_name:ident, $head:ty, $($tail:ty),+ ) => { + extend_has_impls_helper!($context_name, $head, $($tail),+); + extend_has_impls!($context_name, $($tail),+); + }; + ($context_name:ident, $head:ty) => {}; +} + +macro_rules! new_context_type { + ($context_name:ident, $($types:ty),+ ) => { + pub struct $context_name { + inner: C, + item: T, + } - fn get_mut(&mut self) -> &mut XSpanIdString { - self.inner.get_mut() - } -} + impl Has for $context_name { + fn set(&mut self, item: T) { + self.item = item; + } -impl>> Has> for ContextExtension { - fn set(&mut self, item: Option) { - self.inner.set(item); - } + fn get(&self) -> &T { + &self.item + } - fn get(&self) -> &Option { - self.inner.get() - } - - fn get_mut(&mut self) -> &mut Option { - self.inner.get_mut() - } -} + fn get_mut(&mut self) -> &mut T { + &mut self.item + } + } -impl>> Has> for ContextExtension> { - fn set(&mut self, item: Option) { - self.inner.set(item); - } + impl ExtendsWith for $context_name { + fn new(inner: C, item: T) -> Self { + $context_name { inner, item } + } + } - fn get(&self) -> &Option { - self.inner.get() - } + extend_has_impls!($context_name, $($types),+); + }; - fn get_mut(&mut self) -> &mut Option { - self.inner.get_mut() - } } -impl>> Has> for ContextExtension> { - fn set(&mut self, item: Option) { - self.inner.set(item); - } +new_context_type!(ContextExtension, String, u32, bool); - fn get(&self) -> &Option { - self.inner.get() - } - fn get_mut(&mut self) -> &mut Option { - self.inner.get_mut() - } -} /// Trait for retrieving a logger from a struct. pub trait HasLogger { From 0c9ff0783be11cca8614cceb725453c0314a2e12 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Thu, 29 Mar 2018 10:14:52 +0100 Subject: [PATCH 08/98] added generic context parameter to NoAuthentication wrapper --- src/auth.rs | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/src/auth.rs b/src/auth.rs index 64a9178c71..246bf731d4 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -2,6 +2,7 @@ use std::collections::BTreeSet; use std::io; +use std::marker::PhantomData; use hyper; use hyper::{Request, Response, Error}; use super::Context; @@ -55,35 +56,32 @@ pub enum AuthData { /// No Authenticator, that does not insert any authorization data, denying all /// access to endpoints that require authentication. #[derive(Debug)] -pub struct NoAuthentication(pub T); - -impl hyper::server::NewService for NoAuthentication -where - T: hyper::server::NewService< - Request = (Request, - Context), - Response = Response, - Error = Error, - >, +pub struct NoAuthentication + where C: Default, +{ + inner: T, + marker: PhantomData, +} + +impl hyper::server::NewService for NoAuthentication + where + T: hyper::server::NewService, + C: Default, { type Request = Request; type Response = Response; type Error = Error; - type Instance = NoAuthentication; + type Instance = NoAuthentication; fn new_service(&self) -> Result { - self.0.new_service().map(NoAuthentication) + self.inner.new_service().map(|s| NoAuthentication{inner: s, marker: PhantomData}) } } -impl hyper::server::Service for NoAuthentication -where - T: hyper::server::Service< - Request = (Request, - Context), - Response = Response, - Error = Error, - >, +impl hyper::server::Service for NoAuthentication + where + T: hyper::server::Service, + C: Default, { type Request = Request; type Response = Response; @@ -91,7 +89,7 @@ where type Future = T::Future; fn call(&self, req: Self::Request) -> Self::Future { - self.0.call((req, Context::default())) + self.inner.call((req, C::default())) } } From c321dd47acc11361b24673e7df267762928ebf9d Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Thu, 29 Mar 2018 10:26:24 +0100 Subject: [PATCH 09/98] added generic context type parameters for AllowAllAuthenticator wrapper --- src/auth.rs | 53 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/src/auth.rs b/src/auth.rs index 246bf731d4..0760eeffb4 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -5,7 +5,7 @@ use std::io; use std::marker::PhantomData; use hyper; use hyper::{Request, Response, Error}; -use super::Context; +use super::{Has, ExtendsWith}; /// Authorization scopes. #[derive(Clone, Debug, PartialEq)] @@ -57,7 +57,8 @@ pub enum AuthData { /// access to endpoints that require authentication. #[derive(Debug)] pub struct NoAuthentication - where C: Default, +where + C: Default, { inner: T, marker: PhantomData, @@ -96,47 +97,61 @@ impl hyper::server::Service for NoAuthentication /// Dummy Authenticator, that blindly inserts authorization data, allowing all /// access to an endpoint with the specified subject. #[derive(Debug)] -pub struct AllowAllAuthenticator { +pub struct AllowAllAuthenticator { inner: T, subject: String, + marker1: PhantomData, + marker2: PhantomData, } -impl AllowAllAuthenticator { +impl AllowAllAuthenticator { /// Create a middleware that authorizes with the configured subject. - pub fn new>(inner: T, subject: U) -> AllowAllAuthenticator { + pub fn new>(inner: T, subject: U) -> AllowAllAuthenticator { AllowAllAuthenticator { inner, subject: subject.into(), + marker1: PhantomData, + marker2: PhantomData, } } } -impl hyper::server::NewService for AllowAllAuthenticator - where T: hyper::server::NewService { - type Request = (Request, Option); +impl hyper::server::NewService for AllowAllAuthenticator + where + T: hyper::server::NewService, + C: Has>, + D: ExtendsWith>, +{ + type Request = (Request, C); type Response = Response; type Error = Error; - type Instance = AllowAllAuthenticator; + type Instance = AllowAllAuthenticator; fn new_service(&self) -> Result { self.inner.new_service().map(|s| AllowAllAuthenticator::new(s, self.subject.clone())) } } -impl hyper::server::Service for AllowAllAuthenticator - where T: hyper::server::Service { - type Request = (Request, Option); +impl hyper::server::Service for AllowAllAuthenticator + where + T: hyper::server::Service, + C: Has>, + D: ExtendsWith>, +{ + type Request = (Request, C); type Response = Response; type Error = Error; type Future = T::Future; - fn call(&self, (req, _): Self::Request) -> Self::Future { - let mut context = Context::default(); - context.authorization = Some(Authorization{ - subject: self.subject.clone(), - scopes: Scopes::All, - issuer: None, - }); + fn call(&self, (req, context): Self::Request) -> Self::Future { + let context = D::new( + context, + Some(Authorization{ + subject: self.subject.clone(), + scopes: Scopes::All, + issuer: None, + }) + ); self.inner.call((req, context)) } } From 6425be730bffbbf81a31ff64cd95bcc9388fd288 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Thu, 29 Mar 2018 12:07:27 +0100 Subject: [PATCH 10/98] refactored ExtendsWith to use associated types --- src/auth.rs | 4 +-- src/context.rs | 90 ++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 79 insertions(+), 15 deletions(-) diff --git a/src/auth.rs b/src/auth.rs index 0760eeffb4..9564b712be 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -120,7 +120,7 @@ impl hyper::server::NewService for AllowAllAuthenticator where T: hyper::server::NewService, C: Has>, - D: ExtendsWith>, + D: ExtendsWith>, { type Request = (Request, C); type Response = Response; @@ -136,7 +136,7 @@ impl hyper::server::Service for AllowAllAuthenticator where T: hyper::server::Service, C: Has>, - D: ExtendsWith>, + D: ExtendsWith>, { type Request = (Request, C); type Response = Response; diff --git a/src/context.rs b/src/context.rs index 96de881b86..15e4833672 100644 --- a/src/context.rs +++ b/src/context.rs @@ -29,10 +29,59 @@ pub trait Has { fn get_mut(&mut self) -> &mut T; } -pub trait ExtendsWith: Has { - fn new(inner: C, item: T) -> Self; +pub trait ExtendsWith { + type Extends; + type Extension; + fn new(inner: Self::Extends, item: Self::Extension) -> Self; + fn set(&mut self, Self::Extension); + fn get(&self) -> &Self::Extension; + fn get_mut(&mut self) -> &mut Self::Extension; } +impl Has for (S, T) { + fn set(&mut self, item: S) { + self.0 = item; + } + fn get(&self) -> &S { + &self.0 + } + fn get_mut(&mut self) -> &mut S { + &mut self.0 + } +} + +impl Has for D +where + D: ExtendsWith, +{ + fn set(&mut self, item: T) { + ExtendsWith::set(self, item); + } + fn get(&self) -> &T { + ExtendsWith::get(self) + } + fn get_mut(&mut self) -> &mut T { + ExtendsWith::get_mut(self) + } +} + +// impl Has for D +// where +// D: ExtendsWith, +// T: Has, +// { +// fn set(&mut self, item: S) { +// Has::::get_mut(&mut self).set(item); +// } +// fn get(&self) -> &S { +// Has::::get(&self).get() +// } + +// fn get_mut(&mut self) -> &mut S { +// Has::::get_mut(&mut self).get_mut() +// } +// } + macro_rules! extend_has_impls_helper { ($context_name:ident , $type:ty, $($types:ty),+ ) => { $( @@ -82,26 +131,41 @@ macro_rules! new_context_type { item: T, } - impl Has for $context_name { - fn set(&mut self, item: T) { + // impl Has for $context_name { + // fn set(&mut self, item: T) { + // self.item = item; + // } + + // fn get(&self) -> &T { + // &self.item + // } + + // fn get_mut(&mut self) -> &mut T { + // &mut self.item + // } + // } + + impl ExtendsWith for $context_name { + type Extends = C; + type Extension = T; + + fn new(inner: C, item: T) -> Self { + $context_name { inner, item } + } + + fn set(&mut self, item: Self::Extension) { self.item = item; } - fn get(&self) -> &T { + fn get(&self) -> &Self::Extension { &self.item } - fn get_mut(&mut self) -> &mut T { + fn get_mut(&mut self) -> &mut Self::Extension { &mut self.item } } - impl ExtendsWith for $context_name { - fn new(inner: C, item: T) -> Self { - $context_name { inner, item } - } - } - extend_has_impls!($context_name, $($types),+); }; @@ -135,7 +199,7 @@ impl Has for Context { self.x_span_id = item; } - fn get(&self) -> &XSpanIdString{ + fn get(&self) -> &XSpanIdString { &self.x_span_id } From 8a3c03a05fe3c9b285ed121d4b2a2fe41a182cba Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Thu, 29 Mar 2018 14:50:08 +0100 Subject: [PATCH 11/98] rename associated types of ExtendsWith --- src/auth.rs | 4 ++-- src/context.rs | 40 +++++++++++++--------------------------- 2 files changed, 15 insertions(+), 29 deletions(-) diff --git a/src/auth.rs b/src/auth.rs index 9564b712be..49b0a9d75e 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -120,7 +120,7 @@ impl hyper::server::NewService for AllowAllAuthenticator where T: hyper::server::NewService, C: Has>, - D: ExtendsWith>, + D: ExtendsWith>, { type Request = (Request, C); type Response = Response; @@ -136,7 +136,7 @@ impl hyper::server::Service for AllowAllAuthenticator where T: hyper::server::Service, C: Has>, - D: ExtendsWith>, + D: ExtendsWith>, { type Request = (Request, C); type Response = Response; diff --git a/src/context.rs b/src/context.rs index 15e4833672..1c289baf95 100644 --- a/src/context.rs +++ b/src/context.rs @@ -30,12 +30,12 @@ pub trait Has { } pub trait ExtendsWith { - type Extends; - type Extension; - fn new(inner: Self::Extends, item: Self::Extension) -> Self; - fn set(&mut self, Self::Extension); - fn get(&self) -> &Self::Extension; - fn get_mut(&mut self) -> &mut Self::Extension; + type Inner; + type Ext; + fn new(inner: Self::Inner, item: Self::Ext) -> Self; + fn set(&mut self, Self::Ext); + fn get(&self) -> &Self::Ext; + fn get_mut(&mut self) -> &mut Self::Ext; } impl Has for (S, T) { @@ -52,7 +52,7 @@ impl Has for (S, T) { impl Has for D where - D: ExtendsWith, + D: ExtendsWith, { fn set(&mut self, item: T) { ExtendsWith::set(self, item); @@ -67,7 +67,7 @@ where // impl Has for D // where -// D: ExtendsWith, +// D: ExtendsWith, // T: Has, // { // fn set(&mut self, item: S) { @@ -131,37 +131,23 @@ macro_rules! new_context_type { item: T, } - // impl Has for $context_name { - // fn set(&mut self, item: T) { - // self.item = item; - // } - - // fn get(&self) -> &T { - // &self.item - // } - - // fn get_mut(&mut self) -> &mut T { - // &mut self.item - // } - // } - impl ExtendsWith for $context_name { - type Extends = C; - type Extension = T; + type Inner = C; + type Ext = T; fn new(inner: C, item: T) -> Self { $context_name { inner, item } } - fn set(&mut self, item: Self::Extension) { + fn set(&mut self, item: Self::Ext) { self.item = item; } - fn get(&self) -> &Self::Extension { + fn get(&self) -> &Self::Ext { &self.item } - fn get_mut(&mut self) -> &mut Self::Extension { + fn get_mut(&mut self) -> &mut Self::Ext { &mut self.item } } From 888bafc5098f656317511903bf4212cc93017d7a Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Thu, 29 Mar 2018 15:32:53 +0100 Subject: [PATCH 12/98] add function for retrieving/generating an X-Span-ID --- Cargo.toml | 1 + src/context.rs | 13 +++++++++++++ src/lib.rs | 1 + 3 files changed, 15 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index d05d300b6b..8c5fcd23ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,4 +29,5 @@ openssl = "0.9.14" slog = { version = "2", features = [ "max_level_trace", "release_max_level_debug"] } tokio-core = "0.1.6" futures = "0.1" +uuid = {version = "0.5", features = ["serde", "v4"]} diff --git a/src/context.rs b/src/context.rs index 1c289baf95..c7bc235f83 100644 --- a/src/context.rs +++ b/src/context.rs @@ -3,6 +3,8 @@ use hyper; use auth::{Authorization, AuthData}; use std::marker::Sized; +use uuid::Uuid; +use super::XSpanId; extern crate slog; /// Request context, both as received in a server handler or as sent in a @@ -23,6 +25,17 @@ pub struct Context { #[derive(Debug, Clone, Default)] pub struct XSpanIdString(pub String); +impl XSpanIdString { + pub fn get_or_generate(req: &hyper::Request) -> Self { + XSpanIdString( + req.headers() + .get::() + .map(XSpanId::to_string) + .unwrap_or_else(|| Uuid::new_v4().to_string()) + ) + } +} + pub trait Has { fn set(&mut self, T); fn get(&self) -> &T; diff --git a/src/lib.rs b/src/lib.rs index 522d992bec..d973f0fbf9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,6 +17,7 @@ extern crate base64; extern crate hyper; extern crate futures; +extern crate uuid; use std::fmt; use std::error; From 68024308573604bb67cdf8cc302d989415e8f908 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Thu, 29 Mar 2018 15:40:07 +0100 Subject: [PATCH 13/98] use real types in ContextExtension --- src/context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/context.rs b/src/context.rs index c7bc235f83..00ebe2767c 100644 --- a/src/context.rs +++ b/src/context.rs @@ -170,7 +170,7 @@ macro_rules! new_context_type { } -new_context_type!(ContextExtension, String, u32, bool); +new_context_type!(ContextExtension, XSpanIdString, Option, Option); From d424b33c146d7a71222e3a58dad252fce885c30d Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Thu, 29 Mar 2018 16:52:18 +0100 Subject: [PATCH 14/98] put stricter trait bounds on AllowAllAuthenticator --- src/auth.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/auth.rs b/src/auth.rs index 49b0a9d75e..bc8ae2b144 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -97,14 +97,22 @@ impl hyper::server::Service for NoAuthentication /// Dummy Authenticator, that blindly inserts authorization data, allowing all /// access to an endpoint with the specified subject. #[derive(Debug)] -pub struct AllowAllAuthenticator { +pub struct AllowAllAuthenticator + where + C: Has>, + D: ExtendsWith>, +{ inner: T, subject: String, marker1: PhantomData, marker2: PhantomData, } -impl AllowAllAuthenticator { +impl AllowAllAuthenticator + where + C: Has>, + D: ExtendsWith>, +{ /// Create a middleware that authorizes with the configured subject. pub fn new>(inner: T, subject: U) -> AllowAllAuthenticator { AllowAllAuthenticator { From 2e8fcd32511b0eebec2e8fcd766ba61d19c90cf5 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Thu, 29 Mar 2018 17:12:14 +0100 Subject: [PATCH 15/98] add derived trait implementations for ContextExtension --- src/context.rs | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/src/context.rs b/src/context.rs index 00ebe2767c..c29fb25be7 100644 --- a/src/context.rs +++ b/src/context.rs @@ -78,23 +78,6 @@ where } } -// impl Has for D -// where -// D: ExtendsWith, -// T: Has, -// { -// fn set(&mut self, item: S) { -// Has::::get_mut(&mut self).set(item); -// } -// fn get(&self) -> &S { -// Has::::get(&self).get() -// } - -// fn get_mut(&mut self) -> &mut S { -// Has::::get_mut(&mut self).get_mut() -// } -// } - macro_rules! extend_has_impls_helper { ($context_name:ident , $type:ty, $($types:ty),+ ) => { $( @@ -139,6 +122,7 @@ macro_rules! extend_has_impls { macro_rules! new_context_type { ($context_name:ident, $($types:ty),+ ) => { + #[derive(Debug, Clone, Default)] pub struct $context_name { inner: C, item: T, From 64921e6eb93c3b406ce7d57129abf2fd20b00d4c Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Thu, 29 Mar 2018 17:29:31 +0100 Subject: [PATCH 16/98] removed old Context struct and renamed ContextExtension to Context --- src/composites.rs | 3 +- src/context.rs | 87 +---------------------------------------------- src/lib.rs | 2 +- 3 files changed, 3 insertions(+), 89 deletions(-) diff --git a/src/composites.rs b/src/composites.rs index 873df123bd..e77a831e88 100644 --- a/src/composites.rs +++ b/src/composites.rs @@ -7,7 +7,6 @@ use std::ops::{Deref, DerefMut}; use hyper::server::{Service, NewService}; use hyper::{Request, Response, StatusCode}; use futures::{future, Future}; -use context::Context; /// Trait for getting the path of a request. Must be implemented on the `Request` /// associated type for `NewService`s being combined in a `CompositeNewService`. @@ -22,7 +21,7 @@ impl GetPath for Request { } } -impl GetPath for (Request, Context) { +impl GetPath for (Request, C) { fn path(&self) -> &str { self.0.path() } diff --git a/src/context.rs b/src/context.rs index c29fb25be7..b9f64cad47 100644 --- a/src/context.rs +++ b/src/context.rs @@ -5,22 +5,6 @@ use auth::{Authorization, AuthData}; use std::marker::Sized; use uuid::Uuid; use super::XSpanId; -extern crate slog; - -/// Request context, both as received in a server handler or as sent in a -/// client request. When REST microservices are chained, the Context passes -/// data from the server API to any further HTTP requests. -#[derive(Clone, Debug, Default)] -pub struct Context { - /// Tracking ID when passing a request to another microservice. - pub x_span_id: XSpanIdString, - - /// Authorization data, filled in from middlewares. - pub authorization: Option, - /// Raw authentication data, for use in making HTTP requests as a client. - pub auth_data: Option, - logger: Option, -} #[derive(Debug, Clone, Default)] pub struct XSpanIdString(pub String); @@ -154,77 +138,8 @@ macro_rules! new_context_type { } -new_context_type!(ContextExtension, XSpanIdString, Option, Option); - - - -/// Trait for retrieving a logger from a struct. -pub trait HasLogger { - /// Retrieve the context logger - fn logger(&self) -> &Option; - - /// Set the context logger - fn set_logger(&mut self, logger: slog::Logger); -} - -impl HasLogger for Context { - fn logger(&self) -> &Option { - &self.logger - } - - fn set_logger(&mut self, logger: slog::Logger) { - self.logger = Some(logger); - } -} - -impl Has for Context { - fn set(&mut self, item: XSpanIdString) { - self.x_span_id = item; - } +new_context_type!(Context, XSpanIdString, Option, Option); - fn get(&self) -> &XSpanIdString { - &self.x_span_id - } - - fn get_mut(&mut self) -> &mut XSpanIdString { - &mut self.x_span_id - } -} - -impl Context { - /// Create a new, empty, `Context`. - pub fn new() -> Context { - Context::default() - } - - /// Create a `Context` with a given span ID. - pub fn new_with_span_id>(x_span_id: S) -> Context { - Context { - x_span_id: XSpanIdString(x_span_id.into()), - ..Context::default() - } - } - - /// Set Basic authentication - pub fn auth_basic(&mut self, username: &str, password: &str) { - self.auth_data = Some(AuthData::Basic(hyper::header::Basic { - username: username.to_owned(), - password: Some(password.to_owned()), - })); - } - - /// Set Bearer token authentication - pub fn auth_bearer(&mut self, token: &str) { - self.auth_data = Some(AuthData::Bearer( - hyper::header::Bearer { token: token.to_owned() }, - )); - } - - /// Set ApiKey authentication - pub fn auth_apikey(&mut self, apikey: &str) { - self.auth_data = Some(AuthData::ApiKey(apikey.to_owned())); - } -} /// Context wrapper, to bind an API with a context. #[derive(Debug)] diff --git a/src/lib.rs b/src/lib.rs index d973f0fbf9..e79049bb8d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,7 +34,7 @@ pub mod auth; pub use auth::{Authorization, AuthData}; pub mod context; -pub use context::{Context, ContextWrapper, Has, ExtendsWith, ContextExtension, XSpanIdString}; +pub use context::{Context, ContextWrapper, Has, ExtendsWith, XSpanIdString}; /// Module with utilities for creating connectors with hyper. pub mod connector; From 0ac17301bfae32e1ac4391282312c0b449f9d573 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Tue, 3 Apr 2018 09:27:14 +0100 Subject: [PATCH 17/98] extract X-Span-ID from header in NoAuthentication wrapper --- src/auth.rs | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/auth.rs b/src/auth.rs index bc8ae2b144..356a4da2fc 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -5,7 +5,7 @@ use std::io; use std::marker::PhantomData; use hyper; use hyper::{Request, Response, Error}; -use super::{Has, ExtendsWith}; +use super::{Has, ExtendsWith, XSpanIdString}; /// Authorization scopes. #[derive(Clone, Debug, PartialEq)] @@ -56,33 +56,37 @@ pub enum AuthData { /// No Authenticator, that does not insert any authorization data, denying all /// access to endpoints that require authentication. #[derive(Debug)] -pub struct NoAuthentication +pub struct NoAuthentication where C: Default, + D: ExtendsWith, { inner: T, - marker: PhantomData, + marker1: PhantomData, + marker2: PhantomData, } -impl hyper::server::NewService for NoAuthentication +impl hyper::server::NewService for NoAuthentication where - T: hyper::server::NewService, + T: hyper::server::NewService, C: Default, + D: ExtendsWith, { type Request = Request; type Response = Response; type Error = Error; - type Instance = NoAuthentication; + type Instance = NoAuthentication; fn new_service(&self) -> Result { - self.inner.new_service().map(|s| NoAuthentication{inner: s, marker: PhantomData}) + self.inner.new_service().map(|s| NoAuthentication{inner: s, marker1: PhantomData, marker2: PhantomData}) } } -impl hyper::server::Service for NoAuthentication +impl hyper::server::Service for NoAuthentication where - T: hyper::server::Service, + T: hyper::server::Service, C: Default, + D: ExtendsWith, { type Request = Request; type Response = Response; @@ -90,7 +94,9 @@ impl hyper::server::Service for NoAuthentication type Future = T::Future; fn call(&self, req: Self::Request) -> Self::Future { - self.inner.call((req, C::default())) + let x_span_id = XSpanIdString::get_or_generate(&req); + let context = D::new(C::default(), x_span_id); + self.inner.call((req, context)) } } From 225c7a0399c1476b047907979dc6099aff7d85c7 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Tue, 3 Apr 2018 09:31:52 +0100 Subject: [PATCH 18/98] add constructor for NoAuthentication wrapper --- src/auth.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/auth.rs b/src/auth.rs index 356a4da2fc..64040ab721 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -66,6 +66,20 @@ where marker2: PhantomData, } +impl NoAuthentication +where + C: Default, + D: ExtendsWith, +{ + pub fn new(inner: T) -> Self { + NoAuthentication { + inner, + marker1: PhantomData, + marker2: PhantomData, + } + } +} + impl hyper::server::NewService for NoAuthentication where T: hyper::server::NewService, @@ -78,7 +92,7 @@ impl hyper::server::NewService for NoAuthentication type Instance = NoAuthentication; fn new_service(&self) -> Result { - self.inner.new_service().map(|s| NoAuthentication{inner: s, marker1: PhantomData, marker2: PhantomData}) + self.inner.new_service().map(|s| NoAuthentication::new(s)) } } From ed29bca3585bfb9ecf0e1f0d9bebef89ddba7a18 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Tue, 3 Apr 2018 10:19:58 +0100 Subject: [PATCH 19/98] move XSpanIdString to lib and add Display impl --- src/context.rs | 29 +---------------------------- src/lib.rs | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 29 deletions(-) diff --git a/src/context.rs b/src/context.rs index b9f64cad47..41a890b2f7 100644 --- a/src/context.rs +++ b/src/context.rs @@ -3,22 +3,7 @@ use hyper; use auth::{Authorization, AuthData}; use std::marker::Sized; -use uuid::Uuid; -use super::XSpanId; - -#[derive(Debug, Clone, Default)] -pub struct XSpanIdString(pub String); - -impl XSpanIdString { - pub fn get_or_generate(req: &hyper::Request) -> Self { - XSpanIdString( - req.headers() - .get::() - .map(XSpanId::to_string) - .unwrap_or_else(|| Uuid::new_v4().to_string()) - ) - } -} +use super::{XSpanId, XSpanIdString}; pub trait Has { fn set(&mut self, T); @@ -35,18 +20,6 @@ pub trait ExtendsWith { fn get_mut(&mut self) -> &mut Self::Ext; } -impl Has for (S, T) { - fn set(&mut self, item: S) { - self.0 = item; - } - fn get(&self) -> &S { - &self.0 - } - fn get_mut(&mut self) -> &mut S { - &mut self.0 - } -} - impl Has for D where D: ExtendsWith, diff --git a/src/lib.rs b/src/lib.rs index e79049bb8d..cbef73ef7d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,7 +34,7 @@ pub mod auth; pub use auth::{Authorization, AuthData}; pub mod context; -pub use context::{Context, ContextWrapper, Has, ExtendsWith, XSpanIdString}; +pub use context::{Context, ContextWrapper, Has, ExtendsWith}; /// Module with utilities for creating connectors with hyper. pub mod connector; @@ -48,6 +48,26 @@ header! { (XSpanId, "X-Span-ID") => [String] } +#[derive(Debug, Clone, Default)] +pub struct XSpanIdString(pub String); + +impl XSpanIdString { + pub fn get_or_generate(req: &hyper::Request) -> Self { + XSpanIdString( + req.headers() + .get::() + .map(XSpanId::to_string) + .unwrap_or_else(|| uuid::Uuid::new_v4().to_string()) + ) + } +} + +impl fmt::Display for XSpanIdString { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.0) + } +} + /// Very simple error type - just holds a description of the error. This is useful for human /// diagnosis and troubleshooting, but not for applications to parse. The justification for this /// is to deny applications visibility into the communication layer, forcing the application code From dd12ad15a8a4c0a54e558b1766a1e6dca577a685 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Tue, 3 Apr 2018 11:03:01 +0100 Subject: [PATCH 20/98] export new_context_type macro --- src/context.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/context.rs b/src/context.rs index 41a890b2f7..31118e9603 100644 --- a/src/context.rs +++ b/src/context.rs @@ -77,6 +77,7 @@ macro_rules! extend_has_impls { ($context_name:ident, $head:ty) => {}; } +#[macro_export] macro_rules! new_context_type { ($context_name:ident, $($types:ty),+ ) => { #[derive(Debug, Clone, Default)] From 70128184a40482812ac44f4ba3e2767e6339bc0c Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Tue, 3 Apr 2018 11:28:21 +0100 Subject: [PATCH 21/98] added docstrings --- src/auth.rs | 1 + src/context.rs | 23 +++++++++++++++++++++-- src/lib.rs | 3 +++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/auth.rs b/src/auth.rs index 64040ab721..da0dcb8785 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -71,6 +71,7 @@ where C: Default, D: ExtendsWith, { + /// Create a new NoAuthentication struct wrapping a value pub fn new(inner: T) -> Self { NoAuthentication { inner, diff --git a/src/context.rs b/src/context.rs index 31118e9603..6abba3cd97 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,22 +1,37 @@ //! Module for API context management. -use hyper; use auth::{Authorization, AuthData}; use std::marker::Sized; -use super::{XSpanId, XSpanIdString}; +use super::XSpanIdString; +/// Defines getters and setters for a value of a generic type. pub trait Has { + /// Set the value. fn set(&mut self, T); + /// Get an immutable reference to the value. fn get(&self) -> &T; + /// Get a mutable reference to the value. fn get_mut(&mut self) -> &mut T; } +/// Allows one type to act as an extension of another with an extra field added. pub trait ExtendsWith { + /// The type being extended. type Inner; + + /// The type of the field being added. type Ext; + + /// Create a new extended value. fn new(inner: Self::Inner, item: Self::Ext) -> Self; + + /// Set the added field. fn set(&mut self, Self::Ext); + + /// Get an immutable reference to the added field. fn get(&self) -> &Self::Ext; + + /// Get a mutable reference to the added field. fn get_mut(&mut self) -> &mut Self::Ext; } @@ -80,6 +95,9 @@ macro_rules! extend_has_impls { #[macro_export] macro_rules! new_context_type { ($context_name:ident, $($types:ty),+ ) => { + + /// Wrapper type for building up contexts recursively, adding one item + /// to the context at a time. #[derive(Debug, Clone, Default)] pub struct $context_name { inner: C, @@ -112,6 +130,7 @@ macro_rules! new_context_type { } +/// Create a default context type to export. new_context_type!(Context, XSpanIdString, Option, Option); diff --git a/src/lib.rs b/src/lib.rs index cbef73ef7d..3bd0826e24 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,10 +48,13 @@ header! { (XSpanId, "X-Span-ID") => [String] } +/// Wrapper for a string being used as an X-Span-ID. #[derive(Debug, Clone, Default)] pub struct XSpanIdString(pub String); impl XSpanIdString { + /// Extract an X-Span-ID from a request header if present, and if not + /// generate a new one. pub fn get_or_generate(req: &hyper::Request) -> Self { XSpanIdString( req.headers() From 899d6b41c305074c9180548722c33a1adf96daa9 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Tue, 3 Apr 2018 15:15:28 +0100 Subject: [PATCH 22/98] added UT for contexts --- src/context.rs | 230 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) diff --git a/src/context.rs b/src/context.rs index 6abba3cd97..56c289ba2b 100644 --- a/src/context.rs +++ b/src/context.rs @@ -168,3 +168,233 @@ where ContextWrapper::::new(self, context) } } + + +#[cfg(test)] +mod context_tests { + use hyper::server::{NewService, Service}; + use hyper::{Response, Request, Error, Method, Uri}; + use std::marker::PhantomData; + use std::io; + use std::str::FromStr; + use futures::future::{Future, ok}; + use super::*; + + struct ContextItem1; + struct ContextItem2; + + fn do_something_with_item_1(_: &ContextItem1) {} + fn do_something_with_item_2(_: &ContextItem2) {} + + struct InnerService + where C: Has + Has, + { + marker: PhantomData, + } + + impl Service for InnerService + where C: Has + Has, + { + type Request = (Request, C); + type Response = Response; + type Error = Error; + type Future = Box>; + fn call(&self, (_, context): Self::Request) -> Self::Future { + do_something_with_item_1(Has::::get(&context)); + do_something_with_item_2(Has::::get(&context)); + Box::new(ok(Response::new())) + } + } + + struct InnerNewService + where C: Has + Has, + { + marker: PhantomData, + } + + impl InnerNewService + where C: Has + Has, + { + fn new() -> Self { + InnerNewService { + marker: PhantomData, + } + } + } + + impl NewService for InnerNewService + where C: Has + Has, + { + type Request = (Request, C); + type Response = Response; + type Error = Error; + type Instance = InnerService; + fn new_service(&self) -> Result { + Ok(InnerService{marker: PhantomData}) + } + } + + struct MiddleService + where + T: Service, + C: Has, + D: ExtendsWith, + + { + inner: T, + marker1: PhantomData, + marker2: PhantomData, + } + + impl Service for MiddleService + where + T: Service, + C: Has, + D: ExtendsWith, + { + type Request = (Request, C); + type Response = T::Response; + type Error = T::Error; + type Future = T::Future; + fn call(&self, (req, context): Self::Request) -> Self::Future { + do_something_with_item_1(Has::::get(&context)); + let context = D::new(context, ContextItem2{}); + self.inner.call((req, context)) + } + } + + struct MiddleNewService + where + T: NewService, + C: Has, + D: ExtendsWith, + { + inner: T, + marker1: PhantomData, + marker2: PhantomData, + } + + impl NewService for MiddleNewService + where + T: NewService, + C: Has, + D: ExtendsWith, + { + type Request = (Request, C); + type Response = T::Response; + type Error = T::Error; + type Instance = MiddleService; + fn new_service(&self) -> Result { + self.inner.new_service().map(|s| MiddleService{inner:s, marker1: PhantomData, marker2: PhantomData}) + } + } + + impl MiddleNewService + where + T: NewService, + C: Has, + D: ExtendsWith, + { + fn new(inner: T) -> Self { + MiddleNewService { + inner, + marker1: PhantomData, + marker2:PhantomData, + } + } + } + + struct OuterService + where + T: Service, + C: Default, + D: ExtendsWith, + + { + inner: T, + marker1: PhantomData, + marker2: PhantomData, + } + + impl Service for OuterService + where + T: Service, + C: Default, + D: ExtendsWith, + { + type Request = Request; + type Response = T::Response; + type Error = T::Error; + type Future = T::Future; + fn call(&self, req : Self::Request) -> Self::Future { + let context = D::new(C::default(), ContextItem1 {} ); + self.inner.call((req, context)) + } + } + + struct OuterNewService + where + T: NewService, + C: Default, + D: ExtendsWith, + { + inner: T, + marker1: PhantomData, + marker2: PhantomData, + } + + impl NewService for OuterNewService + where + T: NewService, + C: Default, + D: ExtendsWith, + { + type Request = Request; + type Response = T::Response; + type Error = T::Error; + type Instance = OuterService; + fn new_service(&self) -> Result { + self.inner.new_service().map(|s| OuterService{inner:s, marker1: PhantomData, marker2: PhantomData}) + } + } + + impl OuterNewService + where + T: NewService, + C: Default, + D: ExtendsWith, + { + fn new(inner: T) -> Self { + OuterNewService { + inner, + marker1: PhantomData, + marker2:PhantomData, + } + } + } + + new_context_type!(MyContext, ContextItem1, ContextItem2); + + type Context1 = MyContext<(), ContextItem1>; + type Context2 = MyContext; + + type NewService1 = InnerNewService; + type NewService2 = MiddleNewService; + type NewService3 = OuterNewService; + + #[test] + fn send_request() { + + let new_service : NewService3 = + OuterNewService::new( + MiddleNewService::new( + InnerNewService::new() + ) + ); + + let req = Request::new(Method::Post, Uri::from_str("127.0.0.1:80").unwrap()); + new_service + .new_service().expect("Failed to start new service") + .call(req).wait().expect("Service::call returned an error"); + } +} From 4243baf72ba7dc4f04e8d2aafb31d7758d49c0ce Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Tue, 3 Apr 2018 16:35:15 +0100 Subject: [PATCH 23/98] added documentation and fixed doctests --- src/context.rs | 189 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 146 insertions(+), 43 deletions(-) diff --git a/src/context.rs b/src/context.rs index 56c289ba2b..4c5cfd44b3 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,4 +1,71 @@ //! Module for API context management. +//! +//! This module defines traits and structs that can be used to manage +//! contextual data related to a request, as it is passed through a series of +//! hyper services. +//! +//! `Has`: +//! +//! Used to specify the requirements that a hyper service makes on a generic +//! context type that it receives with a request, e.g. +//! ``` +//! impl hyper::server::Service for MyService +//! where C: Has, +//! { +//! type Request = (hyper::Request, C); +//! type Response = hyper::Response; +//! type Error = hyper::Error; +//! type Future = Box>; +//! fn call(&self, (req, context) : Self::Request) -> Self::Future { +//! do_something_with_my_item(Has::::get(&context)); +//! ... +//! } +//! } +//! ``` +//! +//! `ExtendsWith`: +//! +//! Used to specify what items a middleware service adds to a request context +//! before passing it on to the wrapped service, e.g. +//! +//! impl hyper::server::Service for MyMiddlewareService +//! where +//! T: hyper::server::Service, +//! { +//! type Request = (hyper::Request, C); +//! type Response = hyper::Response; +//! type Error = hyper::Error; +//! type Future = T::Future; +//! fn call(&self, (req, context) : Self::Request) -> Self::Future { +//! let context = D::new(context, MyItem::new()); +//! self.inner.call((req, context)); // where self.inner: T +//! } +//! } +//! +//! `new_context_type!` +//! Defines a struct that can be used to build up contexts recursively by +//! adding one item to the context at a time. The first argument is the name +//! of the newly defined context struct, and subsequent arguments are the types +//! that can be stored in contexts built using this struct. That is, +//! +//! ``` +//! # #[macro_use] extern crate swagger; +//! struct MyType1; +//! struct MyType2; +//! struct MyType3; +//! new_context_type!(MyContext, MyType1, MyType2, MyType3); +//! # fn main() { +//! # } +//! ``` +//! +//! will define a new struct `MyContext`, which implements: +//! - `Has`, +//! - `ExtendsWith`, +//! - `Has` whenever `S` is one of `MyType1`, `MyType2` or `MyType3`, AND +//! `C` implements `Has`. +//! +//! See the `context_tests` module for more usage examples. use auth::{Authorization, AuthData}; use std::marker::Sized; @@ -50,47 +117,47 @@ where } } -macro_rules! extend_has_impls_helper { - ($context_name:ident , $type:ty, $($types:ty),+ ) => { - $( - impl> Has<$type> for $context_name { - fn set(&mut self, item: $type) { - self.inner.set(item); - } - - fn get(&self) -> &$type { - self.inner.get() - } - - fn get_mut(&mut self) -> &mut $type { - self.inner.get_mut() - } - } - - impl> Has<$types> for $context_name { - fn set(&mut self, item: $types) { - self.inner.set(item); - } - - fn get(&self) -> &$types { - self.inner.get() - } - - fn get_mut(&mut self) -> &mut $types { - self.inner.get_mut() - } - } - )+ - } -} - -macro_rules! extend_has_impls { - ($context_name:ident, $head:ty, $($tail:ty),+ ) => { - extend_has_impls_helper!($context_name, $head, $($tail),+); - extend_has_impls!($context_name, $($tail),+); - }; - ($context_name:ident, $head:ty) => {}; -} +// macro_rules! extend_has_impls_helper { +// ($context_name:ident , $type:ty, $($types:ty),+ ) => { +// $( +// impl> Has<$type> for $context_name { +// fn set(&mut self, item: $type) { +// self.inner.set(item); +// } + +// fn get(&self) -> &$type { +// self.inner.get() +// } + +// fn get_mut(&mut self) -> &mut $type { +// self.inner.get_mut() +// } +// } + +// impl> Has<$types> for $context_name { +// fn set(&mut self, item: $types) { +// self.inner.set(item); +// } + +// fn get(&self) -> &$types { +// self.inner.get() +// } + +// fn get_mut(&mut self) -> &mut $types { +// self.inner.get_mut() +// } +// } +// )+ +// } +// } + +// macro_rules! extend_has_impls { +// ($context_name:ident, $head:ty, $($tail:ty),+ ) => { +// extend_has_impls_helper!($context_name, $head, $($tail),+); +// extend_has_impls!($context_name, $($tail),+); +// }; +// ($context_name:ident, $head:ty) => {}; +// } #[macro_export] macro_rules! new_context_type { @@ -104,7 +171,7 @@ macro_rules! new_context_type { item: T, } - impl ExtendsWith for $context_name { + impl $crate::ExtendsWith for $context_name { type Inner = C; type Ext = T; @@ -125,11 +192,47 @@ macro_rules! new_context_type { } } - extend_has_impls!($context_name, $($types),+); + new_context_type!(impl extend_has $context_name, $($types),+); + }; + (impl extend_has $context_name:ident, $head:ty, $($tail:ty),+ ) => { + new_context_type!(impl extend_has_helper $context_name, $head, $($tail),+); + new_context_type!(impl extend_has $context_name, $($tail),+); }; + (impl extend_has $context_name:ident, $head:ty) => {}; + (impl extend_has_helper $context_name:ident , $type:ty, $($types:ty),+ ) => { + $( + impl> $crate::Has<$type> for $context_name { + fn set(&mut self, item: $type) { + self.inner.set(item); + } + + fn get(&self) -> &$type { + self.inner.get() + } + + fn get_mut(&mut self) -> &mut $type { + self.inner.get_mut() + } + } + impl> $crate::Has<$types> for $context_name { + fn set(&mut self, item: $types) { + self.inner.set(item); + } + + fn get(&self) -> &$types { + self.inner.get() + } + + fn get_mut(&mut self) -> &mut $types { + self.inner.get_mut() + } + } + )+ + }; } + /// Create a default context type to export. new_context_type!(Context, XSpanIdString, Option, Option); From d0052981022805778e7db851d70e23e227843e7a Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Tue, 3 Apr 2018 16:52:59 +0100 Subject: [PATCH 24/98] tidied up formatting --- src/context.rs | 42 ------------------------------------------ 1 file changed, 42 deletions(-) diff --git a/src/context.rs b/src/context.rs index 4c5cfd44b3..972d6f3bc6 100644 --- a/src/context.rs +++ b/src/context.rs @@ -117,48 +117,6 @@ where } } -// macro_rules! extend_has_impls_helper { -// ($context_name:ident , $type:ty, $($types:ty),+ ) => { -// $( -// impl> Has<$type> for $context_name { -// fn set(&mut self, item: $type) { -// self.inner.set(item); -// } - -// fn get(&self) -> &$type { -// self.inner.get() -// } - -// fn get_mut(&mut self) -> &mut $type { -// self.inner.get_mut() -// } -// } - -// impl> Has<$types> for $context_name { -// fn set(&mut self, item: $types) { -// self.inner.set(item); -// } - -// fn get(&self) -> &$types { -// self.inner.get() -// } - -// fn get_mut(&mut self) -> &mut $types { -// self.inner.get_mut() -// } -// } -// )+ -// } -// } - -// macro_rules! extend_has_impls { -// ($context_name:ident, $head:ty, $($tail:ty),+ ) => { -// extend_has_impls_helper!($context_name, $head, $($tail),+); -// extend_has_impls!($context_name, $($tail),+); -// }; -// ($context_name:ident, $head:ty) => {}; -// } - #[macro_export] macro_rules! new_context_type { ($context_name:ident, $($types:ty),+ ) => { From 8ac1a9f4632a822544532a817c1f5ea0b92bcd87 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Tue, 3 Apr 2018 17:28:25 +0100 Subject: [PATCH 25/98] updated changelog and bumped version number --- CHANGELOG.md | 14 ++++++++++++-- Cargo.toml | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b8fb3337b4..ea44d20a00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,9 +9,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed +## [0.11.0] -2018-04-04 +### Added +-- `Has` trait for specifying requirements on context types in hyper services +-- `ExtendsWith` trait for specifying the items added to a context by a hyper middleware service +-- `new_context_type!` macro for defining structs that can be used to build concrete context types that implement `Has` and `ExtendsWith` + +### Removed +-- Old `Context` struct + ## [0.10.0] - 2018-03-16 ### Added --- Stucts for combining multiple hyper services +-- Structs for combining multiple hyper services ### Changed @@ -45,7 +54,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [0.5.0] - 2017-09-18 - Start of changelog. -[Unreleased]: https://github.com/Metaswitch/swagger-rs/compare/0.10.0...HEAD +[Unreleased]: https://github.com/Metaswitch/swagger-rs/compare/0.11.0...HEAD +[0.10.0]: https://github.com/Metaswitch/swagger-rs/compare/0.10.0...0.11.0 [0.10.0]: https://github.com/Metaswitch/swagger-rs/compare/0.9.0...0.10.0 [0.9.0]: https://github.com/Metaswitch/swagger-rs/compare/0.8.1...0.9.0 [0.8.1]: https://github.com/Metaswitch/swagger-rs/compare/0.8.0...0.8.1 diff --git a/Cargo.toml b/Cargo.toml index 8c5fcd23ad..8223873694 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "swagger" -version = "0.10.0" +version = "0.11.0" authors = ["Metaswitch Networks Ltd"] license = "Apache-2.0" description = "A set of common utilities for Rust code generated by swagger-codegen" From 7e2db531ad05dde788d98a9887acb2cbff9c49ac Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Tue, 3 Apr 2018 17:54:16 +0100 Subject: [PATCH 26/98] fix tag in changelog footer --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea44d20a00..03af175099 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,7 +55,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Start of changelog. [Unreleased]: https://github.com/Metaswitch/swagger-rs/compare/0.11.0...HEAD -[0.10.0]: https://github.com/Metaswitch/swagger-rs/compare/0.10.0...0.11.0 +[0.11.0]: https://github.com/Metaswitch/swagger-rs/compare/0.10.0...0.11.0 [0.10.0]: https://github.com/Metaswitch/swagger-rs/compare/0.9.0...0.10.0 [0.9.0]: https://github.com/Metaswitch/swagger-rs/compare/0.8.1...0.9.0 [0.8.1]: https://github.com/Metaswitch/swagger-rs/compare/0.8.0...0.8.1 From 9ec559c91686faca496d14a3d85cfb30ef018955 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Thu, 5 Apr 2018 16:51:57 +0100 Subject: [PATCH 27/98] fixed some lints, moved docstrings to the relevant places --- src/auth.rs | 2 +- src/context.rs | 148 +++++++++++++++++++++++++++---------------------- 2 files changed, 83 insertions(+), 67 deletions(-) diff --git a/src/auth.rs b/src/auth.rs index da0dcb8785..382f4ad479 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -93,7 +93,7 @@ impl hyper::server::NewService for NoAuthentication type Instance = NoAuthentication; fn new_service(&self) -> Result { - self.inner.new_service().map(|s| NoAuthentication::new(s)) + self.inner.new_service().map(NoAuthentication::new) } } diff --git a/src/context.rs b/src/context.rs index 972d6f3bc6..3430118e68 100644 --- a/src/context.rs +++ b/src/context.rs @@ -3,75 +3,42 @@ //! This module defines traits and structs that can be used to manage //! contextual data related to a request, as it is passed through a series of //! hyper services. -//! -//! `Has`: -//! -//! Used to specify the requirements that a hyper service makes on a generic -//! context type that it receives with a request, e.g. -//! ``` -//! impl hyper::server::Service for MyService -//! where C: Has, -//! { -//! type Request = (hyper::Request, C); -//! type Response = hyper::Response; -//! type Error = hyper::Error; -//! type Future = Box>; -//! fn call(&self, (req, context) : Self::Request) -> Self::Future { -//! do_something_with_my_item(Has::::get(&context)); -//! ... -//! } -//! } -//! ``` -//! -//! `ExtendsWith`: -//! -//! Used to specify what items a middleware service adds to a request context -//! before passing it on to the wrapped service, e.g. -//! -//! impl hyper::server::Service for MyMiddlewareService -//! where -//! T: hyper::server::Service, -//! { -//! type Request = (hyper::Request, C); -//! type Response = hyper::Response; -//! type Error = hyper::Error; -//! type Future = T::Future; -//! fn call(&self, (req, context) : Self::Request) -> Self::Future { -//! let context = D::new(context, MyItem::new()); -//! self.inner.call((req, context)); // where self.inner: T -//! } -//! } -//! -//! `new_context_type!` -//! Defines a struct that can be used to build up contexts recursively by -//! adding one item to the context at a time. The first argument is the name -//! of the newly defined context struct, and subsequent arguments are the types -//! that can be stored in contexts built using this struct. That is, -//! -//! ``` -//! # #[macro_use] extern crate swagger; -//! struct MyType1; -//! struct MyType2; -//! struct MyType3; -//! new_context_type!(MyContext, MyType1, MyType2, MyType3); -//! # fn main() { -//! # } -//! ``` -//! -//! will define a new struct `MyContext`, which implements: -//! - `Has`, -//! - `ExtendsWith`, -//! - `Has` whenever `S` is one of `MyType1`, `MyType2` or `MyType3`, AND -//! `C` implements `Has`. -//! -//! See the `context_tests` module for more usage examples. use auth::{Authorization, AuthData}; use std::marker::Sized; use super::XSpanIdString; /// Defines getters and setters for a value of a generic type. +/// +/// Used to specify the requirements that a hyper service makes on a generic +/// context type that it receives with a request, e.g. +/// +/// ```rust +/// extern crate hyper; +/// +/// use std::marker::PhantomData; +/// use context::*; +/// +/// struct MyItem; +/// fn do_something_with_my_item(item: &MyItem) {}; +/// +/// struct MyService { +/// marker: PhantomData, +/// } +/// +/// impl hyper::server::Service for MyService +/// where C: Has, +/// { +/// type Request = (hyper::Request, C); +/// type Response = hyper::Response; +/// type Error = hyper::Error; +/// type Future = Box>; +/// fn call(&self, (req, context) : Self::Request) -> Self::Future { +/// do_something_with_my_item(Has::::get(&context)); +/// //... +/// } +/// } +/// ``` pub trait Has { /// Set the value. fn set(&mut self, T); @@ -81,7 +48,37 @@ pub trait Has { fn get_mut(&mut self) -> &mut T; } + + /// Allows one type to act as an extension of another with an extra field added. +/// +/// Used to specify what items a middleware service adds to a request context +/// before passing it on to the wrapped service, e.g. +/// +/// ```rust +/// struct MyItem; +/// +/// struct MyMiddlewareService { +/// inner: T, +/// marker1: PhantomData, +/// marker2: PhantomData, +/// } +/// +/// impl hyper::server::Service for MyMiddlewareService +/// where +/// T: hyper::server::Service, +/// { +/// type Request = (hyper::Request, C); +/// type Response = hyper::Response; +/// type Error = hyper::Error; +/// type Future = T::Future; +/// fn call(&self, (req, context) : Self::Request) -> Self::Future { +/// let context = D::new(context, MyItem {}); +/// self.inner.call((req, context)); +/// } +/// } +///``` pub trait ExtendsWith { /// The type being extended. type Inner; @@ -117,6 +114,28 @@ where } } +/// Defines a struct that can be used to build up contexts recursively by +/// adding one item to the context at a time. The first argument is the name +/// of the newly defined context struct, and subsequent arguments are the types +/// that can be stored in contexts built using this struct. That is, +/// +/// ```rust +/// # #[macro_use] extern crate swagger; +/// struct MyType1; +/// struct MyType2; +/// struct MyType3; +/// new_context_type!(MyContext, MyType1, MyType2, MyType3); +/// # fn main() { +/// # } +/// ``` +/// +/// will define a new struct `MyContext`, which implements: +/// - `Has`, +/// - `ExtendsWith`, +/// - `Has` whenever `S` is one of `MyType1`, `MyType2` or `MyType3`, AND +/// `C` implements `Has`. +/// +/// See the `context_tests` module for more usage examples. #[macro_export] macro_rules! new_context_type { ($context_name:ident, $($types:ty),+ ) => { @@ -190,11 +209,9 @@ macro_rules! new_context_type { }; } - /// Create a default context type to export. new_context_type!(Context, XSpanIdString, Option, Option); - /// Context wrapper, to bind an API with a context. #[derive(Debug)] pub struct ContextWrapper<'a, T: 'a, C> { @@ -230,7 +247,6 @@ where } } - #[cfg(test)] mod context_tests { use hyper::server::{NewService, Service}; From 819a2c83825b07aaf3480eecaaf57dc1e964a245 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Fri, 6 Apr 2018 09:27:37 +0100 Subject: [PATCH 28/98] combine Has and ExtendsWith and add deconstruct method --- src/auth.rs | 26 ++++---- src/context.rs | 165 +++++++++++++++++++------------------------------ src/lib.rs | 2 +- 3 files changed, 79 insertions(+), 114 deletions(-) diff --git a/src/auth.rs b/src/auth.rs index 382f4ad479..7e3157db03 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -5,7 +5,7 @@ use std::io; use std::marker::PhantomData; use hyper; use hyper::{Request, Response, Error}; -use super::{Has, ExtendsWith, XSpanIdString}; +use super::{Has, XSpanIdString}; /// Authorization scopes. #[derive(Clone, Debug, PartialEq)] @@ -59,7 +59,7 @@ pub enum AuthData { pub struct NoAuthentication where C: Default, - D: ExtendsWith, + D: Has, { inner: T, marker1: PhantomData, @@ -69,7 +69,7 @@ where impl NoAuthentication where C: Default, - D: ExtendsWith, + D: Has, { /// Create a new NoAuthentication struct wrapping a value pub fn new(inner: T) -> Self { @@ -85,7 +85,7 @@ impl hyper::server::NewService for NoAuthentication where T: hyper::server::NewService, C: Default, - D: ExtendsWith, + D: Has, { type Request = Request; type Response = Response; @@ -101,7 +101,7 @@ impl hyper::server::Service for NoAuthentication where T: hyper::server::Service, C: Default, - D: ExtendsWith, + D: Has, { type Request = Request; type Response = Response; @@ -110,7 +110,7 @@ impl hyper::server::Service for NoAuthentication fn call(&self, req: Self::Request) -> Self::Future { let x_span_id = XSpanIdString::get_or_generate(&req); - let context = D::new(C::default(), x_span_id); + let context = D::construct(x_span_id, C::default()); self.inner.call((req, context)) } } @@ -121,7 +121,7 @@ impl hyper::server::Service for NoAuthentication pub struct AllowAllAuthenticator where C: Has>, - D: ExtendsWith>, + D: Has, Remainder=C>, { inner: T, subject: String, @@ -132,7 +132,7 @@ pub struct AllowAllAuthenticator impl AllowAllAuthenticator where C: Has>, - D: ExtendsWith>, + D: Has, Remainder=C>, { /// Create a middleware that authorizes with the configured subject. pub fn new>(inner: T, subject: U) -> AllowAllAuthenticator { @@ -149,7 +149,7 @@ impl hyper::server::NewService for AllowAllAuthenticator where T: hyper::server::NewService, C: Has>, - D: ExtendsWith>, + D: Has, Remainder=C>, { type Request = (Request, C); type Response = Response; @@ -165,7 +165,7 @@ impl hyper::server::Service for AllowAllAuthenticator where T: hyper::server::Service, C: Has>, - D: ExtendsWith>, + D: Has, Remainder=C>, { type Request = (Request, C); type Response = Response; @@ -173,13 +173,13 @@ impl hyper::server::Service for AllowAllAuthenticator type Future = T::Future; fn call(&self, (req, context): Self::Request) -> Self::Future { - let context = D::new( - context, + let context = D::construct( Some(Authorization{ subject: self.subject.clone(), scopes: Scopes::All, issuer: None, - }) + }), + context ); self.inner.call((req, context)) } diff --git a/src/context.rs b/src/context.rs index 3430118e68..7ee0f39c2c 100644 --- a/src/context.rs +++ b/src/context.rs @@ -40,78 +40,18 @@ use super::XSpanIdString; /// } /// ``` pub trait Has { + /// The type that is left after removing the T value. + type Remainder; /// Set the value. fn set(&mut self, T); /// Get an immutable reference to the value. fn get(&self) -> &T; /// Get a mutable reference to the value. fn get_mut(&mut self) -> &mut T; -} - - - -/// Allows one type to act as an extension of another with an extra field added. -/// -/// Used to specify what items a middleware service adds to a request context -/// before passing it on to the wrapped service, e.g. -/// -/// ```rust -/// struct MyItem; -/// -/// struct MyMiddlewareService { -/// inner: T, -/// marker1: PhantomData, -/// marker2: PhantomData, -/// } -/// -/// impl hyper::server::Service for MyMiddlewareService -/// where -/// T: hyper::server::Service, -/// { -/// type Request = (hyper::Request, C); -/// type Response = hyper::Response; -/// type Error = hyper::Error; -/// type Future = T::Future; -/// fn call(&self, (req, context) : Self::Request) -> Self::Future { -/// let context = D::new(context, MyItem {}); -/// self.inner.call((req, context)); -/// } -/// } -///``` -pub trait ExtendsWith { - /// The type being extended. - type Inner; - - /// The type of the field being added. - type Ext; - - /// Create a new extended value. - fn new(inner: Self::Inner, item: Self::Ext) -> Self; - - /// Set the added field. - fn set(&mut self, Self::Ext); - - /// Get an immutable reference to the added field. - fn get(&self) -> &Self::Ext; - - /// Get a mutable reference to the added field. - fn get_mut(&mut self) -> &mut Self::Ext; -} - -impl Has for D -where - D: ExtendsWith, -{ - fn set(&mut self, item: T) { - ExtendsWith::set(self, item); - } - fn get(&self) -> &T { - ExtendsWith::get(self) - } - fn get_mut(&mut self) -> &mut T { - ExtendsWith::get_mut(self) - } + /// Split into a the value and the remainder. + fn deconstruct(self) -> (T, Self::Remainder); + /// Constructor out of a value and remainder. + fn construct(T, Self::Remainder) -> Self; } /// Defines a struct that can be used to build up contexts recursively by @@ -143,29 +83,32 @@ macro_rules! new_context_type { /// Wrapper type for building up contexts recursively, adding one item /// to the context at a time. #[derive(Debug, Clone, Default)] - pub struct $context_name { - inner: C, - item: T, + pub struct $context_name { + head: T, + tail: C, } - impl $crate::ExtendsWith for $context_name { - type Inner = C; - type Ext = T; + impl Has for $context_name { + type Remainder = C; + + fn set(&mut self, item: T) { + self.head = item; + } - fn new(inner: C, item: T) -> Self { - $context_name { inner, item } + fn get(&self) -> &T { + &self.head } - fn set(&mut self, item: Self::Ext) { - self.item = item; + fn get_mut(&mut self) -> &mut T { + &mut self.head } - fn get(&self) -> &Self::Ext { - &self.item + fn deconstruct(self) -> (T, Self::Remainder){ + (self.head, self.tail) } - fn get_mut(&mut self) -> &mut Self::Ext { - &mut self.item + fn construct(item: T, remainder: Self::Remainder) -> Self { + $context_name{ head: item, tail: remainder} } } @@ -178,31 +121,53 @@ macro_rules! new_context_type { (impl extend_has $context_name:ident, $head:ty) => {}; (impl extend_has_helper $context_name:ident , $type:ty, $($types:ty),+ ) => { $( - impl> $crate::Has<$type> for $context_name { + impl> $crate::Has<$type> for $context_name<$types, C> { + type Remainder = $context_name<$types, C::Remainder>; + fn set(&mut self, item: $type) { - self.inner.set(item); + self.tail.set(item); } fn get(&self) -> &$type { - self.inner.get() + self.tail.get() } fn get_mut(&mut self) -> &mut $type { - self.inner.get_mut() + self.tail.get_mut() + } + + fn deconstruct(self) -> ($type, Self::Remainder) { + let (item, remainder) = self.tail.deconstruct(); + (item, $context_name { head: self.head, tail: remainder}) + } + + fn construct(item: $type, remainder: Self::Remainder) -> Self { + $context_name { head: remainder.head, tail: C::construct(item, remainder.tail)} } } - impl> $crate::Has<$types> for $context_name { + impl> $crate::Has<$types> for $context_name<$type, C> { + type Remainder = $context_name<$type, C::Remainder>; + fn set(&mut self, item: $types) { - self.inner.set(item); + self.tail.set(item); } fn get(&self) -> &$types { - self.inner.get() + self.tail.get() } fn get_mut(&mut self) -> &mut $types { - self.inner.get_mut() + self.tail.get_mut() + } + + fn deconstruct(self) -> ($types, Self::Remainder) { + let (item, remainder) = self.tail.deconstruct(); + (item, $context_name { head: self.head, tail: remainder}) + } + + fn construct(item: $types, remainder: Self::Remainder) -> Self { + $context_name { head: remainder.head, tail: C::construct(item, remainder.tail)} } } )+ @@ -315,7 +280,7 @@ mod context_tests { where T: Service, C: Has, - D: ExtendsWith, + D: Has, { inner: T, @@ -327,7 +292,7 @@ mod context_tests { where T: Service, C: Has, - D: ExtendsWith, + D: Has, { type Request = (Request, C); type Response = T::Response; @@ -335,7 +300,7 @@ mod context_tests { type Future = T::Future; fn call(&self, (req, context): Self::Request) -> Self::Future { do_something_with_item_1(Has::::get(&context)); - let context = D::new(context, ContextItem2{}); + let context = D::construct(ContextItem2{}, context); self.inner.call((req, context)) } } @@ -344,7 +309,7 @@ mod context_tests { where T: NewService, C: Has, - D: ExtendsWith, + D: Has, { inner: T, marker1: PhantomData, @@ -355,7 +320,7 @@ mod context_tests { where T: NewService, C: Has, - D: ExtendsWith, + D: Has, { type Request = (Request, C); type Response = T::Response; @@ -370,7 +335,7 @@ mod context_tests { where T: NewService, C: Has, - D: ExtendsWith, + D: Has, { fn new(inner: T) -> Self { MiddleNewService { @@ -385,7 +350,7 @@ mod context_tests { where T: Service, C: Default, - D: ExtendsWith, + D: Has, { inner: T, @@ -397,14 +362,14 @@ mod context_tests { where T: Service, C: Default, - D: ExtendsWith, + D: Has, { type Request = Request; type Response = T::Response; type Error = T::Error; type Future = T::Future; fn call(&self, req : Self::Request) -> Self::Future { - let context = D::new(C::default(), ContextItem1 {} ); + let context = D::construct(ContextItem1 {}, C::default() ); self.inner.call((req, context)) } } @@ -413,7 +378,7 @@ mod context_tests { where T: NewService, C: Default, - D: ExtendsWith, + D: Has, { inner: T, marker1: PhantomData, @@ -424,7 +389,7 @@ mod context_tests { where T: NewService, C: Default, - D: ExtendsWith, + D: Has, { type Request = Request; type Response = T::Response; @@ -439,7 +404,7 @@ mod context_tests { where T: NewService, C: Default, - D: ExtendsWith, + D: Has, { fn new(inner: T) -> Self { OuterNewService { diff --git a/src/lib.rs b/src/lib.rs index 3bd0826e24..a94438c0c5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,7 +34,7 @@ pub mod auth; pub use auth::{Authorization, AuthData}; pub mod context; -pub use context::{Context, ContextWrapper, Has, ExtendsWith}; +pub use context::{Context, ContextWrapper, Has}; /// Module with utilities for creating connectors with hyper. pub mod connector; From 16be16e0d0397b9b5139f9fbbc514f1c9f08ed02 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Fri, 6 Apr 2018 09:35:06 +0100 Subject: [PATCH 29/98] fixed context UT --- src/context.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/context.rs b/src/context.rs index 7ee0f39c2c..0a1698e083 100644 --- a/src/context.rs +++ b/src/context.rs @@ -417,8 +417,8 @@ mod context_tests { new_context_type!(MyContext, ContextItem1, ContextItem2); - type Context1 = MyContext<(), ContextItem1>; - type Context2 = MyContext; + type Context1 = MyContext; + type Context2 = MyContext; type NewService1 = InnerNewService; type NewService2 = MiddleNewService; From 07accd65a3565c2b6235e8327752c8065ea9ff26 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Fri, 6 Apr 2018 12:17:31 +0100 Subject: [PATCH 30/98] fixed doctests --- src/auth.rs | 16 ++-- src/context.rs | 244 ++++++++++++++++++++++++++++++------------------- src/lib.rs | 6 +- 3 files changed, 159 insertions(+), 107 deletions(-) diff --git a/src/auth.rs b/src/auth.rs index 7e3157db03..6794152f91 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -59,7 +59,7 @@ pub enum AuthData { pub struct NoAuthentication where C: Default, - D: Has, + D: Has, { inner: T, marker1: PhantomData, @@ -69,7 +69,7 @@ where impl NoAuthentication where C: Default, - D: Has, + D: Has, { /// Create a new NoAuthentication struct wrapping a value pub fn new(inner: T) -> Self { @@ -119,9 +119,9 @@ impl hyper::server::Service for NoAuthentication /// access to an endpoint with the specified subject. #[derive(Debug)] pub struct AllowAllAuthenticator - where - C: Has>, - D: Has, Remainder=C>, +where + C: Has>, + D: Has, Remainder = C>, { inner: T, subject: String, @@ -130,9 +130,9 @@ pub struct AllowAllAuthenticator } impl AllowAllAuthenticator - where - C: Has>, - D: Has, Remainder=C>, +where + C: Has>, + D: Has, Remainder = C>, { /// Create a middleware that authorizes with the configured subject. pub fn new>(inner: T, subject: U) -> AllowAllAuthenticator { diff --git a/src/context.rs b/src/context.rs index 0a1698e083..02baa5277a 100644 --- a/src/context.rs +++ b/src/context.rs @@ -14,14 +14,17 @@ use super::XSpanIdString; /// context type that it receives with a request, e.g. /// /// ```rust -/// extern crate hyper; -/// -/// use std::marker::PhantomData; -/// use context::*; -/// -/// struct MyItem; -/// fn do_something_with_my_item(item: &MyItem) {}; -/// +/// # extern crate hyper; +/// # extern crate swagger; +/// # extern crate futures; +/// # +/// # use swagger::context::*; +/// # use futures::future::{Future, ok}; +/// # use std::marker::PhantomData; +/// # +/// # struct MyItem; +/// # fn do_something_with_my_item(item: &MyItem) {} +/// # /// struct MyService { /// marker: PhantomData, /// } @@ -32,12 +35,14 @@ use super::XSpanIdString; /// type Request = (hyper::Request, C); /// type Response = hyper::Response; /// type Error = hyper::Error; -/// type Future = Box>; +/// type Future = Box>; /// fn call(&self, (req, context) : Self::Request) -> Self::Future { /// do_something_with_my_item(Has::::get(&context)); -/// //... +/// Box::new(ok(hyper::Response::new())) /// } /// } +/// +/// # fn main() {} /// ``` pub trait Has { /// The type that is left after removing the T value. @@ -57,16 +62,55 @@ pub trait Has { /// Defines a struct that can be used to build up contexts recursively by /// adding one item to the context at a time. The first argument is the name /// of the newly defined context struct, and subsequent arguments are the types -/// that can be stored in contexts built using this struct. That is, +/// that can be stored in contexts built using this struct. +/// +/// A cons list built using the generated context type will implement Has +/// for each type T that appears in the list, provided that the list only +/// contains the types that were passed to the macro invocation after the context +/// type name. +/// +/// E.g. /// /// ```rust /// # #[macro_use] extern crate swagger; +/// # use swagger::Has; +/// /// struct MyType1; /// struct MyType2; /// struct MyType3; +/// struct MyType4; +/// /// new_context_type!(MyContext, MyType1, MyType2, MyType3); -/// # fn main() { -/// # } +/// +/// fn use_has_my_type_1> (_: &T) {} +/// fn use_has_my_type_2> (_: &T) {} +/// fn use_has_my_type_3> (_: &T) {} +/// fn use_has_my_type_4> (_: &T) {} +/// +/// type ExampleContext = MyContext>>; +/// type BadContext = MyContext>; +/// +/// fn main() { +/// let context: ExampleContext = MyContext::construct( +/// MyType1{}, +/// MyContext::construct( +/// MyType2{}, +/// MyContext::construct(MyType3{}, ()) +/// ) +/// ); +/// use_has_my_type_1(&context); +/// use_has_my_type_2(&context); +/// use_has_my_type_3(&context); +/// +/// let bad_context: BadContext = MyContext::construct( +/// MyType1{}, +/// MyContext::construct(MyType4{}, ()) +/// ); +/// +/// // will not work +/// // use_has_my_type_4(&bad_context); +/// +/// } /// ``` /// /// will define a new struct `MyContext`, which implements: @@ -88,7 +132,7 @@ macro_rules! new_context_type { tail: C, } - impl Has for $context_name { + impl $crate::Has for $context_name { type Remainder = C; fn set(&mut self, item: T) { @@ -229,59 +273,60 @@ mod context_tests { fn do_something_with_item_2(_: &ContextItem2) {} struct InnerService - where C: Has + Has, + where + C: Has, { marker: PhantomData, } impl Service for InnerService - where C: Has + Has, + where + C: Has, { type Request = (Request, C); type Response = Response; type Error = Error; - type Future = Box>; + type Future = Box>; fn call(&self, (_, context): Self::Request) -> Self::Future { - do_something_with_item_1(Has::::get(&context)); do_something_with_item_2(Has::::get(&context)); Box::new(ok(Response::new())) } } struct InnerNewService - where C: Has + Has, + where + C: Has, { marker: PhantomData, } impl InnerNewService - where C: Has + Has, + where + C: Has, { fn new() -> Self { - InnerNewService { - marker: PhantomData, - } + InnerNewService { marker: PhantomData } } } impl NewService for InnerNewService - where C: Has + Has, + where + C: Has, { type Request = (Request, C); type Response = Response; type Error = Error; type Instance = InnerService; fn new_service(&self) -> Result { - Ok(InnerService{marker: PhantomData}) + Ok(InnerService { marker: PhantomData }) } } struct MiddleService - where - T: Service, - C: Has, - D: Has, - + where + T: Service, + D: Has, + C: Has, { inner: T, marker1: PhantomData, @@ -289,27 +334,28 @@ mod context_tests { } impl Service for MiddleService - where - T: Service, - C: Has, - D: Has, + where + T: Service, + D: Has, + C: Has, { type Request = (Request, C); type Response = T::Response; type Error = T::Error; type Future = T::Future; fn call(&self, (req, context): Self::Request) -> Self::Future { - do_something_with_item_1(Has::::get(&context)); - let context = D::construct(ContextItem2{}, context); + let (item, remainder) = context.deconstruct(); + do_something_with_item_1(&item); + let context = D::construct(ContextItem2 {}, remainder); self.inner.call((req, context)) } } struct MiddleNewService - where - T: NewService, - C: Has, - D: Has, + where + T: NewService, + D: Has, + C: Has, { inner: T, marker1: PhantomData, @@ -317,100 +363,107 @@ mod context_tests { } impl NewService for MiddleNewService - where - T: NewService, - C: Has, - D: Has, + where + T: NewService, + D: Has, + C: Has, { type Request = (Request, C); type Response = T::Response; type Error = T::Error; type Instance = MiddleService; fn new_service(&self) -> Result { - self.inner.new_service().map(|s| MiddleService{inner:s, marker1: PhantomData, marker2: PhantomData}) + self.inner.new_service().map(|s| { + MiddleService { + inner: s, + marker1: PhantomData, + marker2: PhantomData, + } + }) } } impl MiddleNewService - where - T: NewService, - C: Has, - D: Has, + where + T: NewService, + D: Has, + C: Has, { fn new(inner: T) -> Self { MiddleNewService { inner, marker1: PhantomData, - marker2:PhantomData, + marker2: PhantomData, } } } - struct OuterService - where - T: Service, - C: Default, - D: Has, - + struct OuterService + where + T: Service, + D: Has, + >::Remainder: Default, { inner: T, - marker1: PhantomData, - marker2: PhantomData, + marker: PhantomData, } - impl Service for OuterService - where - T: Service, - C: Default, - D: Has, + impl Service for OuterService + where + T: Service, + D: Has, + >::Remainder: Default, { type Request = Request; type Response = T::Response; type Error = T::Error; type Future = T::Future; - fn call(&self, req : Self::Request) -> Self::Future { - let context = D::construct(ContextItem1 {}, C::default() ); + fn call(&self, req: Self::Request) -> Self::Future { + let context = D::construct(ContextItem1 {}, D::Remainder::default()); self.inner.call((req, context)) } } - struct OuterNewService - where - T: NewService, - C: Default, - D: Has, + struct OuterNewService + where + T: NewService, + D: Has, + >::Remainder: Default, { inner: T, - marker1: PhantomData, - marker2: PhantomData, + marker: PhantomData, } - impl NewService for OuterNewService - where - T: NewService, - C: Default, - D: Has, + impl NewService for OuterNewService + where + T: NewService, + D: Has, + >::Remainder: Default, { type Request = Request; type Response = T::Response; type Error = T::Error; - type Instance = OuterService; + type Instance = OuterService; fn new_service(&self) -> Result { - self.inner.new_service().map(|s| OuterService{inner:s, marker1: PhantomData, marker2: PhantomData}) + self.inner.new_service().map(|s| { + OuterService { + inner: s, + marker: PhantomData, + } + }) } } - impl OuterNewService - where - T: NewService, - C: Default, - D: Has, + impl OuterNewService + where + T: NewService, + D: Has, + >::Remainder: Default, { fn new(inner: T) -> Self { OuterNewService { inner, - marker1: PhantomData, - marker2:PhantomData, + marker: PhantomData, } } } @@ -418,25 +471,24 @@ mod context_tests { new_context_type!(MyContext, ContextItem1, ContextItem2); type Context1 = MyContext; - type Context2 = MyContext; + type Context2 = MyContext; type NewService1 = InnerNewService; type NewService2 = MiddleNewService; - type NewService3 = OuterNewService; + type NewService3 = OuterNewService; #[test] fn send_request() { - let new_service : NewService3 = - OuterNewService::new( - MiddleNewService::new( - InnerNewService::new() - ) - ); + let new_service: NewService3 = + OuterNewService::new(MiddleNewService::new(InnerNewService::new())); let req = Request::new(Method::Post, Uri::from_str("127.0.0.1:80").unwrap()); new_service - .new_service().expect("Failed to start new service") - .call(req).wait().expect("Service::call returned an error"); + .new_service() + .expect("Failed to start new service") + .call(req) + .wait() + .expect("Service::call returned an error"); } } diff --git a/src/lib.rs b/src/lib.rs index a94438c0c5..aa18b80b52 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -58,9 +58,9 @@ impl XSpanIdString { pub fn get_or_generate(req: &hyper::Request) -> Self { XSpanIdString( req.headers() - .get::() - .map(XSpanId::to_string) - .unwrap_or_else(|| uuid::Uuid::new_v4().to_string()) + .get::() + .map(XSpanId::to_string) + .unwrap_or_else(|| uuid::Uuid::new_v4().to_string()), ) } } From a1e8607fb34786554b920f7b2ae2667c2ab95150 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Fri, 6 Apr 2018 13:41:15 +0100 Subject: [PATCH 31/98] add to code example for composite services --- src/composites.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/composites.rs b/src/composites.rs index e77a831e88..4bea190770 100644 --- a/src/composites.rs +++ b/src/composites.rs @@ -87,15 +87,15 @@ where /// base path is a prefix of the request path. /// /// Usage: -/// ``` -/// let my_new_service1 = ... -/// let my_new_service2 = ... +/// ```ignore +/// let my_new_service1 = NewService1::new(); +/// let my_new_service2 = NewService2::new(); /// /// let mut composite_new_service = CompositeNewService::new(); /// composite_new_service.push(("/base/path/1", my_new_service1)); /// composite_new_service.push(("/base/path/2", my_new_service2)); /// -/// +/// // use as you would any `NewService` instance /// ``` #[derive(Default)] pub struct CompositeNewService(CompositeNewServiceVec) From 0ecec9f50c985a8fa6bd60e1ae2e3ec9e793e576 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Fri, 6 Apr 2018 14:28:28 +0100 Subject: [PATCH 32/98] update AllowAllAuthenticator to consume AuthData --- src/auth.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/auth.rs b/src/auth.rs index 6794152f91..acdc046b0c 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -121,7 +121,7 @@ impl hyper::server::Service for NoAuthentication pub struct AllowAllAuthenticator where C: Has>, - D: Has, Remainder = C>, + D: Has, Remainder = C::Remainder>, { inner: T, subject: String, @@ -132,7 +132,7 @@ where impl AllowAllAuthenticator where C: Has>, - D: Has, Remainder = C>, + D: Has, Remainder = C::Remainder>, { /// Create a middleware that authorizes with the configured subject. pub fn new>(inner: T, subject: U) -> AllowAllAuthenticator { @@ -149,7 +149,7 @@ impl hyper::server::NewService for AllowAllAuthenticator where T: hyper::server::NewService, C: Has>, - D: Has, Remainder=C>, + D: Has, Remainder = C::Remainder>, { type Request = (Request, C); type Response = Response; @@ -165,7 +165,7 @@ impl hyper::server::Service for AllowAllAuthenticator where T: hyper::server::Service, C: Has>, - D: Has, Remainder=C>, + D: Has, Remainder = C::Remainder>, { type Request = (Request, C); type Response = Response; @@ -173,6 +173,8 @@ impl hyper::server::Service for AllowAllAuthenticator type Future = T::Future; fn call(&self, (req, context): Self::Request) -> Self::Future { + let (_auth_data, context) = context.deconstruct(); + let context = D::construct( Some(Authorization{ subject: self.subject.clone(), From 303326cda70c9a9115bfa09525a66196e1de948a Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Fri, 6 Apr 2018 15:30:29 +0100 Subject: [PATCH 33/98] add macros for constructing context types and values --- src/context.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/context.rs b/src/context.rs index 02baa5277a..41140f5ab4 100644 --- a/src/context.rs +++ b/src/context.rs @@ -221,6 +221,26 @@ macro_rules! new_context_type { /// Create a default context type to export. new_context_type!(Context, XSpanIdString, Option, Option); +#[macro_export] +macro_rules! make_context_ty { + ($context_name:ident, $type:ty $(, $types:ty)* $(,)* ) => { + $context_name<$type, make_context_ty!($context_name, $($types),*)> + }; + ($context_name:ident $(,)* ) => { + () + }; +} + +#[macro_export] +macro_rules! make_context { + ($context_name:ident, $value:expr $(, $values:expr)* $(,)*) => { + $context_name::construct($value, make_context!($context_name, $($values),*)) + }; + ($context_name:ident $(,)* ) => { + () + }; +} + /// Context wrapper, to bind an API with a context. #[derive(Debug)] pub struct ContextWrapper<'a, T: 'a, C> { @@ -452,6 +472,7 @@ mod context_tests { } }) } + } impl OuterNewService From 68472c66ae32671163904db663e6f87d057adece Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Fri, 6 Apr 2018 15:36:24 +0100 Subject: [PATCH 34/98] add documentation for new macros --- src/context.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/context.rs b/src/context.rs index 41140f5ab4..4dc0e05658 100644 --- a/src/context.rs +++ b/src/context.rs @@ -221,6 +221,9 @@ macro_rules! new_context_type { /// Create a default context type to export. new_context_type!(Context, XSpanIdString, Option, Option); +/// Macro for easily defining context types. The first argument should be a +/// context type created with `new_context_type!` and subsequent arguments are the +/// types to be stored in the context, with the outermost first. #[macro_export] macro_rules! make_context_ty { ($context_name:ident, $type:ty $(, $types:ty)* $(,)* ) => { @@ -231,6 +234,9 @@ macro_rules! make_context_ty { }; } +/// Macro for easily defining context values. The first argument should be a +/// context type created with `new_context_type!` and subsequent arguments are the +/// values to be stored in the context, with the outermost first. #[macro_export] macro_rules! make_context { ($context_name:ident, $value:expr $(, $values:expr)* $(,)*) => { @@ -491,8 +497,8 @@ mod context_tests { new_context_type!(MyContext, ContextItem1, ContextItem2); - type Context1 = MyContext; - type Context2 = MyContext; + type Context1 = make_context_ty!(MyContext, ContextItem1); + type Context2 = make_context_ty!(MyContext, ContextItem2); type NewService1 = InnerNewService; type NewService2 = MiddleNewService; From ba0895fbcb7c52067b0a0c604070397e361475eb Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Fri, 6 Apr 2018 17:36:00 +0100 Subject: [PATCH 35/98] rustfmt --- src/context.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/context.rs b/src/context.rs index 4dc0e05658..08cdc1ea3e 100644 --- a/src/context.rs +++ b/src/context.rs @@ -478,7 +478,6 @@ mod context_tests { } }) } - } impl OuterNewService From 5da3b525110aa32fcc2aa2d369a075db24187525 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Fri, 6 Apr 2018 17:47:26 +0100 Subject: [PATCH 36/98] updated changelog and docs --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03af175099..4864c62f96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,9 +11,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [0.11.0] -2018-04-04 ### Added --- `Has` trait for specifying requirements on context types in hyper services --- `ExtendsWith` trait for specifying the items added to a context by a hyper middleware service --- `new_context_type!` macro for defining structs that can be used to build concrete context types that implement `Has` and `ExtendsWith` +-- `Has` trait for specifying requirements on context types in hyper services, and providing methods for manipulating them +-- `new_context_type!` macro for defining structs that can be used to build concrete context types that implement `Has` +-- `make_context!` and `make_context_ty!` for conveniently creating contexts at value and type level ### Removed -- Old `Context` struct From b92f79f382f8b4d0e96f1d3ba99f39bab6b5fed5 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Tue, 10 Apr 2018 09:49:21 +0100 Subject: [PATCH 37/98] use Has, Push, Pop traits --- src/auth.rs | 76 ++++++++---------- src/context.rs | 214 ++++++++++++++++++++++++------------------------- src/lib.rs | 2 +- 3 files changed, 140 insertions(+), 152 deletions(-) diff --git a/src/auth.rs b/src/auth.rs index acdc046b0c..4211025a6d 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -5,7 +5,7 @@ use std::io; use std::marker::PhantomData; use hyper; use hyper::{Request, Response, Error}; -use super::{Has, XSpanIdString}; +use super::{Has, Pop, Push, XSpanIdString}; /// Authorization scopes. #[derive(Clone, Debug, PartialEq)] @@ -56,52 +56,47 @@ pub enum AuthData { /// No Authenticator, that does not insert any authorization data, denying all /// access to endpoints that require authentication. #[derive(Debug)] -pub struct NoAuthentication +pub struct NoAuthentication where - C: Default, - D: Has, + C: Default + Push, { inner: T, marker1: PhantomData, - marker2: PhantomData, } -impl NoAuthentication +impl NoAuthentication where - C: Default, - D: Has, + C: Default + Push, { /// Create a new NoAuthentication struct wrapping a value pub fn new(inner: T) -> Self { NoAuthentication { inner, marker1: PhantomData, - marker2: PhantomData, } } } -impl hyper::server::NewService for NoAuthentication +impl hyper::server::NewService for NoAuthentication where - T: hyper::server::NewService, - C: Default, - D: Has, + C: Default + Push, + T: hyper::server::NewService, + { type Request = Request; type Response = Response; type Error = Error; - type Instance = NoAuthentication; + type Instance = NoAuthentication; fn new_service(&self) -> Result { self.inner.new_service().map(NoAuthentication::new) } } -impl hyper::server::Service for NoAuthentication +impl hyper::server::Service for NoAuthentication where - T: hyper::server::Service, - C: Default, - D: Has, + C: Default + Push, + T: hyper::server::Service, { type Request = Request; type Response = Response; @@ -110,7 +105,7 @@ impl hyper::server::Service for NoAuthentication fn call(&self, req: Self::Request) -> Self::Future { let x_span_id = XSpanIdString::get_or_generate(&req); - let context = D::construct(x_span_id, C::default()); + let context = C::default().push(x_span_id); self.inner.call((req, context)) } } @@ -118,54 +113,53 @@ impl hyper::server::Service for NoAuthentication /// Dummy Authenticator, that blindly inserts authorization data, allowing all /// access to an endpoint with the specified subject. #[derive(Debug)] -pub struct AllowAllAuthenticator +pub struct AllowAllAuthenticator where - C: Has>, - D: Has, Remainder = C::Remainder>, + C: Pop>, + C::Result : Push>, { inner: T, subject: String, marker1: PhantomData, - marker2: PhantomData, } -impl AllowAllAuthenticator +impl AllowAllAuthenticator where - C: Has>, - D: Has, Remainder = C::Remainder>, + C: Pop>, + C::Result : Push>, { /// Create a middleware that authorizes with the configured subject. - pub fn new>(inner: T, subject: U) -> AllowAllAuthenticator { + pub fn new>(inner: T, subject: U) -> AllowAllAuthenticator { AllowAllAuthenticator { inner, subject: subject.into(), marker1: PhantomData, - marker2: PhantomData, } } } -impl hyper::server::NewService for AllowAllAuthenticator +impl hyper::server::NewService for AllowAllAuthenticator where - T: hyper::server::NewService, - C: Has>, - D: Has, Remainder = C::Remainder>, + C: Pop>, + C::Result : Push>, + T: hyper::server::NewService>>::Result), Response=Response, Error=Error>, + { type Request = (Request, C); type Response = Response; type Error = Error; - type Instance = AllowAllAuthenticator; + type Instance = AllowAllAuthenticator; fn new_service(&self) -> Result { self.inner.new_service().map(|s| AllowAllAuthenticator::new(s, self.subject.clone())) } } -impl hyper::server::Service for AllowAllAuthenticator +impl hyper::server::Service for AllowAllAuthenticator where - T: hyper::server::Service, - C: Has>, - D: Has, Remainder = C::Remainder>, + C: Pop>, + C::Result : Push>, + T: hyper::server::Service>>::Result), Response=Response, Error=Error>, { type Request = (Request, C); type Response = Response; @@ -173,16 +167,14 @@ impl hyper::server::Service for AllowAllAuthenticator type Future = T::Future; fn call(&self, (req, context): Self::Request) -> Self::Future { - let (_auth_data, context) = context.deconstruct(); + let (_auth_data, context) = context.pop(); - let context = D::construct( + let context = context.push( Some(Authorization{ subject: self.subject.clone(), scopes: Scopes::All, issuer: None, - }), - context - ); + })); self.inner.call((req, context)) } } diff --git a/src/context.rs b/src/context.rs index 08cdc1ea3e..f39917dd73 100644 --- a/src/context.rs +++ b/src/context.rs @@ -8,10 +8,9 @@ use auth::{Authorization, AuthData}; use std::marker::Sized; use super::XSpanIdString; -/// Defines getters and setters for a value of a generic type. -/// -/// Used to specify the requirements that a hyper service makes on a generic -/// context type that it receives with a request, e.g. +/// Defines methods for accessing, modifying, adding and removing the data stored +/// in a context. Used to specify the requirements that a hyper service makes on +/// a generic context type that it receives with a request, e.g. /// /// ```rust /// # extern crate hyper; @@ -45,18 +44,22 @@ use super::XSpanIdString; /// # fn main() {} /// ``` pub trait Has { - /// The type that is left after removing the T value. - type Remainder; - /// Set the value. - fn set(&mut self, T); /// Get an immutable reference to the value. fn get(&self) -> &T; - /// Get a mutable reference to the value. - fn get_mut(&mut self) -> &mut T; /// Split into a the value and the remainder. - fn deconstruct(self) -> (T, Self::Remainder); - /// Constructor out of a value and remainder. - fn construct(T, Self::Remainder) -> Self; + fn get_mut(&mut self) -> &mut T; + /// Set the value. + fn set(&mut self, value: T); +} + +pub trait Pop { + type Result; + fn pop(self) -> (T, Self::Result); +} + +pub trait Push { + type Result; + fn push(self, T) -> Self::Result; } /// Defines a struct that can be used to build up contexts recursively by @@ -122,7 +125,7 @@ pub trait Has { /// See the `context_tests` module for more usage examples. #[macro_export] macro_rules! new_context_type { - ($context_name:ident, $($types:ty),+ ) => { + ($context_name:ident, $empty_context_name:ident, $($types:ty),+ ) => { /// Wrapper type for building up contexts recursively, adding one item /// to the context at a time. @@ -132,9 +135,17 @@ macro_rules! new_context_type { tail: C, } - impl $crate::Has for $context_name { - type Remainder = C; + #[derive(Debug, Clone, Default)] + pub struct $empty_context_name; + impl $crate::Push for $empty_context_name { + type Result = $context_name; + fn push(self, item: U) -> Self::Result { + $context_name{head: item, tail: Self::default()} + } + } + + impl $crate::Has for $context_name { fn set(&mut self, item: T) { self.head = item; } @@ -146,28 +157,32 @@ macro_rules! new_context_type { fn get_mut(&mut self) -> &mut T { &mut self.head } + } - fn deconstruct(self) -> (T, Self::Remainder){ + impl $crate::Pop for $context_name { + type Result = C; + fn pop(self) -> (T, Self::Result) { (self.head, self.tail) } + } - fn construct(item: T, remainder: Self::Remainder) -> Self { - $context_name{ head: item, tail: remainder} + impl $crate::Push for $context_name { + type Result = $context_name; + fn push(self, item: U) -> Self::Result { + $context_name{head: item, tail: self} } } - new_context_type!(impl extend_has $context_name, $($types),+); + new_context_type!(impl extend_has $context_name, $empty_context_name, $($types),+); }; - (impl extend_has $context_name:ident, $head:ty, $($tail:ty),+ ) => { - new_context_type!(impl extend_has_helper $context_name, $head, $($tail),+); - new_context_type!(impl extend_has $context_name, $($tail),+); + (impl extend_has $context_name:ident, $empty_context_name:ident, $head:ty, $($tail:ty),+ ) => { + new_context_type!(impl extend_has_helper $context_name, $empty_context_name, $head, $($tail),+); + new_context_type!(impl extend_has $context_name, $empty_context_name, $($tail),+); }; - (impl extend_has $context_name:ident, $head:ty) => {}; - (impl extend_has_helper $context_name:ident , $type:ty, $($types:ty),+ ) => { + (impl extend_has $context_name:ident, $empty_context_name:ident, $head:ty) => {}; + (impl extend_has_helper $context_name:ident , $empty_context_name:ident, $type:ty, $($types:ty),+ ) => { $( impl> $crate::Has<$type> for $context_name<$types, C> { - type Remainder = $context_name<$types, C::Remainder>; - fn set(&mut self, item: $type) { self.tail.set(item); } @@ -179,20 +194,9 @@ macro_rules! new_context_type { fn get_mut(&mut self) -> &mut $type { self.tail.get_mut() } - - fn deconstruct(self) -> ($type, Self::Remainder) { - let (item, remainder) = self.tail.deconstruct(); - (item, $context_name { head: self.head, tail: remainder}) - } - - fn construct(item: $type, remainder: Self::Remainder) -> Self { - $context_name { head: remainder.head, tail: C::construct(item, remainder.tail)} - } } impl> $crate::Has<$types> for $context_name<$type, C> { - type Remainder = $context_name<$type, C::Remainder>; - fn set(&mut self, item: $types) { self.tail.set(item); } @@ -204,14 +208,21 @@ macro_rules! new_context_type { fn get_mut(&mut self) -> &mut $types { self.tail.get_mut() } + } - fn deconstruct(self) -> ($types, Self::Remainder) { - let (item, remainder) = self.tail.deconstruct(); - (item, $context_name { head: self.head, tail: remainder}) + impl $crate::Pop<$type> for $context_name<$types, C> where C: Pop<$type> { + type Result = $context_name<$types, C::Result>; + fn pop(self) -> ($type, Self::Result) { + let (value, tail) = self.tail.pop(); + (value, $context_name{ head: self.head, tail: tail}) } + } - fn construct(item: $types, remainder: Self::Remainder) -> Self { - $context_name { head: remainder.head, tail: C::construct(item, remainder.tail)} + impl $crate::Pop<$types> for $context_name<$type, C> where C: Pop<$types> { + type Result = $context_name<$type, C::Result>; + fn pop(self) -> ($types, Self::Result) { + let (value, tail) = self.tail.pop(); + (value, $context_name{ head: self.head, tail: tail}) } } )+ @@ -219,18 +230,18 @@ macro_rules! new_context_type { } /// Create a default context type to export. -new_context_type!(Context, XSpanIdString, Option, Option); +new_context_type!(Context, EmpContext, XSpanIdString, Option, Option); /// Macro for easily defining context types. The first argument should be a /// context type created with `new_context_type!` and subsequent arguments are the /// types to be stored in the context, with the outermost first. #[macro_export] macro_rules! make_context_ty { - ($context_name:ident, $type:ty $(, $types:ty)* $(,)* ) => { - $context_name<$type, make_context_ty!($context_name, $($types),*)> + ($context_name:ident, $empty_context_name:ident, $type:ty $(, $types:ty)* $(,)* ) => { + $context_name<$type, make_context_ty!($context_name, $empty_context_name, $($types),*)> }; - ($context_name:ident $(,)* ) => { - () + ($context_name:ident, $empty_context_name:ident $(,)* ) => { + $empty_context_name }; } @@ -243,7 +254,7 @@ macro_rules! make_context { $context_name::construct($value, make_context!($context_name, $($values),*)) }; ($context_name:ident $(,)* ) => { - () + $empty_context_name::default() }; } @@ -348,128 +359,120 @@ mod context_tests { } } - struct MiddleService + struct MiddleService where - T: Service, - D: Has, - C: Has, + C: Pop, + C::Result : Push, + T: Service>::Result)>, { inner: T, marker1: PhantomData, - marker2: PhantomData, } - impl Service for MiddleService + impl Service for MiddleService where - T: Service, - D: Has, - C: Has, + C: Pop, + C::Result : Push, + T: Service>::Result)>, { type Request = (Request, C); type Response = T::Response; type Error = T::Error; type Future = T::Future; fn call(&self, (req, context): Self::Request) -> Self::Future { - let (item, remainder) = context.deconstruct(); + let (item, context) = context.pop(); do_something_with_item_1(&item); - let context = D::construct(ContextItem2 {}, remainder); + let context = context.push(ContextItem2 {}); self.inner.call((req, context)) } } - struct MiddleNewService + struct MiddleNewService where - T: NewService, - D: Has, - C: Has, + C: Pop, + C::Result : Push, + T: NewService>::Result)>, { inner: T, marker1: PhantomData, - marker2: PhantomData, } - impl NewService for MiddleNewService + impl NewService for MiddleNewService where - T: NewService, - D: Has, - C: Has, + C: Pop, + C::Result : Push, + T: NewService>::Result)>, { type Request = (Request, C); type Response = T::Response; type Error = T::Error; - type Instance = MiddleService; + type Instance = MiddleService; fn new_service(&self) -> Result { self.inner.new_service().map(|s| { MiddleService { inner: s, marker1: PhantomData, - marker2: PhantomData, } }) } } - impl MiddleNewService + impl MiddleNewService where - T: NewService, - D: Has, - C: Has, + C: Pop, + C::Result : Push, + T: NewService>::Result)>, { fn new(inner: T) -> Self { MiddleNewService { inner, marker1: PhantomData, - marker2: PhantomData, } } } - struct OuterService + struct OuterService where - T: Service, - D: Has, - >::Remainder: Default, + C: Default + Push, + T: Service, { inner: T, - marker: PhantomData, + marker: PhantomData, } - impl Service for OuterService + impl Service for OuterService where - T: Service, - D: Has, - >::Remainder: Default, + C: Default + Push, + T: Service, { type Request = Request; type Response = T::Response; type Error = T::Error; type Future = T::Future; fn call(&self, req: Self::Request) -> Self::Future { - let context = D::construct(ContextItem1 {}, D::Remainder::default()); + let context = C::default().push(ContextItem1 {}); self.inner.call((req, context)) } } - struct OuterNewService + struct OuterNewService where - T: NewService, - D: Has, - >::Remainder: Default, + C: Default + Push, + T: NewService, { inner: T, - marker: PhantomData, + marker: PhantomData, } - impl NewService for OuterNewService + impl NewService for OuterNewService where - T: NewService, - D: Has, - >::Remainder: Default, + C: Default + Push, + T: NewService, { type Request = Request; type Response = T::Response; type Error = T::Error; - type Instance = OuterService; + type Instance = OuterService; fn new_service(&self) -> Result { self.inner.new_service().map(|s| { OuterService { @@ -480,11 +483,10 @@ mod context_tests { } } - impl OuterNewService + impl OuterNewService where - T: NewService, - D: Has, - >::Remainder: Default, + C: Default + Push, + T: NewService, { fn new(inner: T) -> Self { OuterNewService { @@ -494,20 +496,14 @@ mod context_tests { } } - new_context_type!(MyContext, ContextItem1, ContextItem2); - - type Context1 = make_context_ty!(MyContext, ContextItem1); - type Context2 = make_context_ty!(MyContext, ContextItem2); + new_context_type!(MyContext, MyEmptyContext, ContextItem1, ContextItem2); - type NewService1 = InnerNewService; - type NewService2 = MiddleNewService; - type NewService3 = OuterNewService; #[test] fn send_request() { - let new_service: NewService3 = - OuterNewService::new(MiddleNewService::new(InnerNewService::new())); + let new_service = + OuterNewService::<_, MyEmptyContext>::new(MiddleNewService::new(InnerNewService::new())); let req = Request::new(Method::Post, Uri::from_str("127.0.0.1:80").unwrap()); new_service diff --git a/src/lib.rs b/src/lib.rs index aa18b80b52..1f627e48f1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,7 +34,7 @@ pub mod auth; pub use auth::{Authorization, AuthData}; pub mod context; -pub use context::{Context, ContextWrapper, Has}; +pub use context::{Context, ContextWrapper, Has, Pop, Push}; /// Module with utilities for creating connectors with hyper. pub mod connector; From c5742f67042dbc3034b9a4488930dec88ac24781 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Tue, 10 Apr 2018 10:08:11 +0100 Subject: [PATCH 38/98] export default EmptyContext type --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 1f627e48f1..70709273dc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,7 +34,7 @@ pub mod auth; pub use auth::{Authorization, AuthData}; pub mod context; -pub use context::{Context, ContextWrapper, Has, Pop, Push}; +pub use context::{Context, EmptyContext, ContextWrapper, Has, Pop, Push}; /// Module with utilities for creating connectors with hyper. pub mod connector; From ae43f1e94d57eae455ffc7a5f85081b5ea3e6a9c Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Tue, 10 Apr 2018 10:09:22 +0100 Subject: [PATCH 39/98] fix typo --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 70709273dc..eb6f442895 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,7 +34,7 @@ pub mod auth; pub use auth::{Authorization, AuthData}; pub mod context; -pub use context::{Context, EmptyContext, ContextWrapper, Has, Pop, Push}; +pub use context::{Context, EmpContext, ContextWrapper, Has, Pop, Push}; /// Module with utilities for creating connectors with hyper. pub mod connector; From c34e04df3ce6d96c94226ef64533a078a27f8d93 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Tue, 10 Apr 2018 10:12:08 +0100 Subject: [PATCH 40/98] fix typo --- src/context.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/context.rs b/src/context.rs index f39917dd73..ce7ab21725 100644 --- a/src/context.rs +++ b/src/context.rs @@ -250,10 +250,10 @@ macro_rules! make_context_ty { /// values to be stored in the context, with the outermost first. #[macro_export] macro_rules! make_context { - ($context_name:ident, $value:expr $(, $values:expr)* $(,)*) => { + ($context_name:ident, $empty_context_name:ident, $value:expr $(, $values:expr)* $(,)*) => { $context_name::construct($value, make_context!($context_name, $($values),*)) }; - ($context_name:ident $(,)* ) => { + ($context_name:ident $empty_context_name:ident, $(,)* ) => { $empty_context_name::default() }; } From bbf96941e42f8c686bd11f17c5239aa138ca2408 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Tue, 10 Apr 2018 10:14:55 +0100 Subject: [PATCH 41/98] fix typo --- src/context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/context.rs b/src/context.rs index ce7ab21725..f612b5fb9c 100644 --- a/src/context.rs +++ b/src/context.rs @@ -253,7 +253,7 @@ macro_rules! make_context { ($context_name:ident, $empty_context_name:ident, $value:expr $(, $values:expr)* $(,)*) => { $context_name::construct($value, make_context!($context_name, $($values),*)) }; - ($context_name:ident $empty_context_name:ident, $(,)* ) => { + ($context_name:ident, $empty_context_name:ident $(,)* ) => { $empty_context_name::default() }; } From 311fe088d4f62af50ede727198ce418af044296e Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Tue, 10 Apr 2018 10:17:39 +0100 Subject: [PATCH 42/98] fix typo --- src/context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/context.rs b/src/context.rs index f612b5fb9c..6281a01cee 100644 --- a/src/context.rs +++ b/src/context.rs @@ -251,7 +251,7 @@ macro_rules! make_context_ty { #[macro_export] macro_rules! make_context { ($context_name:ident, $empty_context_name:ident, $value:expr $(, $values:expr)* $(,)*) => { - $context_name::construct($value, make_context!($context_name, $($values),*)) + $context_name::construct($value, make_context!($context_name, $empty_context_name, $($values),*)) }; ($context_name:ident, $empty_context_name:ident $(,)* ) => { $empty_context_name::default() From 4a680762efefa294355ebb0e36ba1a0b1d78709d Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Tue, 10 Apr 2018 10:20:15 +0100 Subject: [PATCH 43/98] update make_context! macro --- src/context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/context.rs b/src/context.rs index 6281a01cee..a4e180ace1 100644 --- a/src/context.rs +++ b/src/context.rs @@ -251,7 +251,7 @@ macro_rules! make_context_ty { #[macro_export] macro_rules! make_context { ($context_name:ident, $empty_context_name:ident, $value:expr $(, $values:expr)* $(,)*) => { - $context_name::construct($value, make_context!($context_name, $empty_context_name, $($values),*)) + $context_name{ head: $value, tail: make_context!($context_name, $empty_context_name, $($values),*)} }; ($context_name:ident, $empty_context_name:ident $(,)* ) => { $empty_context_name::default() From 7d5fbeb48632939beb1e1faa279392dc8f1f258a Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Tue, 10 Apr 2018 10:25:13 +0100 Subject: [PATCH 44/98] fix make_context! macro --- src/context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/context.rs b/src/context.rs index a4e180ace1..de760377c1 100644 --- a/src/context.rs +++ b/src/context.rs @@ -251,7 +251,7 @@ macro_rules! make_context_ty { #[macro_export] macro_rules! make_context { ($context_name:ident, $empty_context_name:ident, $value:expr $(, $values:expr)* $(,)*) => { - $context_name{ head: $value, tail: make_context!($context_name, $empty_context_name, $($values),*)} + make_context!($context_name, $empty_context_name, $($values),*).push($value) }; ($context_name:ident, $empty_context_name:ident $(,)* ) => { $empty_context_name::default() From 0389ab65922bfe3ee7d864eff8df58c610825c4c Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Tue, 10 Apr 2018 17:48:51 +0100 Subject: [PATCH 45/98] fix macro doctests --- src/context.rs | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/src/context.rs b/src/context.rs index de760377c1..ea7f967bd1 100644 --- a/src/context.rs +++ b/src/context.rs @@ -52,7 +52,9 @@ pub trait Has { fn set(&mut self, value: T); } +/// pub trait Pop { + type Result; fn pop(self) -> (T, Self::Result); } @@ -63,9 +65,11 @@ pub trait Push { } /// Defines a struct that can be used to build up contexts recursively by -/// adding one item to the context at a time. The first argument is the name -/// of the newly defined context struct, and subsequent arguments are the types -/// that can be stored in contexts built using this struct. +/// adding one item to the context at a time, and a unit struct representing an +/// empty context. The first argument is the name of the newly defined context struct +/// that is used to add an item to the context, the second argument is the name of +/// the empty context struct, and subsequent arguments are the types +/// that can be stored in contexts built using these struct. /// /// A cons list built using the generated context type will implement Has /// for each type T that appears in the list, provided that the list only @@ -76,40 +80,31 @@ pub trait Push { /// /// ```rust /// # #[macro_use] extern crate swagger; -/// # use swagger::Has; +/// # use swagger::{Has, Pop, Push}; /// /// struct MyType1; /// struct MyType2; /// struct MyType3; /// struct MyType4; /// -/// new_context_type!(MyContext, MyType1, MyType2, MyType3); +/// new_context_type!(MyContext, MyEmpContext, MyType1, MyType2, MyType3); /// /// fn use_has_my_type_1> (_: &T) {} /// fn use_has_my_type_2> (_: &T) {} /// fn use_has_my_type_3> (_: &T) {} /// fn use_has_my_type_4> (_: &T) {} /// -/// type ExampleContext = MyContext>>; -/// type BadContext = MyContext>; +/// type ExampleContext = MyContext>>; +/// type BadContext = MyContext>; /// /// fn main() { -/// let context: ExampleContext = MyContext::construct( -/// MyType1{}, -/// MyContext::construct( -/// MyType2{}, -/// MyContext::construct(MyType3{}, ()) -/// ) -/// ); +/// let context : ExampleContext = MyEmpContext::default().push(MyType3{}).push(MyType2{}).push(MyType1{}); +/// /// use_has_my_type_1(&context); /// use_has_my_type_2(&context); /// use_has_my_type_3(&context); /// -/// let bad_context: BadContext = MyContext::construct( -/// MyType1{}, -/// MyContext::construct(MyType4{}, ()) -/// ); -/// +/// let bad_context: BadContext = MyEmpContext::default().push(MyType4{}).push(MyType1{}); /// // will not work /// // use_has_my_type_4(&bad_context); /// From 27b1ccd61da6c34fee2835671ec5e6dc9340b931 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Wed, 11 Apr 2018 09:17:03 +0100 Subject: [PATCH 46/98] add doctests for Pop and Push --- src/context.rs | 78 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/src/context.rs b/src/context.rs index ea7f967bd1..950b481e01 100644 --- a/src/context.rs +++ b/src/context.rs @@ -52,15 +52,91 @@ pub trait Has { fn set(&mut self, value: T); } +/// Defines a method for permanently extracting a value, changing the resulting +/// type. Used to specify that a hyper service consumes some data from the context, +/// making it unavailable to later layers, e.g. /// +/// ```rust +/// # extern crate hyper; +/// # extern crate swagger; +/// # extern crate futures; +/// # +/// # use swagger::context::*; +/// # use futures::future::{Future, ok}; +/// # use std::marker::PhantomData; +/// # +/// # struct MyItem; +/// # fn do_something_with_my_item(item: &MyItem) {} +/// # +/// struct MiddlewareService { +/// inner: T, +/// marker: PhantomData, +/// } +/// +/// impl hyper::server::Service for MiddlewareService +/// where +/// C: Pop, +/// T: hyper::server::Service +/// { +/// type Request = (hyper::Request, C); +/// type Response = T::Response; +/// type Error = T::Error; +/// type Future = T::Future; +/// fn call(&self, (req, context) : Self::Request) -> Self::Future { +/// let (item, context) = context.pop(); +/// do_something_with_my_item(&item); +/// self.inner.call((req, context)) +/// } +/// } +/// +/// # fn main() {} pub trait Pop { - + /// The type that remains after the value has been popped. type Result; + /// Extracts a value. fn pop(self) -> (T, Self::Result); } +/// Defines a method for inserting a value, changing the resulting +/// type. Used to specify that a hyper service adds some data from the context, +/// making it available to later layers, e.g. +/// +/// ```rust +/// # extern crate hyper; +/// # extern crate swagger; +/// # extern crate futures; +/// # +/// # use swagger::context::*; +/// # use futures::future::{Future, ok}; +/// # use std::marker::PhantomData; +/// # +/// # struct MyItem; +/// # +/// struct MiddlewareService { +/// inner: T, +/// marker: PhantomData, +/// } +/// +/// impl hyper::server::Service for MiddlewareService +/// where +/// C: Push, +/// T: hyper::server::Service +/// { +/// type Request = (hyper::Request, C); +/// type Response = T::Response; +/// type Error = T::Error; +/// type Future = T::Future; +/// fn call(&self, (req, context) : Self::Request) -> Self::Future { +/// let context = context.push(MyItem{}); +/// self.inner.call((req, context)) +/// } +/// } +/// +/// # fn main() {} pub trait Push { + /// The type that results from adding an item. type Result; + /// Inserts a value. fn push(self, T) -> Self::Result; } From f61539206e904ddc16bde154eff78f82dc6914c9 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Wed, 11 Apr 2018 09:26:47 +0100 Subject: [PATCH 47/98] fix lints, formatting, changelog --- CHANGELOG.md | 6 +++--- src/auth.rs | 18 +++++++++--------- src/context.rs | 35 ++++++++++++++++++++++++++--------- 3 files changed, 38 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4864c62f96..25cf59d929 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,10 +9,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed -## [0.11.0] -2018-04-04 +## [0.11.0] -2018-04-11 ### Added --- `Has` trait for specifying requirements on context types in hyper services, and providing methods for manipulating them --- `new_context_type!` macro for defining structs that can be used to build concrete context types that implement `Has` +-- `Has`, `Pop` and `Push` traits for specifying requirements on context types in hyper services, and providing methods for manipulating them +-- `new_context_type!` macro for defining structs that can be used to build concrete context types that implement `Has`, `Pop` and `Push` -- `make_context!` and `make_context_ty!` for conveniently creating contexts at value and type level ### Removed diff --git a/src/auth.rs b/src/auth.rs index 4211025a6d..d006598a58 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -5,7 +5,7 @@ use std::io; use std::marker::PhantomData; use hyper; use hyper::{Request, Response, Error}; -use super::{Has, Pop, Push, XSpanIdString}; +use super::{Pop, Push, XSpanIdString}; /// Authorization scopes. #[derive(Clone, Debug, PartialEq)] @@ -116,7 +116,7 @@ impl hyper::server::Service for NoAuthentication pub struct AllowAllAuthenticator where C: Pop>, - C::Result : Push>, + C::Result: Push>, { inner: T, subject: String, @@ -126,7 +126,7 @@ where impl AllowAllAuthenticator where C: Pop>, - C::Result : Push>, + C::Result: Push>, { /// Create a middleware that authorizes with the configured subject. pub fn new>(inner: T, subject: U) -> AllowAllAuthenticator { @@ -138,11 +138,11 @@ where } } -impl hyper::server::NewService for AllowAllAuthenticator +impl hyper::server::NewService for AllowAllAuthenticator where C: Pop>, - C::Result : Push>, - T: hyper::server::NewService>>::Result), Response=Response, Error=Error>, + C::Result : Push, Result=D>, + T: hyper::server::NewService, { type Request = (Request, C); @@ -155,11 +155,11 @@ impl hyper::server::NewService for AllowAllAuthenticator } } -impl hyper::server::Service for AllowAllAuthenticator +impl hyper::server::Service for AllowAllAuthenticator where C: Pop>, - C::Result : Push>, - T: hyper::server::Service>>::Result), Response=Response, Error=Error>, + C::Result : Push, Result=D>, + T: hyper::server::Service, { type Request = (Request, C); type Response = Response; diff --git a/src/context.rs b/src/context.rs index 950b481e01..b83da881f7 100644 --- a/src/context.rs +++ b/src/context.rs @@ -174,7 +174,11 @@ pub trait Push { /// type BadContext = MyContext>; /// /// fn main() { -/// let context : ExampleContext = MyEmpContext::default().push(MyType3{}).push(MyType2{}).push(MyType1{}); +/// let context : ExampleContext = +/// MyEmpContext::default() +/// .push(MyType3{}) +/// .push(MyType2{}) +/// .push(MyType1{}); /// /// use_has_my_type_1(&context); /// use_has_my_type_2(&context); @@ -206,6 +210,7 @@ macro_rules! new_context_type { tail: C, } + /// Unit struct representing a context with no data in it. #[derive(Debug, Clone, Default)] pub struct $empty_context_name; @@ -247,11 +252,22 @@ macro_rules! new_context_type { new_context_type!(impl extend_has $context_name, $empty_context_name, $($types),+); }; (impl extend_has $context_name:ident, $empty_context_name:ident, $head:ty, $($tail:ty),+ ) => { - new_context_type!(impl extend_has_helper $context_name, $empty_context_name, $head, $($tail),+); + new_context_type!( + impl extend_has_helper + $context_name, + $empty_context_name, + $head, + $($tail),+ + ); new_context_type!(impl extend_has $context_name, $empty_context_name, $($tail),+); }; (impl extend_has $context_name:ident, $empty_context_name:ident, $head:ty) => {}; - (impl extend_has_helper $context_name:ident , $empty_context_name:ident, $type:ty, $($types:ty),+ ) => { + (impl extend_has_helper + $context_name:ident, + $empty_context_name:ident, + $type:ty, + $($types:ty),+ + ) => { $( impl> $crate::Has<$type> for $context_name<$types, C> { fn set(&mut self, item: $type) { @@ -285,7 +301,7 @@ macro_rules! new_context_type { type Result = $context_name<$types, C::Result>; fn pop(self) -> ($type, Self::Result) { let (value, tail) = self.tail.pop(); - (value, $context_name{ head: self.head, tail: tail}) + (value, $context_name{ head: self.head, tail}) } } @@ -293,7 +309,7 @@ macro_rules! new_context_type { type Result = $context_name<$type, C::Result>; fn pop(self) -> ($types, Self::Result) { let (value, tail) = self.tail.pop(); - (value, $context_name{ head: self.head, tail: tail}) + (value, $context_name{ head: self.head, tail}) } } )+ @@ -433,7 +449,7 @@ mod context_tests { struct MiddleService where C: Pop, - C::Result : Push, + C::Result: Push, T: Service>::Result)>, { inner: T, @@ -461,7 +477,7 @@ mod context_tests { struct MiddleNewService where C: Pop, - C::Result : Push, + C::Result: Push, T: NewService>::Result)>, { inner: T, @@ -573,8 +589,9 @@ mod context_tests { #[test] fn send_request() { - let new_service = - OuterNewService::<_, MyEmptyContext>::new(MiddleNewService::new(InnerNewService::new())); + let new_service = OuterNewService::<_, MyEmptyContext>::new( + MiddleNewService::new(InnerNewService::new()), + ); let req = Request::new(Method::Post, Uri::from_str("127.0.0.1:80").unwrap()); new_service From be968814feb3989b7351884036d47ce2cd969f74 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Thu, 12 Apr 2018 14:03:39 +0100 Subject: [PATCH 48/98] updated docs and examples --- src/auth.rs | 8 +-- src/context.rs | 176 +++++++++++++++++++++++++++++++++---------------- src/lib.rs | 2 +- 3 files changed, 125 insertions(+), 61 deletions(-) diff --git a/src/auth.rs b/src/auth.rs index d006598a58..829b01fb2e 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -61,7 +61,7 @@ where C: Default + Push, { inner: T, - marker1: PhantomData, + marker: PhantomData, } impl NoAuthentication @@ -72,7 +72,7 @@ where pub fn new(inner: T) -> Self { NoAuthentication { inner, - marker1: PhantomData, + marker: PhantomData, } } } @@ -120,7 +120,7 @@ where { inner: T, subject: String, - marker1: PhantomData, + marker: PhantomData, } impl AllowAllAuthenticator @@ -133,7 +133,7 @@ where AllowAllAuthenticator { inner, subject: subject.into(), - marker1: PhantomData, + marker: PhantomData, } } } diff --git a/src/context.rs b/src/context.rs index b83da881f7..835da0c124 100644 --- a/src/context.rs +++ b/src/context.rs @@ -3,6 +3,8 @@ //! This module defines traits and structs that can be used to manage //! contextual data related to a request, as it is passed through a series of //! hyper services. +//! +//! See the contexts_tests module below for examples of how to use. use auth::{Authorization, AuthData}; use std::marker::Sized; @@ -46,7 +48,7 @@ use super::XSpanIdString; pub trait Has { /// Get an immutable reference to the value. fn get(&self) -> &T; - /// Split into a the value and the remainder. + /// get an mutable reference to the value. fn get_mut(&mut self) -> &mut T; /// Set the value. fn set(&mut self, value: T); @@ -65,26 +67,33 @@ pub trait Has { /// # use futures::future::{Future, ok}; /// # use std::marker::PhantomData; /// # -/// # struct MyItem; -/// # fn do_something_with_my_item(item: &MyItem) {} -/// # +/// struct MyItem1; +/// struct MyItem2; +/// struct MyItem3; +/// /// struct MiddlewareService { /// inner: T, /// marker: PhantomData, /// } /// -/// impl hyper::server::Service for MiddlewareService +/// impl hyper::server::Service for MiddlewareService /// where -/// C: Pop, -/// T: hyper::server::Service +/// C: Pop, +/// D: Pop, +/// E: Pop, +/// T: hyper::server::Service /// { /// type Request = (hyper::Request, C); /// type Response = T::Response; /// type Error = T::Error; /// type Future = T::Future; /// fn call(&self, (req, context) : Self::Request) -> Self::Future { -/// let (item, context) = context.pop(); -/// do_something_with_my_item(&item); +/// +/// // type annotations optional, included for illustrative purposes +/// let (_, context): (MyItem1, D) = context.pop(); +/// let (_, context): (MyItem2, E) = context.pop(); +/// let (_, context): (MyItem3, E::Result) = context.pop(); +/// /// self.inner.call((req, context)) /// } /// } @@ -110,24 +119,31 @@ pub trait Pop { /// # use futures::future::{Future, ok}; /// # use std::marker::PhantomData; /// # -/// # struct MyItem; -/// # +/// struct MyItem1; +/// struct MyItem2; +/// struct MyItem3; +/// /// struct MiddlewareService { /// inner: T, /// marker: PhantomData, /// } /// -/// impl hyper::server::Service for MiddlewareService +/// impl hyper::server::Service for MiddlewareService /// where -/// C: Push, -/// T: hyper::server::Service +/// C: Push, +/// D: Push, +/// E: Push, +/// T: hyper::server::Service /// { /// type Request = (hyper::Request, C); /// type Response = T::Response; /// type Error = T::Error; /// type Future = T::Future; /// fn call(&self, (req, context) : Self::Request) -> Self::Future { -/// let context = context.push(MyItem{}); +/// let context = context +/// .push(MyItem1{}) +/// .push(MyItem2{}) +/// .push(MyItem3{}); /// self.inner.call((req, context)) /// } /// } @@ -147,11 +163,16 @@ pub trait Push { /// the empty context struct, and subsequent arguments are the types /// that can be stored in contexts built using these struct. /// -/// A cons list built using the generated context type will implement Has +/// A cons list built using the generated context type will implement Has and Pop /// for each type T that appears in the list, provided that the list only /// contains the types that were passed to the macro invocation after the context /// type name. /// +/// All list types constructed using the generated types will implement `Push` +/// for all `T`, but it should ony be used when `T` is one of the types passed +/// to the macro invocation, otherwise it might not be possible to retrieve the +/// inserted value. +/// /// E.g. /// /// ```rust @@ -170,33 +191,35 @@ pub trait Push { /// fn use_has_my_type_3> (_: &T) {} /// fn use_has_my_type_4> (_: &T) {} /// -/// type ExampleContext = MyContext>>; +/// // will implement `Has` and `Has` because these appear +/// // in the type, and were passed to `new_context_type!`. Will not implement +/// // `Has` even though it was passed to `new_context_type!`, because +/// // it is not included in the type. +/// type ExampleContext = MyContext>; +/// +/// // Will not implement `Has` even though it appears in the type, +/// // because `MyType4` was not passed to `new_context_type!`. /// type BadContext = MyContext>; /// /// fn main() { /// let context : ExampleContext = /// MyEmpContext::default() -/// .push(MyType3{}) /// .push(MyType2{}) /// .push(MyType1{}); /// /// use_has_my_type_1(&context); /// use_has_my_type_2(&context); -/// use_has_my_type_3(&context); +/// // use_has_my_type3(&context); // will fail /// -/// let bad_context: BadContext = MyEmpContext::default().push(MyType4{}).push(MyType1{}); -/// // will not work -/// // use_has_my_type_4(&bad_context); +/// let bad_context: BadContext = +/// MyEmpContext::default() +/// .push(MyType4{}) +/// .push(MyType1{}); +/// // use_has_my_type_4(&bad_context); // will fail /// /// } /// ``` /// -/// will define a new struct `MyContext`, which implements: -/// - `Has`, -/// - `ExtendsWith`, -/// - `Has` whenever `S` is one of `MyType1`, `MyType2` or `MyType3`, AND -/// `C` implements `Has`. -/// /// See the `context_tests` module for more usage examples. #[macro_export] macro_rules! new_context_type { @@ -317,7 +340,7 @@ macro_rules! new_context_type { } /// Create a default context type to export. -new_context_type!(Context, EmpContext, XSpanIdString, Option, Option); +new_context_type!(Context, EmptyContext, XSpanIdString, Option, Option); /// Macro for easily defining context types. The first argument should be a /// context type created with `new_context_type!` and subsequent arguments are the @@ -392,41 +415,53 @@ mod context_tests { struct ContextItem1; struct ContextItem2; + struct ContextItem3; - fn do_something_with_item_1(_: &ContextItem1) {} - fn do_something_with_item_2(_: &ContextItem2) {} + fn use_item_1_owned(_: ContextItem1) {} + fn use_item_2(_: &ContextItem2) {} + fn use_item_3_owned(_: ContextItem3) {} + // Example of a "terminating" hyper service using contexts - i.e. doesn't + // pass a request and its context on a wrapped service. struct InnerService where - C: Has, + C: Has + Pop, { marker: PhantomData, } impl Service for InnerService where - C: Has, + // include a trait bounds like this for each type you want to use from + // the context. Use `Pop` when you need to take ownership of the value, + // or `Has` if a reference is enough. + C: Has + Pop, { type Request = (Request, C); type Response = Response; type Error = Error; type Future = Box>; fn call(&self, (_, context): Self::Request) -> Self::Future { - do_something_with_item_2(Has::::get(&context)); + + use_item_2(Has::::get(&context)); + + let (item3, _) : (ContextItem3, _) = context.pop(); + use_item_3_owned(item3); + Box::new(ok(Response::new())) } } struct InnerNewService where - C: Has, + C: Has + Pop, { marker: PhantomData, } impl InnerNewService where - C: Has, + C: Has + Pop, { fn new() -> Self { InnerNewService { marker: PhantomData } @@ -435,7 +470,7 @@ mod context_tests { impl NewService for InnerNewService where - C: Has, + C: Has + Pop, { type Request = (Request, C); type Response = Response; @@ -446,21 +481,31 @@ mod context_tests { } } + // Example of a middleware service using contexts, i.e. a hyper service that + // processes a request (and its context) and passes it on to another wrapped + // service. struct MiddleService where C: Pop, C::Result: Push, - T: Service>::Result)>, + >::Result: Push, + T: Service>::Result as Push>::Result)>, { inner: T, marker1: PhantomData, } - impl Service for MiddleService + impl Service for MiddleService where - C: Pop, - C::Result : Push, - T: Service>::Result)>, + // Use trait bounds like this to indicate how the context will be modified + // in sequence. Use `Pop` to remove an item from the context (making it + // unavailable to subsequent layers) and push to add items. Use `Has` to + // use a reference to an item in the context or modify it without removing + // that type from the context. + C: Pop, + D: Push, + E: Push, + T: Service, { type Request = (Request, C); type Response = T::Response; @@ -468,8 +513,11 @@ mod context_tests { type Future = T::Future; fn call(&self, (req, context): Self::Request) -> Self::Future { let (item, context) = context.pop(); - do_something_with_item_1(&item); - let context = context.push(ContextItem2 {}); + use_item_1_owned(item); + let context = + context + .push(ContextItem2 {}) + .push(ContextItem3 {}); self.inner.call((req, context)) } } @@ -478,17 +526,19 @@ mod context_tests { where C: Pop, C::Result: Push, - T: NewService>::Result)>, + >::Result: Push, + T: NewService>::Result as Push>::Result)>, { inner: T, marker1: PhantomData, } - impl NewService for MiddleNewService + impl NewService for MiddleNewService where - C: Pop, - C::Result : Push, - T: NewService>::Result)>, + C: Pop, + D: Push, + E: Push, + T: NewService, { type Request = (Request, C); type Response = T::Response; @@ -504,11 +554,12 @@ mod context_tests { } } - impl MiddleNewService + impl MiddleNewService where - C: Pop, - C::Result : Push, - T: NewService>::Result)>, + C: Pop, + D: Push, + E: Push, + T: NewService, { fn new(inner: T) -> Self { MiddleNewService { @@ -518,8 +569,12 @@ mod context_tests { } } + // Example of a top layer service that creates a context to be used by + // lower layers. struct OuterService where + // Use a Default trait bound so that the context can be created by your + // service. User `Push` bounds for each type you will add to the context. C: Default + Push, T: Service, { @@ -583,14 +638,23 @@ mod context_tests { } } - new_context_type!(MyContext, MyEmptyContext, ContextItem1, ContextItem2); - + // Example of use by a service in its main.rs file. At this point you know + // all the hyper service layers you will be using, and what requirements + // their contexts types have. Use the `new_context_type!` macro to create + // a context type and empty context type that are capable of containing all the + // types that your hyper services require. + new_context_type!(MyContext, MyEmptyContext, ContextItem1, ContextItem2, ContextItem3); #[test] fn send_request() { + // annotate the outermost service to indicate that the context type it + // uses is the empty context type created by the above macro invocation. + // the compiler should infer all the other context types. let new_service = OuterNewService::<_, MyEmptyContext>::new( - MiddleNewService::new(InnerNewService::new()), + MiddleNewService::new( + InnerNewService::new() + ), ); let req = Request::new(Method::Post, Uri::from_str("127.0.0.1:80").unwrap()); diff --git a/src/lib.rs b/src/lib.rs index eb6f442895..70709273dc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,7 +34,7 @@ pub mod auth; pub use auth::{Authorization, AuthData}; pub mod context; -pub use context::{Context, EmpContext, ContextWrapper, Has, Pop, Push}; +pub use context::{Context, EmptyContext, ContextWrapper, Has, Pop, Push}; /// Module with utilities for creating connectors with hyper. pub mod connector; From 030958c4685f44c0ce6e079d41a0d143e2ec7735 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Thu, 12 Apr 2018 15:12:05 +0100 Subject: [PATCH 49/98] rename NoAuthentication to MiddlewareWrapper and move it to its own submodule --- CHANGELOG.md | 13 ++++++----- src/auth.rs | 59 +------------------------------------------------- src/context.rs | 45 +++++++++++++++----------------------- src/lib.rs | 3 +++ 4 files changed, 30 insertions(+), 90 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25cf59d929..8144ec7dbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,16 +11,19 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [0.11.0] -2018-04-11 ### Added --- `Has`, `Pop` and `Push` traits for specifying requirements on context types in hyper services, and providing methods for manipulating them --- `new_context_type!` macro for defining structs that can be used to build concrete context types that implement `Has`, `Pop` and `Push` --- `make_context!` and `make_context_ty!` for conveniently creating contexts at value and type level +- `Has`, `Pop` and `Push` traits for specifying requirements on context types in hyper services, and providing methods for manipulating them +- `new_context_type!` macro for defining structs that can be used to build concrete context types that implement `Has`, `Pop` and `Push` +- `make_context!` and `make_context_ty!` for conveniently creating contexts at value and type level ### Removed --- Old `Context` struct +- Old `Context` struct + +### Changed +- Renamed `NoAuthentication` to `MiddlewareWrapper` and moved it to its own module. ## [0.10.0] - 2018-03-16 ### Added --- Structs for combining multiple hyper services +- Structs for combining multiple hyper services ### Changed diff --git a/src/auth.rs b/src/auth.rs index 829b01fb2e..07ed061b75 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -5,7 +5,7 @@ use std::io; use std::marker::PhantomData; use hyper; use hyper::{Request, Response, Error}; -use super::{Pop, Push, XSpanIdString}; +use super::{Pop, Push}; /// Authorization scopes. #[derive(Clone, Debug, PartialEq)] @@ -53,63 +53,6 @@ pub enum AuthData { ApiKey(String), } -/// No Authenticator, that does not insert any authorization data, denying all -/// access to endpoints that require authentication. -#[derive(Debug)] -pub struct NoAuthentication -where - C: Default + Push, -{ - inner: T, - marker: PhantomData, -} - -impl NoAuthentication -where - C: Default + Push, -{ - /// Create a new NoAuthentication struct wrapping a value - pub fn new(inner: T) -> Self { - NoAuthentication { - inner, - marker: PhantomData, - } - } -} - -impl hyper::server::NewService for NoAuthentication - where - C: Default + Push, - T: hyper::server::NewService, - -{ - type Request = Request; - type Response = Response; - type Error = Error; - type Instance = NoAuthentication; - - fn new_service(&self) -> Result { - self.inner.new_service().map(NoAuthentication::new) - } -} - -impl hyper::server::Service for NoAuthentication - where - C: Default + Push, - T: hyper::server::Service, -{ - type Request = Request; - type Response = Response; - type Error = Error; - type Future = T::Future; - - fn call(&self, req: Self::Request) -> Self::Future { - let x_span_id = XSpanIdString::get_or_generate(&req); - let context = C::default().push(x_span_id); - self.inner.call((req, context)) - } -} - /// Dummy Authenticator, that blindly inserts authorization data, allowing all /// access to an endpoint with the specified subject. #[derive(Debug)] diff --git a/src/context.rs b/src/context.rs index 835da0c124..7ab27c99c9 100644 --- a/src/context.rs +++ b/src/context.rs @@ -4,7 +4,7 @@ //! contextual data related to a request, as it is passed through a series of //! hyper services. //! -//! See the contexts_tests module below for examples of how to use. +//! See the `context_tests` module below for examples of how to use. use auth::{Authorization, AuthData}; use std::marker::Sized; @@ -432,9 +432,6 @@ mod context_tests { impl Service for InnerService where - // include a trait bounds like this for each type you want to use from - // the context. Use `Pop` when you need to take ownership of the value, - // or `Has` if a reference is enough. C: Has + Pop, { type Request = (Request, C); @@ -445,7 +442,7 @@ mod context_tests { use_item_2(Has::::get(&context)); - let (item3, _) : (ContextItem3, _) = context.pop(); + let (item3, _): (ContextItem3, _) = context.pop(); use_item_3_owned(item3); Box::new(ok(Response::new())) @@ -489,7 +486,10 @@ mod context_tests { C: Pop, C::Result: Push, >::Result: Push, - T: Service>::Result as Push>::Result)>, + T: Service>::Result as Push>::Result + )>, { inner: T, marker1: PhantomData, @@ -497,13 +497,8 @@ mod context_tests { impl Service for MiddleService where - // Use trait bounds like this to indicate how the context will be modified - // in sequence. Use `Pop` to remove an item from the context (making it - // unavailable to subsequent layers) and push to add items. Use `Has` to - // use a reference to an item in the context or modify it without removing - // that type from the context. - C: Pop, - D: Push, + C: Pop, + D: Push, E: Push, T: Service, { @@ -514,10 +509,7 @@ mod context_tests { fn call(&self, (req, context): Self::Request) -> Self::Future { let (item, context) = context.pop(); use_item_1_owned(item); - let context = - context - .push(ContextItem2 {}) - .push(ContextItem3 {}); + let context = context.push(ContextItem2 {}).push(ContextItem3 {}); self.inner.call((req, context)) } } @@ -527,7 +519,10 @@ mod context_tests { C: Pop, C::Result: Push, >::Result: Push, - T: NewService>::Result as Push>::Result)>, + T: NewService>::Result as Push>::Result + )>, { inner: T, marker1: PhantomData, @@ -535,8 +530,8 @@ mod context_tests { impl NewService for MiddleNewService where - C: Pop, - D: Push, + C: Pop, + D: Push, E: Push, T: NewService, { @@ -556,8 +551,8 @@ mod context_tests { impl MiddleNewService where - C: Pop, - D: Push, + C: Pop, + D: Push, E: Push, T: NewService, { @@ -573,8 +568,6 @@ mod context_tests { // lower layers. struct OuterService where - // Use a Default trait bound so that the context can be created by your - // service. User `Push` bounds for each type you will add to the context. C: Default + Push, T: Service, { @@ -652,9 +645,7 @@ mod context_tests { // uses is the empty context type created by the above macro invocation. // the compiler should infer all the other context types. let new_service = OuterNewService::<_, MyEmptyContext>::new( - MiddleNewService::new( - InnerNewService::new() - ), + MiddleNewService::new(InnerNewService::new()), ); let req = Request::new(Method::Post, Uri::from_str("127.0.0.1:80").unwrap()); diff --git a/src/lib.rs b/src/lib.rs index 70709273dc..cd64189472 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,6 +43,9 @@ pub use connector::{http_connector, https_connector, https_mutual_connector}; pub mod composites; pub use composites::{GetPath, NotFound, CompositeNewService, CompositeService}; +pub mod middleware_wrapper; +pub use middleware_wrapper::MiddlewareWrapper; + header! { /// `X-Span-ID` header, used to track a request through a chain of microservices. (XSpanId, "X-Span-ID") => [String] From 258a24277d86123bf17a81d8415bf388953a14eb Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Thu, 12 Apr 2018 15:25:22 +0100 Subject: [PATCH 50/98] add the new middleware_wrapper.rs file --- src/middleware_wrapper.rs | 68 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/middleware_wrapper.rs diff --git a/src/middleware_wrapper.rs b/src/middleware_wrapper.rs new file mode 100644 index 0000000000..b115b5fec0 --- /dev/null +++ b/src/middleware_wrapper.rs @@ -0,0 +1,68 @@ +//! Hyper service that adds a context to an incoming request and passes it on +//! to a wrapped service. + + +use std::io; +use std::marker::PhantomData; + +use hyper; +use hyper::{Request, Response, Error}; +use super::{Push, XSpanIdString}; + +/// Middleware wrapper service, that should be used as the outermost layer in a +/// stack of hyper services. Adds a context to a plain `hyper::Request` that can be +/// used by subsequent layers in the stack. +#[derive(Debug)] +pub struct MiddlewareWrapper +where + C: Default + Push, +{ + inner: T, + marker: PhantomData, +} + +impl MiddlewareWrapper +where + C: Default + Push, +{ + /// Create a new MiddlewareWrapper struct wrapping a value + pub fn new(inner: T) -> Self { + MiddlewareWrapper { + inner, + marker: PhantomData, + } + } +} + +impl hyper::server::NewService for MiddlewareWrapper + where + C: Default + Push, + T: hyper::server::NewService, + +{ + type Request = Request; + type Response = Response; + type Error = Error; + type Instance = MiddlewareWrapper; + + fn new_service(&self) -> Result { + self.inner.new_service().map(MiddlewareWrapper::new) + } +} + +impl hyper::server::Service for MiddlewareWrapper + where + C: Default + Push, + T: hyper::server::Service, +{ + type Request = Request; + type Response = Response; + type Error = Error; + type Future = T::Future; + + fn call(&self, req: Self::Request) -> Self::Future { + let x_span_id = XSpanIdString::get_or_generate(&req); + let context = C::default().push(x_span_id); + self.inner.call((req, context)) + } +} From 484441e52e00f51fb2e233e09b79c581544eaddb Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Thu, 12 Apr 2018 17:17:03 +0100 Subject: [PATCH 51/98] add doctests for make_context and make_context_ty --- src/context.rs | 55 ++++++++++++++++++++++++++++++++++++--- src/middleware_wrapper.rs | 2 -- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/context.rs b/src/context.rs index 7ab27c99c9..9677c06d93 100644 --- a/src/context.rs +++ b/src/context.rs @@ -48,7 +48,7 @@ use super::XSpanIdString; pub trait Has { /// Get an immutable reference to the value. fn get(&self) -> &T; - /// get an mutable reference to the value. + /// Get a mutable reference to the value. fn get_mut(&mut self) -> &mut T; /// Set the value. fn set(&mut self, value: T); @@ -227,14 +227,14 @@ macro_rules! new_context_type { /// Wrapper type for building up contexts recursively, adding one item /// to the context at a time. - #[derive(Debug, Clone, Default)] + #[derive(Debug, Clone, Default, PartialEq, Eq)] pub struct $context_name { head: T, tail: C, } /// Unit struct representing a context with no data in it. - #[derive(Debug, Clone, Default)] + #[derive(Debug, Clone, Default, PartialEq, Eq)] pub struct $empty_context_name; impl $crate::Push for $empty_context_name { @@ -345,6 +345,28 @@ new_context_type!(Context, EmptyContext, XSpanIdString, Option, Option /// Macro for easily defining context types. The first argument should be a /// context type created with `new_context_type!` and subsequent arguments are the /// types to be stored in the context, with the outermost first. +/// +/// ```rust +/// # #[macro_use] extern crate swagger; +/// # use swagger::{Has, Pop, Push}; +/// +/// # struct Type1; +/// # struct Type2; +/// # struct Type3; +/// +/// # new_context_type!(MyContext, MyEmptyContext, Type1, Type2, Type3); +/// +/// the following two types are identical +/// type ExampleContext1 = make_context_ty!(MyContext, MyEmptyContext, Type1, Type2, Type3); +/// type ExampleContext2 = MyContext>>; +/// +/// /// e.g. this wouldn't compile if they were different types +/// fn do_nothing(input: ExampleContext1) -> ExampleContext2 { +/// input +/// } +/// +/// # fn main() {} +/// ``` #[macro_export] macro_rules! make_context_ty { ($context_name:ident, $empty_context_name:ident, $type:ty $(, $types:ty)* $(,)* ) => { @@ -358,6 +380,31 @@ macro_rules! make_context_ty { /// Macro for easily defining context values. The first argument should be a /// context type created with `new_context_type!` and subsequent arguments are the /// values to be stored in the context, with the outermost first. +/// +/// ```rust +/// # #[macro_use] extern crate swagger; +/// # use swagger::{Has, Pop, Push}; +/// +/// # #[derive(PartialEq, Eq, Debug)] +/// # struct Type1; +/// # #[derive(PartialEq, Eq, Debug)] +/// # struct Type2; +/// # #[derive(PartialEq, Eq, Debug)] +/// # struct Type3; +/// +/// # new_context_type!(MyContext, MyEmptyContext, Type1, Type2, Type3); +/// +/// fn main() { +/// // the following are equivalent +/// let context1 = make_context!(MyContext, MyEmptyContext, Type1 {}, Type2 {}, Type3 {}); +/// let context2 = MyEmptyContext::default() +/// .push(Type3{}) +/// .push(Type2{}) +/// .push(Type1{}); +/// +/// assert_eq!(context1, context2); +/// } +/// ``` #[macro_export] macro_rules! make_context { ($context_name:ident, $empty_context_name:ident, $value:expr $(, $values:expr)* $(,)*) => { @@ -422,7 +469,7 @@ mod context_tests { fn use_item_3_owned(_: ContextItem3) {} // Example of a "terminating" hyper service using contexts - i.e. doesn't - // pass a request and its context on a wrapped service. + // pass a request and its context on to a wrapped service. struct InnerService where C: Has + Pop, diff --git a/src/middleware_wrapper.rs b/src/middleware_wrapper.rs index b115b5fec0..e6ce444ae5 100644 --- a/src/middleware_wrapper.rs +++ b/src/middleware_wrapper.rs @@ -1,10 +1,8 @@ //! Hyper service that adds a context to an incoming request and passes it on //! to a wrapped service. - use std::io; use std::marker::PhantomData; - use hyper; use hyper::{Request, Response, Error}; use super::{Push, XSpanIdString}; From 53e94a123ddef18e693fc71ae42a6003c3d95c84 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Thu, 12 Apr 2018 17:24:14 +0100 Subject: [PATCH 52/98] add back the comments that were eaten by rustfmt --- src/context.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/context.rs b/src/context.rs index 9677c06d93..94b2268876 100644 --- a/src/context.rs +++ b/src/context.rs @@ -356,11 +356,11 @@ new_context_type!(Context, EmptyContext, XSpanIdString, Option, Option /// /// # new_context_type!(MyContext, MyEmptyContext, Type1, Type2, Type3); /// -/// the following two types are identical +/// // the following two types are identical /// type ExampleContext1 = make_context_ty!(MyContext, MyEmptyContext, Type1, Type2, Type3); /// type ExampleContext2 = MyContext>>; /// -/// /// e.g. this wouldn't compile if they were different types +/// // e.g. this wouldn't compile if they were different types /// fn do_nothing(input: ExampleContext1) -> ExampleContext2 { /// input /// } @@ -477,6 +477,9 @@ mod context_tests { marker: PhantomData, } + // Use trait bounds to indicate what your service will use from the context. + // use `Pop` if you want to take ownership of a value stored in the context, + // or `Has` if a reference is enough. impl Service for InnerService where C: Has + Pop, @@ -542,6 +545,8 @@ mod context_tests { marker1: PhantomData, } + // Use trait bounds to indicate what modifications your service will make + // to the context, chaining them as below. impl Service for MiddleService where C: Pop, @@ -622,6 +627,9 @@ mod context_tests { marker: PhantomData, } + // Use a `Default` trait bound so that the context can be created. Use + // `Push` trait bounds for each type that you will add to the newly + // created context. impl Service for OuterService where C: Default + Push, From 205336fe821f45b8fe85a705ccc5148776aa4075 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Fri, 13 Apr 2018 09:38:15 +0100 Subject: [PATCH 53/98] rename MiddlewareWrapper as AddContext --- src/lib.rs | 4 +-- src/middleware_wrapper.rs | 66 --------------------------------------- 2 files changed, 2 insertions(+), 68 deletions(-) delete mode 100644 src/middleware_wrapper.rs diff --git a/src/lib.rs b/src/lib.rs index cd64189472..e3a421404d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,8 +43,8 @@ pub use connector::{http_connector, https_connector, https_mutual_connector}; pub mod composites; pub use composites::{GetPath, NotFound, CompositeNewService, CompositeService}; -pub mod middleware_wrapper; -pub use middleware_wrapper::MiddlewareWrapper; +pub mod add_context; +pub use add_context::AddContext; header! { /// `X-Span-ID` header, used to track a request through a chain of microservices. diff --git a/src/middleware_wrapper.rs b/src/middleware_wrapper.rs deleted file mode 100644 index e6ce444ae5..0000000000 --- a/src/middleware_wrapper.rs +++ /dev/null @@ -1,66 +0,0 @@ -//! Hyper service that adds a context to an incoming request and passes it on -//! to a wrapped service. - -use std::io; -use std::marker::PhantomData; -use hyper; -use hyper::{Request, Response, Error}; -use super::{Push, XSpanIdString}; - -/// Middleware wrapper service, that should be used as the outermost layer in a -/// stack of hyper services. Adds a context to a plain `hyper::Request` that can be -/// used by subsequent layers in the stack. -#[derive(Debug)] -pub struct MiddlewareWrapper -where - C: Default + Push, -{ - inner: T, - marker: PhantomData, -} - -impl MiddlewareWrapper -where - C: Default + Push, -{ - /// Create a new MiddlewareWrapper struct wrapping a value - pub fn new(inner: T) -> Self { - MiddlewareWrapper { - inner, - marker: PhantomData, - } - } -} - -impl hyper::server::NewService for MiddlewareWrapper - where - C: Default + Push, - T: hyper::server::NewService, - -{ - type Request = Request; - type Response = Response; - type Error = Error; - type Instance = MiddlewareWrapper; - - fn new_service(&self) -> Result { - self.inner.new_service().map(MiddlewareWrapper::new) - } -} - -impl hyper::server::Service for MiddlewareWrapper - where - C: Default + Push, - T: hyper::server::Service, -{ - type Request = Request; - type Response = Response; - type Error = Error; - type Future = T::Future; - - fn call(&self, req: Self::Request) -> Self::Future { - let x_span_id = XSpanIdString::get_or_generate(&req); - let context = C::default().push(x_span_id); - self.inner.call((req, context)) - } -} From 35f2a6b74a8fe225381d85110ab83fbf54ceef2d Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Fri, 13 Apr 2018 09:54:05 +0100 Subject: [PATCH 54/98] add the remaned add_context.rs file --- src/add_context.rs | 71 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 src/add_context.rs diff --git a/src/add_context.rs b/src/add_context.rs new file mode 100644 index 0000000000..40b1014580 --- /dev/null +++ b/src/add_context.rs @@ -0,0 +1,71 @@ +//! Hyper service that adds a context to an incoming request and passes it on +//! to a wrapped service. + +use std::io; +use std::marker::PhantomData; +use hyper; +use hyper::{Request, Response, Error}; +use super::{Push, XSpanIdString}; + +/// Middleware wrapper service, that should be used as the outermost layer in a +/// stack of hyper services. Adds a context to a plain `hyper::Request` that can be +/// used by subsequent layers in the stack. +#[derive(Debug)] +pub struct AddContext +where + C: Default + Push, +{ + inner: T, + marker: PhantomData, +} + +impl AddContext +where + C: Default + Push, +{ + /// Create a new AddContext struct wrapping a value + pub fn new(inner: T) -> Self { + AddContext { + inner, + marker: PhantomData, + } + } +} + +impl hyper::server::NewService for AddContext + where + C: Default + Push, + T: hyper::server::NewService, + +{ + type Request = Request; + type Response = Response; + type Error = Error; + type Instance = AddContext; + + fn new_service(&self) -> Result { + self.inner.new_service().map(AddContext::new) + } +} + +impl hyper::server::Service for AddContext +where + C: Default + Push, + T: hyper::server::Service< + Request = (Request, + C::Result), + Response = Response, + Error = Error, + >, +{ + type Request = Request; + type Response = Response; + type Error = Error; + type Future = T::Future; + + fn call(&self, req: Self::Request) -> Self::Future { + let x_span_id = XSpanIdString::get_or_generate(&req); + let context = C::default().push(x_span_id); + self.inner.call((req, context)) + } +} From cac157218fefc0cc01b4068adaabfc8b6bb99349 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Tue, 17 Apr 2018 09:33:02 +0100 Subject: [PATCH 55/98] rename exported Context type to ContextBuilder --- src/context.rs | 7 ++++++- src/lib.rs | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/context.rs b/src/context.rs index 94b2268876..7fcf2fbc71 100644 --- a/src/context.rs +++ b/src/context.rs @@ -340,7 +340,12 @@ macro_rules! new_context_type { } /// Create a default context type to export. -new_context_type!(Context, EmptyContext, XSpanIdString, Option, Option); +new_context_type!(ContextBuilder, + EmptyContext, + XSpanIdString, + Option, + Option +); /// Macro for easily defining context types. The first argument should be a /// context type created with `new_context_type!` and subsequent arguments are the diff --git a/src/lib.rs b/src/lib.rs index e3a421404d..db6f1a2311 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,7 +34,7 @@ pub mod auth; pub use auth::{Authorization, AuthData}; pub mod context; -pub use context::{Context, EmptyContext, ContextWrapper, Has, Pop, Push}; +pub use context::{ContextBuilder, EmptyContext, ContextWrapper, Has, Pop, Push}; /// Module with utilities for creating connectors with hyper. pub mod connector; From 0d9a46ba92e36bc37d1c90fabf06a749916c8cc7 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Tue, 17 Apr 2018 12:06:06 +0100 Subject: [PATCH 56/98] added explanatory comments in the definition of new_context_type --- src/context.rs | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/context.rs b/src/context.rs index 7fcf2fbc71..cbb42a413b 100644 --- a/src/context.rs +++ b/src/context.rs @@ -233,10 +233,12 @@ macro_rules! new_context_type { tail: C, } - /// Unit struct representing a context with no data in it. + /// Unit struct representing an empty context with no data in it. #[derive(Debug, Clone, Default, PartialEq, Eq)] pub struct $empty_context_name; + // implement `Push` on the empty context type for any `T`, so that + // items can be added to the context impl $crate::Push for $empty_context_name { type Result = $context_name; fn push(self, item: U) -> Self::Result { @@ -244,6 +246,7 @@ macro_rules! new_context_type { } } + // implement `Has` for a list where `T` is the type of the head impl $crate::Has for $context_name { fn set(&mut self, item: T) { self.head = item; @@ -258,6 +261,7 @@ macro_rules! new_context_type { } } + // implement `Pop` for a list where `T` is the type of the head impl $crate::Pop for $context_name { type Result = C; fn pop(self) -> (T, Self::Result) { @@ -265,6 +269,7 @@ macro_rules! new_context_type { } } + // implement `Push` for non-empty lists, for all types `U` impl $crate::Push for $context_name { type Result = $context_name; fn push(self, item: U) -> Self::Result { @@ -272,9 +277,25 @@ macro_rules! new_context_type { } } + // Add implementations of `Has` and `Pop` when `T` is any type stored in + // the list, not just the head. new_context_type!(impl extend_has $context_name, $empty_context_name, $($types),+); }; + + // "HELPER" MACRO CASE - NOT FOR EXTERNAL USE + // takes a type `Type1` ($head) and a non-empty list of types `Types` ($tail). First calls + // another helper macro to define the following impls, for each `Type2` in `Types`: + // ``` + // impl Has for $context_name {...} + // impl Has for $context_name {...} + // impl Pop for $context_name {...} + // impl Pop for $context_name {...} + // ``` + // then calls itself again with the rest of the list. The end result is to define the above + // impls for all distinct pairs of types in the original list. (impl extend_has $context_name:ident, $empty_context_name:ident, $head:ty, $($tail:ty),+ ) => { + + // new_context_type!( impl extend_has_helper $context_name, @@ -284,7 +305,22 @@ macro_rules! new_context_type { ); new_context_type!(impl extend_has $context_name, $empty_context_name, $($tail),+); }; + + // "HELPER" MACRO CASE - NOT FOR EXTERNAL USE + // base case of the preceding helper macro - was passed an empty list of types, so + // we don't need to do anything. (impl extend_has $context_name:ident, $empty_context_name:ident, $head:ty) => {}; + + // "HELPER" MACRO CASE - NOT FOR EXTERNAL USE + // takes a type `Type1` ($type) and a non-empty list of types `Types` ($types). For + // each `Type2` in `Types`, defines the following impls: + // ``` + // impl Has for $context_name {...} + // impl Has for $context_name {...} + // impl Pop for $context_name {...} + // impl Pop for $context_name {...} + // ``` + // (impl extend_has_helper $context_name:ident, $empty_context_name:ident, From a35f1831cfd04a29f7296eb6eee9f2b7e0101767 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Wed, 18 Apr 2018 12:02:28 +0100 Subject: [PATCH 57/98] add constructor methods for AuthData --- src/auth.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/auth.rs b/src/auth.rs index 07ed061b75..c3c20f5ec8 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -53,6 +53,26 @@ pub enum AuthData { ApiKey(String), } +impl AuthData { + /// Set Basic authentication + pub fn basic(&mut self, username: &str, password: &str) -> Self { + AuthData::Basic(hyper::header::Basic { + username: username.to_owned(), + password: Some(password.to_owned()), + }) + } + + /// Set Bearer token authentication + pub fn bearer(&mut self, token: &str) -> Self { + AuthData::Bearer(hyper::header::Bearer { token: token.to_owned() }) + } + + /// Set ApiKey authentication + pub fn apikey(&mut self, apikey: &str) -> Self { + AuthData::ApiKey(apikey.to_owned()) + } +} + /// Dummy Authenticator, that blindly inserts authorization data, allowing all /// access to an endpoint with the specified subject. #[derive(Debug)] From b771447a8a1a985da7c3822ec2462de18793026b Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Wed, 18 Apr 2018 12:06:47 +0100 Subject: [PATCH 58/98] remove Pop> constraint from AllowAllAuthenticator --- src/auth.rs | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/auth.rs b/src/auth.rs index c3c20f5ec8..63eb62ae43 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -5,7 +5,7 @@ use std::io; use std::marker::PhantomData; use hyper; use hyper::{Request, Response, Error}; -use super::{Pop, Push}; +use super::Push; /// Authorization scopes. #[derive(Clone, Debug, PartialEq)] @@ -78,8 +78,7 @@ impl AuthData { #[derive(Debug)] pub struct AllowAllAuthenticator where - C: Pop>, - C::Result: Push>, + C: Push>, { inner: T, subject: String, @@ -88,8 +87,7 @@ where impl AllowAllAuthenticator where - C: Pop>, - C::Result: Push>, + C: Push>, { /// Create a middleware that authorizes with the configured subject. pub fn new>(inner: T, subject: U) -> AllowAllAuthenticator { @@ -101,11 +99,10 @@ where } } -impl hyper::server::NewService for AllowAllAuthenticator +impl hyper::server::NewService for AllowAllAuthenticator where - C: Pop>, - C::Result : Push, Result=D>, - T: hyper::server::NewService, + C: Push>, + T: hyper::server::NewService, { type Request = (Request, C); @@ -118,11 +115,10 @@ impl hyper::server::NewService for AllowAllAuthenticator } } -impl hyper::server::Service for AllowAllAuthenticator +impl hyper::server::Service for AllowAllAuthenticator where - C: Pop>, - C::Result : Push, Result=D>, - T: hyper::server::Service, + C : Push>, + T: hyper::server::Service, { type Request = (Request, C); type Response = Response; @@ -130,8 +126,6 @@ impl hyper::server::Service for AllowAllAuthenticator type Future = T::Future; fn call(&self, (req, context): Self::Request) -> Self::Future { - let (_auth_data, context) = context.pop(); - let context = context.push( Some(Authorization{ subject: self.subject.clone(), From a2d3726903bbfb6d78329792ad902ab4ad288ba8 Mon Sep 17 00:00:00 2001 From: Tom Avery Date: Wed, 18 Apr 2018 12:38:24 +0100 Subject: [PATCH 59/98] Fix AuthData constructors --- src/auth.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/auth.rs b/src/auth.rs index 63eb62ae43..99c11487ee 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -55,7 +55,7 @@ pub enum AuthData { impl AuthData { /// Set Basic authentication - pub fn basic(&mut self, username: &str, password: &str) -> Self { + pub fn basic(username: &str, password: &str) -> Self { AuthData::Basic(hyper::header::Basic { username: username.to_owned(), password: Some(password.to_owned()), @@ -63,12 +63,12 @@ impl AuthData { } /// Set Bearer token authentication - pub fn bearer(&mut self, token: &str) -> Self { + pub fn bearer(token: &str) -> Self { AuthData::Bearer(hyper::header::Bearer { token: token.to_owned() }) } /// Set ApiKey authentication - pub fn apikey(&mut self, apikey: &str) -> Self { + pub fn apikey(apikey: &str) -> Self { AuthData::ApiKey(apikey.to_owned()) } } From aa99a05c23f0039c8e86d3ebb113f198ff49a7d1 Mon Sep 17 00:00:00 2001 From: Thomas Whiteway Date: Wed, 25 Apr 2018 12:53:03 +0100 Subject: [PATCH 60/98] Add DropContext as inverse of AddContext --- src/drop_context.rs | 69 +++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 ++ 2 files changed, 72 insertions(+) create mode 100644 src/drop_context.rs diff --git a/src/drop_context.rs b/src/drop_context.rs new file mode 100644 index 0000000000..37bf708ae0 --- /dev/null +++ b/src/drop_context.rs @@ -0,0 +1,69 @@ +//! Hyper service that drops a context to an incoming request and passes it on +//! to a wrapped service. + +use std::io; +use std::marker::PhantomData; +use hyper; +use hyper::{Request, Response, Error}; +use super::{Push, XSpanIdString}; + +/// Middleware wrapper service, that can be used to include services that take a plain +/// `hyper::Request` in a `CompositeService` wrapped in an `AddContext` service. +/// Drops the context from the incoming request and passes the plain `hyper::Request` +/// to the wrapped service. +#[derive(Debug)] +pub struct DropContext +where + C: Default + Push, +{ + inner: T, + marker: PhantomData, +} + +impl DropContext +where + C: Default + Push, +{ + /// Create a new DropContext struct wrapping a value + pub fn new(inner: T) -> Self { + DropContext { + inner, + marker: PhantomData, + } + } +} + +impl hyper::server::NewService for DropContext + where + C: Default + Push, + T: hyper::server::NewService, + +{ + type Request = (Request, C::Result); + type Response = Response; + type Error = Error; + type Instance = DropContext; + + fn new_service(&self) -> Result { + self.inner.new_service().map(DropContext::new) + } +} + +impl hyper::server::Service for DropContext +where + C: Default + Push, + T: hyper::server::Service< + Request = Request, + Response = Response, + Error = Error, + >, +{ + type Request = (Request, C::Result); + type Response = Response; + type Error = Error; + type Future = T::Future; + + fn call(&self, (req, _): Self::Request) -> Self::Future { + self.inner.call(req) + } +} diff --git a/src/lib.rs b/src/lib.rs index db6f1a2311..faa81da3fc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,6 +46,9 @@ pub use composites::{GetPath, NotFound, CompositeNewService, CompositeService}; pub mod add_context; pub use add_context::AddContext; +pub mod drop_context; +pub use drop_context::DropContext; + header! { /// `X-Span-ID` header, used to track a request through a chain of microservices. (XSpanId, "X-Span-ID") => [String] From 49998f93a322e25ab58c96593fc228601c307f49 Mon Sep 17 00:00:00 2001 From: Thomas Whiteway Date: Thu, 26 Apr 2018 09:42:52 +0100 Subject: [PATCH 61/98] Add example for DropContext and fix up formatting for example for CompositeNewService --- src/composites.rs | 4 +++- src/drop_context.rs | 28 ++++++++++++++++++++++++---- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/composites.rs b/src/composites.rs index 4bea190770..c6ef65b7fb 100644 --- a/src/composites.rs +++ b/src/composites.rs @@ -86,7 +86,9 @@ where /// request to the first `Service` in the list for which the associated /// base path is a prefix of the request path. /// -/// Usage: +/// Example Usage +/// ============= +/// /// ```ignore /// let my_new_service1 = NewService1::new(); /// let my_new_service2 = NewService2::new(); diff --git a/src/drop_context.rs b/src/drop_context.rs index 37bf708ae0..59657bb487 100644 --- a/src/drop_context.rs +++ b/src/drop_context.rs @@ -7,10 +7,30 @@ use hyper; use hyper::{Request, Response, Error}; use super::{Push, XSpanIdString}; -/// Middleware wrapper service, that can be used to include services that take a plain -/// `hyper::Request` in a `CompositeService` wrapped in an `AddContext` service. -/// Drops the context from the incoming request and passes the plain `hyper::Request` -/// to the wrapped service. +/// Middleware wrapper service that trops the context from the incoming request +/// and passes the plain `hyper::Request` to the wrapped service. +/// +/// This service can be used to to include services that take a plain `hyper::Request` +/// in a `CompositeService` wrapped in an `AddContext` service. +/// +/// Example Usage +/// ============= +/// +/// In the following example `SwaggerService` implements `hyper::server::NewService` +/// with `Request = (hyper::Request, SomeContext)`, and `PlainService` implements it +/// with `Request = hyper::Request` +/// +/// ```ignore +/// let swagger_service_one = SwaggerService::new(); +/// let swagger_service_two = SwaggerService::new(); +/// let plain_service = PlainService::new(); +/// +/// let mut composite_new_service = CompositeNewService::new(); +/// composite_new_service.push(("/base/path/1", swagger_service_one)); +/// composite_new_service.push(("/base/path/2", swagger_service_two)); +/// composite_new_service.push(("/base/path/3", DropContext::new(plain_service))); +/// ``` + #[derive(Debug)] pub struct DropContext where From 38c63c6c6d59326719f982bfb46499e7ef965af0 Mon Sep 17 00:00:00 2001 From: Thomas Whiteway Date: Thu, 26 Apr 2018 10:37:19 +0100 Subject: [PATCH 62/98] Remove unnecessary blank line --- src/drop_context.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/drop_context.rs b/src/drop_context.rs index 59657bb487..7217c6400c 100644 --- a/src/drop_context.rs +++ b/src/drop_context.rs @@ -30,7 +30,6 @@ use super::{Push, XSpanIdString}; /// composite_new_service.push(("/base/path/2", swagger_service_two)); /// composite_new_service.push(("/base/path/3", DropContext::new(plain_service))); /// ``` - #[derive(Debug)] pub struct DropContext where From 14638c01a756f1355517bf3ce259fe5d29987639 Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Thu, 26 Apr 2018 11:34:55 +0100 Subject: [PATCH 63/98] Bump version to 0.12.0 --- CHANGELOG.md | 11 +++++++++-- Cargo.toml | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8144ec7dbf..a627044795 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed -## [0.11.0] -2018-04-11 +### Removed + +## [0.11.0] - 2018-04-26 +### Added +- `DropContext` to pass a raw (context-less) `hyper::Request` to a service. + +## [0.11.0] - 2018-04-11 ### Added - `Has`, `Pop` and `Push` traits for specifying requirements on context types in hyper services, and providing methods for manipulating them - `new_context_type!` macro for defining structs that can be used to build concrete context types that implement `Has`, `Pop` and `Push` @@ -57,7 +63,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [0.5.0] - 2017-09-18 - Start of changelog. -[Unreleased]: https://github.com/Metaswitch/swagger-rs/compare/0.11.0...HEAD +[Unreleased]: https://github.com/Metaswitch/swagger-rs/compare/0.12.0...HEAD +[0.12.0]: https://github.com/Metaswitch/swagger-rs/compare/0.11.0...0.12.0 [0.11.0]: https://github.com/Metaswitch/swagger-rs/compare/0.10.0...0.11.0 [0.10.0]: https://github.com/Metaswitch/swagger-rs/compare/0.9.0...0.10.0 [0.9.0]: https://github.com/Metaswitch/swagger-rs/compare/0.8.1...0.9.0 diff --git a/Cargo.toml b/Cargo.toml index 8223873694..ec86accf30 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "swagger" -version = "0.11.0" +version = "0.12.0" authors = ["Metaswitch Networks Ltd"] license = "Apache-2.0" description = "A set of common utilities for Rust code generated by swagger-codegen" From 3ecdd2e1e774d3e59a22a00fb9d0a7a81afb69c7 Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Thu, 26 Apr 2018 11:47:41 +0100 Subject: [PATCH 64/98] Correct changelog version --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a627044795..0c56a36318 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Removed -## [0.11.0] - 2018-04-26 +## [0.12.0] - 2018-04-26 ### Added - `DropContext` to pass a raw (context-less) `hyper::Request` to a service. From 8565a2367ffa25947f3a70458caecc8d3289bed1 Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Thu, 26 Apr 2018 13:20:00 +0100 Subject: [PATCH 65/98] Add contribution guidelines --- CONTRIBUTING.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..f7529b314d --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,15 @@ +# Contributing to `swagger-rs` + +Thanks for your interest - we gratefully welcome contributions. + +Questions can be asked in [issues](https://github.com/Metaswitch/swagger-rs/issues). + +To help us help you get pull requests merged quickly and smoothly, open an issue before submitted large changes. Please keep the contents of pull requests and commits short. Commit messages should include the intent of the commit. Pull requests should add an entry to [CHANGELOG.md]. + +Contributions that add/improve tests are awesome. Please add tests for every change. + +`swagger-rs` uses [`rustfmt-nightly`](https://github.com/rust-lang-nursery/rustfmt) for formatting and [`clippy`](https://github.com/rust-lang-nursery/rust-clippy) for linting. + +## Conduct + +In all `swagger-rs`-related forums, we follow the [Swagger Codegen Code of Conduct](https://github.com/swagger-api/swagger-codegen/blob/master/CODE_OF_CONDUCT.md). For escalation or moderation issues please contact Benjamin (mailto:benjamin.gill@metaswitch.com) instead of the swagger-api moderation team. From 0d6b3f165d52ba7d052910d09c87874482006dc9 Mon Sep 17 00:00:00 2001 From: Mark Thebridge Date: Thu, 26 Apr 2018 16:10:21 +0100 Subject: [PATCH 66/98] Add RequestParser trait to allow retrieving swagger information from other middlewares --- src/lib.rs | 9 ++++++--- src/request_parser.rs | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 src/request_parser.rs diff --git a/src/lib.rs b/src/lib.rs index faa81da3fc..ff139ace78 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,17 +31,17 @@ pub mod nullable_format; pub use nullable_format::Nullable; pub mod auth; -pub use auth::{Authorization, AuthData}; +pub use auth::{AuthData, Authorization}; pub mod context; -pub use context::{ContextBuilder, EmptyContext, ContextWrapper, Has, Pop, Push}; +pub use context::{ContextBuilder, ContextWrapper, EmptyContext, Has, Pop, Push}; /// Module with utilities for creating connectors with hyper. pub mod connector; pub use connector::{http_connector, https_connector, https_mutual_connector}; pub mod composites; -pub use composites::{GetPath, NotFound, CompositeNewService, CompositeService}; +pub use composites::{CompositeNewService, CompositeService, GetPath, NotFound}; pub mod add_context; pub use add_context::AddContext; @@ -49,6 +49,9 @@ pub use add_context::AddContext; pub mod drop_context; pub use drop_context::DropContext; +pub mod request_parser; +pub use request_parser::RequestParser; + header! { /// `X-Span-ID` header, used to track a request through a chain of microservices. (XSpanId, "X-Span-ID") => [String] diff --git a/src/request_parser.rs b/src/request_parser.rs new file mode 100644 index 0000000000..e2deda80a6 --- /dev/null +++ b/src/request_parser.rs @@ -0,0 +1,16 @@ +//! Methods for retrieving swagger-related information from an HTTP request. +use hyper::Request; + +/// A trait for retrieving swagger-related information from a request. +/// +/// This allows other middlewares to retrieve API-related information from a request that +/// may not have been handled by the autogenerated API code yet. For example, a statistics +/// tracking service may wish to use this to count requests per-operation. +/// +/// The trait is automatically implemented by swagger-codegen. +pub trait RequestParser { + /// Retrieve the Swagger operation identifier that matches this request. + /// + /// Returns `Err(())` if this request does not match any known operation on this API. + fn get_operation(req: &Request) -> Result<&'static str, ()>; +} From 226c3048a608cd4c47bac97bcb8d63219b53721a Mon Sep 17 00:00:00 2001 From: Nigel Thorpe Date: Thu, 26 Apr 2018 17:53:07 +0100 Subject: [PATCH 67/98] Remove unnecessary type bounds from DropContext --- src/drop_context.rs | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/src/drop_context.rs b/src/drop_context.rs index 7217c6400c..c93829a588 100644 --- a/src/drop_context.rs +++ b/src/drop_context.rs @@ -5,7 +5,6 @@ use std::io; use std::marker::PhantomData; use hyper; use hyper::{Request, Response, Error}; -use super::{Push, XSpanIdString}; /// Middleware wrapper service that trops the context from the incoming request /// and passes the plain `hyper::Request` to the wrapped service. @@ -31,18 +30,12 @@ use super::{Push, XSpanIdString}; /// composite_new_service.push(("/base/path/3", DropContext::new(plain_service))); /// ``` #[derive(Debug)] -pub struct DropContext -where - C: Default + Push, -{ +pub struct DropContext { inner: T, marker: PhantomData, } -impl DropContext -where - C: Default + Push, -{ +impl DropContext { /// Create a new DropContext struct wrapping a value pub fn new(inner: T) -> Self { DropContext { @@ -54,11 +47,10 @@ where impl hyper::server::NewService for DropContext where - C: Default + Push, T: hyper::server::NewService, { - type Request = (Request, C::Result); + type Request = (Request, C); type Response = Response; type Error = Error; type Instance = DropContext; @@ -70,14 +62,13 @@ impl hyper::server::NewService for DropContext impl hyper::server::Service for DropContext where - C: Default + Push, T: hyper::server::Service< Request = Request, Response = Response, Error = Error, >, { - type Request = (Request, C::Result); + type Request = (Request, C); type Response = Response; type Error = Error; type Future = T::Future; From 9a681c4d483caa0cb02c74d48d6c9cfe3550acd7 Mon Sep 17 00:00:00 2001 From: Mark Thebridge Date: Fri, 27 Apr 2018 09:52:38 +0100 Subject: [PATCH 68/98] Minor changes after review --- CHANGELOG.md | 1 + src/request_parser.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c56a36318..c47bf2b71e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] ### Added +- `RequestParser` trait for retrieving Swagger related info in middlewares. ### Changed diff --git a/src/request_parser.rs b/src/request_parser.rs index e2deda80a6..e2ce2d6502 100644 --- a/src/request_parser.rs +++ b/src/request_parser.rs @@ -12,5 +12,5 @@ pub trait RequestParser { /// Retrieve the Swagger operation identifier that matches this request. /// /// Returns `Err(())` if this request does not match any known operation on this API. - fn get_operation(req: &Request) -> Result<&'static str, ()>; + fn get_operation_id(req: &Request) -> Result<&'static str, ()>; } From 70380b02c76f6ac3feb32b3abbe17a48e77c4b68 Mon Sep 17 00:00:00 2001 From: Nigel Thorpe Date: Fri, 27 Apr 2018 09:56:12 +0100 Subject: [PATCH 69/98] Add CHANGELOG entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c56a36318..171e3e6f40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added ### Changed +- Fixed `DropContext` to remove trait bounds on the type of context it can drop ### Removed From 36768777a19b42e7d55d761a332979483e9f2984 Mon Sep 17 00:00:00 2001 From: Mark Thebridge Date: Fri, 27 Apr 2018 09:59:03 +0100 Subject: [PATCH 70/98] Make function name more idiomatic --- src/request_parser.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/request_parser.rs b/src/request_parser.rs index e2ce2d6502..219c5163ca 100644 --- a/src/request_parser.rs +++ b/src/request_parser.rs @@ -12,5 +12,5 @@ pub trait RequestParser { /// Retrieve the Swagger operation identifier that matches this request. /// /// Returns `Err(())` if this request does not match any known operation on this API. - fn get_operation_id(req: &Request) -> Result<&'static str, ()>; + fn operation_id(req: &Request) -> Result<&'static str, ()>; } From c0da6347ce19ae01c3b7fe38ac9b6302864bcae7 Mon Sep 17 00:00:00 2001 From: Mark Thebridge Date: Fri, 27 Apr 2018 10:06:21 +0100 Subject: [PATCH 71/98] Change function name to final agreed version --- src/request_parser.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/request_parser.rs b/src/request_parser.rs index 219c5163ca..5454742b0a 100644 --- a/src/request_parser.rs +++ b/src/request_parser.rs @@ -12,5 +12,5 @@ pub trait RequestParser { /// Retrieve the Swagger operation identifier that matches this request. /// /// Returns `Err(())` if this request does not match any known operation on this API. - fn operation_id(req: &Request) -> Result<&'static str, ()>; + fn parse_operation_id(req: &Request) -> Result<&'static str, ()>; } From bfd425bc80d321f1e03a44026d569709c7a3875c Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Fri, 27 Apr 2018 10:58:31 +0100 Subject: [PATCH 72/98] Bump to 0.12.1 --- CHANGELOG.md | 10 +++++++++- Cargo.toml | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bdc3e7e1c..be4662d3a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] ### Added + +### Changed + +### Removed + +## [0.12.1] - 2018-04-27 +### Added - `RequestParser` trait for retrieving Swagger related info in middlewares. ### Changed @@ -65,7 +72,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [0.5.0] - 2017-09-18 - Start of changelog. -[Unreleased]: https://github.com/Metaswitch/swagger-rs/compare/0.12.0...HEAD +[Unreleased]: https://github.com/Metaswitch/swagger-rs/compare/0.12.1...HEAD +[0.12.1]: https://github.com/Metaswitch/swagger-rs/compare/0.12.0...0.12.1 [0.12.0]: https://github.com/Metaswitch/swagger-rs/compare/0.11.0...0.12.0 [0.11.0]: https://github.com/Metaswitch/swagger-rs/compare/0.10.0...0.11.0 [0.10.0]: https://github.com/Metaswitch/swagger-rs/compare/0.9.0...0.10.0 diff --git a/Cargo.toml b/Cargo.toml index ec86accf30..b6297c248e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "swagger" -version = "0.12.0" +version = "0.12.1" authors = ["Metaswitch Networks Ltd"] license = "Apache-2.0" description = "A set of common utilities for Rust code generated by swagger-codegen" From a37139fc828c34b55691388f7233adeff88e9c6d Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Mon, 30 Apr 2018 16:25:23 +0100 Subject: [PATCH 73/98] Declare v1.0.0 --- CHANGELOG.md | 10 +++++----- Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index be4662d3a7..d743e210ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Removed +## [1.0.0] - 2018-04-30 +No changes. We now think we've got enough to declare this crate stable. + ## [0.12.1] - 2018-04-27 ### Added - `RequestParser` trait for retrieving Swagger related info in middlewares. @@ -18,8 +21,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed - Fixed `DropContext` to remove trait bounds on the type of context it can drop -### Removed - ## [0.12.0] - 2018-04-26 ### Added - `DropContext` to pass a raw (context-less) `hyper::Request` to a service. @@ -40,8 +41,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - Structs for combining multiple hyper services -### Changed - ## [0.9.0] - 2018-01-25 ### Added - Connector functions for instantiating easy-mode clients @@ -72,7 +71,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [0.5.0] - 2017-09-18 - Start of changelog. -[Unreleased]: https://github.com/Metaswitch/swagger-rs/compare/0.12.1...HEAD +[Unreleased]: https://github.com/Metaswitch/swagger-rs/compare/1.0.0...HEAD +[0.12.1]: https://github.com/Metaswitch/swagger-rs/compare/0.12.1...1.0.0 [0.12.1]: https://github.com/Metaswitch/swagger-rs/compare/0.12.0...0.12.1 [0.12.0]: https://github.com/Metaswitch/swagger-rs/compare/0.11.0...0.12.0 [0.11.0]: https://github.com/Metaswitch/swagger-rs/compare/0.10.0...0.11.0 diff --git a/Cargo.toml b/Cargo.toml index b6297c248e..b4e1a6a6a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "swagger" -version = "0.12.1" +version = "1.0.0" authors = ["Metaswitch Networks Ltd"] license = "Apache-2.0" description = "A set of common utilities for Rust code generated by swagger-codegen" From 08005b1f96678992ef797aad5fbd144017d531bb Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Mon, 30 Apr 2018 16:28:12 +0100 Subject: [PATCH 74/98] Correct changelog... --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d743e210ef..1e16add403 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,7 +72,7 @@ No changes. We now think we've got enough to declare this crate stable. - Start of changelog. [Unreleased]: https://github.com/Metaswitch/swagger-rs/compare/1.0.0...HEAD -[0.12.1]: https://github.com/Metaswitch/swagger-rs/compare/0.12.1...1.0.0 +[1.0.0]: https://github.com/Metaswitch/swagger-rs/compare/0.12.1...1.0.0 [0.12.1]: https://github.com/Metaswitch/swagger-rs/compare/0.12.0...0.12.1 [0.12.0]: https://github.com/Metaswitch/swagger-rs/compare/0.11.0...0.12.0 [0.11.0]: https://github.com/Metaswitch/swagger-rs/compare/0.10.0...0.11.0 From 0ed26843a1371fe6e23a39d6707183464d7de4d2 Mon Sep 17 00:00:00 2001 From: Jamie Gorman Date: Thu, 17 May 2018 15:32:45 +0100 Subject: [PATCH 75/98] Add SwaggerContext trait used by swagger-codegen middleware --- CHANGELOG.md | 1 + src/context.rs | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e16add403..2d080dbbcf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] ### Added +- `SwaggerService` trait used by swagger-codegen middlewares. ### Changed diff --git a/src/context.rs b/src/context.rs index cbb42a413b..849f5e78a9 100644 --- a/src/context.rs +++ b/src/context.rs @@ -9,6 +9,8 @@ use auth::{Authorization, AuthData}; use std::marker::Sized; use super::XSpanIdString; +use hyper; +use futures::future::Future; /// Defines methods for accessing, modifying, adding and removing the data stored /// in a context. Used to specify the requirements that a hyper service makes on @@ -491,6 +493,20 @@ where } } +/// Swagger uses a specific specialization of the hyper Service trait. +pub trait SwaggerService + : Clone + + hyper::server::Service< + Request = (hyper::server::Request, C), + Response = hyper::server::Response, + Error = hyper::Error, + Future = Box>, +> +where + C: Clone + 'static, +{ +} + #[cfg(test)] mod context_tests { use hyper::server::{NewService, Service}; From bc26033446d42bb5064316cc69ff43a702d953fa Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Fri, 18 May 2018 16:03:45 +0100 Subject: [PATCH 76/98] Move to rustfmt 0.4.1-stable (the version packaged with Rust 1.26) --- .travis.yml | 5 ++- src/add_context.rs | 24 ++++++------ src/auth.rs | 42 ++++++++++++--------- src/base64_format.rs | 4 +- src/composites.rs | 41 +++++---------------- src/connector.rs | 18 ++++----- src/context.rs | 83 +++++++++++++++++++++++------------------- src/drop_context.rs | 15 +++----- src/lib.rs | 2 +- src/nullable_format.rs | 29 ++++++--------- 10 files changed, 123 insertions(+), 140 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3ebe3715c5..73fe1bda4f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,7 +18,10 @@ matrix: - rust: nightly-2018-03-07 before_script: - cargo install clippy --vers 0.0.187 - - cargo install rustfmt --vers 0.9.0 --force script: - cargo clippy -- -D warnings + - rust: stable + before_script: + - rustup component add rustfmt-preview + script: - cargo fmt -- --write-mode diff diff --git a/src/add_context.rs b/src/add_context.rs index 40b1014580..c551dc276b 100644 --- a/src/add_context.rs +++ b/src/add_context.rs @@ -1,11 +1,11 @@ //! Hyper service that adds a context to an incoming request and passes it on //! to a wrapped service. +use super::{Push, XSpanIdString}; +use hyper; +use hyper::{Error, Request, Response}; use std::io; use std::marker::PhantomData; -use hyper; -use hyper::{Request, Response, Error}; -use super::{Push, XSpanIdString}; /// Middleware wrapper service, that should be used as the outermost layer in a /// stack of hyper services. Adds a context to a plain `hyper::Request` that can be @@ -33,10 +33,13 @@ where } impl hyper::server::NewService for AddContext - where - C: Default + Push, - T: hyper::server::NewService, - +where + C: Default + Push, + T: hyper::server::NewService< + Request = (Request, C::Result), + Response = Response, + Error = Error, + >, { type Request = Request; type Response = Response; @@ -51,12 +54,7 @@ impl hyper::server::NewService for AddContext impl hyper::server::Service for AddContext where C: Default + Push, - T: hyper::server::Service< - Request = (Request, - C::Result), - Response = Response, - Error = Error, - >, + T: hyper::server::Service, { type Request = Request; type Response = Response; diff --git a/src/auth.rs b/src/auth.rs index 99c11487ee..067c7ce639 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -1,11 +1,11 @@ //! Authentication and authorization data structures +use super::Push; +use hyper; +use hyper::{Error, Request, Response}; use std::collections::BTreeSet; use std::io; use std::marker::PhantomData; -use hyper; -use hyper::{Request, Response, Error}; -use super::Push; /// Authorization scopes. #[derive(Clone, Debug, PartialEq)] @@ -64,7 +64,9 @@ impl AuthData { /// Set Bearer token authentication pub fn bearer(token: &str) -> Self { - AuthData::Bearer(hyper::header::Bearer { token: token.to_owned() }) + AuthData::Bearer(hyper::header::Bearer { + token: token.to_owned(), + }) } /// Set ApiKey authentication @@ -100,10 +102,13 @@ where } impl hyper::server::NewService for AllowAllAuthenticator - where - C: Push>, - T: hyper::server::NewService, - +where + C: Push>, + T: hyper::server::NewService< + Request = (Request, C::Result), + Response = Response, + Error = Error, + >, { type Request = (Request, C); type Response = Response; @@ -111,14 +116,16 @@ impl hyper::server::NewService for AllowAllAuthenticator type Instance = AllowAllAuthenticator; fn new_service(&self) -> Result { - self.inner.new_service().map(|s| AllowAllAuthenticator::new(s, self.subject.clone())) + self.inner + .new_service() + .map(|s| AllowAllAuthenticator::new(s, self.subject.clone())) } } impl hyper::server::Service for AllowAllAuthenticator - where - C : Push>, - T: hyper::server::Service, +where + C: Push>, + T: hyper::server::Service, { type Request = (Request, C); type Response = Response; @@ -126,12 +133,11 @@ impl hyper::server::Service for AllowAllAuthenticator type Future = T::Future; fn call(&self, (req, context): Self::Request) -> Self::Future { - let context = context.push( - Some(Authorization{ - subject: self.subject.clone(), - scopes: Scopes::All, - issuer: None, - })); + let context = context.push(Some(Authorization { + subject: self.subject.clone(), + scopes: Scopes::All, + issuer: None, + })); self.inner.call((req, context)) } } diff --git a/src/base64_format.rs b/src/base64_format.rs index 597d115819..b00f1e875a 100644 --- a/src/base64_format.rs +++ b/src/base64_format.rs @@ -2,11 +2,11 @@ // dead code. #![allow(dead_code)] #[cfg(feature = "serdejson")] -use serde::ser::{Serialize, Serializer}; +use base64::{decode, encode}; #[cfg(feature = "serdejson")] use serde::de::{Deserialize, Deserializer, Error}; #[cfg(feature = "serdejson")] -use base64::{encode, decode}; +use serde::ser::{Serialize, Serializer}; use std::ops::{Deref, DerefMut}; #[derive(Debug, Clone, PartialEq, PartialOrd)] diff --git a/src/composites.rs b/src/composites.rs index c6ef65b7fb..36a2d19540 100644 --- a/src/composites.rs +++ b/src/composites.rs @@ -2,11 +2,11 @@ //! //! Use by passing `hyper::server::NewService` instances to a `CompositeNewService` //! together with the base path for requests that should be handled by that service. -use std::{io, fmt}; -use std::ops::{Deref, DerefMut}; -use hyper::server::{Service, NewService}; -use hyper::{Request, Response, StatusCode}; use futures::{future, Future}; +use hyper::server::{NewService, Service}; +use hyper::{Request, Response, StatusCode}; +use std::ops::{Deref, DerefMut}; +use std::{fmt, io}; /// Trait for getting the path of a request. Must be implemented on the `Request` /// associated type for `NewService`s being combined in a `CompositeNewService`. @@ -43,14 +43,8 @@ impl NotFound for Response { type BoxedFuture = Box>; type CompositeNewServiceVec = Vec<(&'static str, Box>)>; -type BoxedService = Box< - Service< - Request = U, - Response = V, - Error = W, - Future = BoxedFuture, - >, ->; +type BoxedService = + Box>>; /// Trait for wrapping hyper `NewService`s to make the return type of `new_service` uniform. /// This is necessary in order for the `NewService`s with different `Instance` types to @@ -63,16 +57,10 @@ pub trait BoxedNewService { impl BoxedNewService for T where T: NewService, - T::Instance: Service> - + 'static, + T::Instance: Service> + 'static, { /// Call the `new_service` method of the wrapped `NewService` and `Box` the result - fn boxed_new_service( - &self, - ) -> Result< - BoxedService, - io::Error, - > { + fn boxed_new_service(&self) -> Result, io::Error> { let service = self.new_service()?; Ok(Box::new(service)) } @@ -146,11 +134,7 @@ where fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { // Get vector of base paths let str_vec: Vec<&'static str> = self.0.iter().map(|&(base_path, _)| base_path).collect(); - write!( - f, - "CompositeNewService accepting base paths: {:?}", - str_vec, - ) + write!(f, "CompositeNewService accepting base paths: {:?}", str_vec,) } } @@ -197,7 +181,6 @@ where type Future = Box>; fn call(&self, req: Self::Request) -> Self::Future { - let mut result = None; for &(base_path, ref service) in &self.0 { @@ -220,11 +203,7 @@ where fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { // Get vector of base paths let str_vec: Vec<&'static str> = self.0.iter().map(|&(base_path, _)| base_path).collect(); - write!( - f, - "CompositeService accepting base paths: {:?}", - str_vec, - ) + write!(f, "CompositeService accepting base paths: {:?}", str_vec,) } } diff --git a/src/connector.rs b/src/connector.rs index 349764d43c..c0349a6c9b 100644 --- a/src/connector.rs +++ b/src/connector.rs @@ -1,20 +1,18 @@ //! Utility methods for instantiating common connectors for clients. extern crate hyper_tls; -extern crate tokio_core; -extern crate openssl; extern crate native_tls; +extern crate openssl; +extern crate tokio_core; use std::path::Path; -use hyper; use self::tokio_core::reactor::Handle; +use hyper; /// Returns a function which creates an http-connector. Used for instantiating /// clients with custom connectors pub fn http_connector() -> Box hyper::client::HttpConnector + Send + Sync> { - Box::new(move |handle: &Handle| { - hyper::client::HttpConnector::new(4, handle) - }) + Box::new(move |handle: &Handle| hyper::client::HttpConnector::new(4, handle)) } /// Returns a function which creates an https-connector @@ -31,8 +29,8 @@ where let ca_certificate = ca_certificate.as_ref().to_owned(); Box::new(move |handle: &Handle| { // SSL implementation - let mut ssl = openssl::ssl::SslConnectorBuilder::new(openssl::ssl::SslMethod::tls()) - .unwrap(); + let mut ssl = + openssl::ssl::SslConnectorBuilder::new(openssl::ssl::SslMethod::tls()).unwrap(); // Server authentication ssl.set_ca_file(ca_certificate.clone()).unwrap(); @@ -68,8 +66,8 @@ where let client_certificate = client_certificate.as_ref().to_owned(); Box::new(move |handle: &Handle| { // SSL implementation - let mut ssl = openssl::ssl::SslConnectorBuilder::new(openssl::ssl::SslMethod::tls()) - .unwrap(); + let mut ssl = + openssl::ssl::SslConnectorBuilder::new(openssl::ssl::SslMethod::tls()).unwrap(); // Server authentication ssl.set_ca_file(ca_certificate.clone()).unwrap(); diff --git a/src/context.rs b/src/context.rs index cbb42a413b..ca01fe1fcd 100644 --- a/src/context.rs +++ b/src/context.rs @@ -6,9 +6,9 @@ //! //! See the `context_tests` module below for examples of how to use. -use auth::{Authorization, AuthData}; -use std::marker::Sized; use super::XSpanIdString; +use auth::{AuthData, Authorization}; +use std::marker::Sized; /// Defines methods for accessing, modifying, adding and removing the data stored /// in a context. Used to specify the requirements that a hyper service makes on @@ -376,11 +376,12 @@ macro_rules! new_context_type { } /// Create a default context type to export. -new_context_type!(ContextBuilder, - EmptyContext, - XSpanIdString, - Option, - Option +new_context_type!( + ContextBuilder, + EmptyContext, + XSpanIdString, + Option, + Option ); /// Macro for easily defining context types. The first argument should be a @@ -493,13 +494,13 @@ where #[cfg(test)] mod context_tests { + use super::*; + use futures::future::{ok, Future}; use hyper::server::{NewService, Service}; - use hyper::{Response, Request, Error, Method, Uri}; - use std::marker::PhantomData; + use hyper::{Error, Method, Request, Response, Uri}; use std::io; + use std::marker::PhantomData; use std::str::FromStr; - use futures::future::{Future, ok}; - use super::*; struct ContextItem1; struct ContextItem2; @@ -530,7 +531,6 @@ mod context_tests { type Error = Error; type Future = Box>; fn call(&self, (_, context): Self::Request) -> Self::Future { - use_item_2(Has::::get(&context)); let (item3, _): (ContextItem3, _) = context.pop(); @@ -552,7 +552,9 @@ mod context_tests { C: Has + Pop, { fn new() -> Self { - InnerNewService { marker: PhantomData } + InnerNewService { + marker: PhantomData, + } } } @@ -565,7 +567,9 @@ mod context_tests { type Error = Error; type Instance = InnerService; fn new_service(&self) -> Result { - Ok(InnerService { marker: PhantomData }) + Ok(InnerService { + marker: PhantomData, + }) } } @@ -577,10 +581,12 @@ mod context_tests { C: Pop, C::Result: Push, >::Result: Push, - T: Service>::Result as Push>::Result - )>, + T: Service< + Request = ( + Request, + <>::Result as Push>::Result, + ), + >, { inner: T, marker1: PhantomData, @@ -612,10 +618,12 @@ mod context_tests { C: Pop, C::Result: Push, >::Result: Push, - T: NewService>::Result as Push>::Result - )>, + T: NewService< + Request = ( + Request, + <>::Result as Push>::Result, + ), + >, { inner: T, marker1: PhantomData, @@ -633,11 +641,9 @@ mod context_tests { type Error = T::Error; type Instance = MiddleService; fn new_service(&self) -> Result { - self.inner.new_service().map(|s| { - MiddleService { - inner: s, - marker1: PhantomData, - } + self.inner.new_service().map(|s| MiddleService { + inner: s, + marker1: PhantomData, }) } } @@ -705,11 +711,9 @@ mod context_tests { type Error = T::Error; type Instance = OuterService; fn new_service(&self) -> Result { - self.inner.new_service().map(|s| { - OuterService { - inner: s, - marker: PhantomData, - } + self.inner.new_service().map(|s| OuterService { + inner: s, + marker: PhantomData, }) } } @@ -732,17 +736,22 @@ mod context_tests { // their contexts types have. Use the `new_context_type!` macro to create // a context type and empty context type that are capable of containing all the // types that your hyper services require. - new_context_type!(MyContext, MyEmptyContext, ContextItem1, ContextItem2, ContextItem3); + new_context_type!( + MyContext, + MyEmptyContext, + ContextItem1, + ContextItem2, + ContextItem3 + ); #[test] fn send_request() { - // annotate the outermost service to indicate that the context type it // uses is the empty context type created by the above macro invocation. // the compiler should infer all the other context types. - let new_service = OuterNewService::<_, MyEmptyContext>::new( - MiddleNewService::new(InnerNewService::new()), - ); + let new_service = OuterNewService::<_, MyEmptyContext>::new(MiddleNewService::new( + InnerNewService::new(), + )); let req = Request::new(Method::Post, Uri::from_str("127.0.0.1:80").unwrap()); new_service diff --git a/src/drop_context.rs b/src/drop_context.rs index c93829a588..47994373e7 100644 --- a/src/drop_context.rs +++ b/src/drop_context.rs @@ -1,10 +1,10 @@ //! Hyper service that drops a context to an incoming request and passes it on //! to a wrapped service. +use hyper; +use hyper::{Error, Request, Response}; use std::io; use std::marker::PhantomData; -use hyper; -use hyper::{Request, Response, Error}; /// Middleware wrapper service that trops the context from the incoming request /// and passes the plain `hyper::Request` to the wrapped service. @@ -46,9 +46,8 @@ impl DropContext { } impl hyper::server::NewService for DropContext - where - T: hyper::server::NewService, - +where + T: hyper::server::NewService, { type Request = (Request, C); type Response = Response; @@ -62,11 +61,7 @@ impl hyper::server::NewService for DropContext impl hyper::server::Service for DropContext where - T: hyper::server::Service< - Request = Request, - Response = Response, - Error = Error, - >, + T: hyper::server::Service, { type Request = (Request, C); type Response = Response; diff --git a/src/lib.rs b/src/lib.rs index ff139ace78..c502c3fe28 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,8 +19,8 @@ extern crate hyper; extern crate futures; extern crate uuid; -use std::fmt; use std::error; +use std::fmt; /// Module for encoding API properties in base64. pub mod base64_format; diff --git a/src/nullable_format.rs b/src/nullable_format.rs index a06ac2c99d..b08824c36d 100644 --- a/src/nullable_format.rs +++ b/src/nullable_format.rs @@ -2,11 +2,11 @@ // dead code. #![allow(dead_code)] #[cfg(feature = "serdejson")] -use serde::ser::{Serialize, Serializer}; +use serde::de::Error as SerdeError; #[cfg(feature = "serdejson")] -use serde::de::{Deserializer, Deserialize, DeserializeOwned}; +use serde::de::{Deserialize, DeserializeOwned, Deserializer}; #[cfg(feature = "serdejson")] -use serde::de::Error as SerdeError; +use serde::ser::{Serialize, Serializer}; use std::mem; @@ -499,7 +499,6 @@ impl Nullable { } } - impl<'a, T: Clone> Nullable<&'a T> { /// Maps an `Nullable<&T>` to an `Nullable` by cloning the contents of the /// Nullable. @@ -607,11 +606,9 @@ where ::serde::Deserialize::deserialize(deserializer); match presence { Ok(::serde_json::Value::Null) => Ok(Nullable::Null), - Ok(some_value) => { - ::serde_json::from_value(some_value) - .map(Nullable::Present) - .map_err(SerdeError::custom) - } + Ok(some_value) => ::serde_json::from_value(some_value) + .map(Nullable::Present) + .map_err(SerdeError::custom), Err(x) => Err(x), } } @@ -676,13 +673,12 @@ mod serde_tests { ::serde_json::from_str($string).expect("Deserialization to JSON Value failed"); println!("JSON Value: {:?}", json); - let thing: $type = - ::serde_json::from_value(json.clone()).expect("Deserialization to struct failed"); + let thing: $type = ::serde_json::from_value(json.clone()) + .expect("Deserialization to struct failed"); println!("Struct: {:?}", thing); - let json_redux: ::serde_json::Value = - ::serde_json::to_value(thing.clone()) - .expect("Reserialization to JSON Value failed"); + let json_redux: ::serde_json::Value = ::serde_json::to_value(thing.clone()) + .expect("Reserialization to JSON Value failed"); println!("JSON Redux: {:?}", json_redux); let string_redux = @@ -690,11 +686,10 @@ mod serde_tests { println!("String Redux: {:?}", string_redux); assert_eq!( - $string, - string_redux, + $string, string_redux, "Original did not match after round trip" ); - } + }; } // The tests: From 4c7dd76755f7805a54ffc86fa2fdcfebc6dcb571 Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Fri, 18 May 2018 16:08:53 +0100 Subject: [PATCH 77/98] Disambiguate the two stable builds --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 73fe1bda4f..54c77c9f89 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,6 +21,7 @@ matrix: script: - cargo clippy -- -D warnings - rust: stable + env: RUSTFMT=1 before_script: - rustup component add rustfmt-preview script: From 581ed58ae1097995a2072e48c629cf58ec635691 Mon Sep 17 00:00:00 2001 From: Jamie Gorman Date: Mon, 21 May 2018 09:28:22 +0100 Subject: [PATCH 78/98] Cargo fmt output --- src/context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/context.rs b/src/context.rs index 849f5e78a9..b089f5dc81 100644 --- a/src/context.rs +++ b/src/context.rs @@ -503,7 +503,7 @@ pub trait SwaggerService Future = Box>, > where - C: Clone + 'static, + C: Clone + 'static { } From 5fc2a0a38a3bc1a16421dc765976708b1b690ce1 Mon Sep 17 00:00:00 2001 From: Jamie Gorman Date: Tue, 22 May 2018 11:11:55 +0100 Subject: [PATCH 79/98] Reveiw mark-ups --- src/context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/context.rs b/src/context.rs index b089f5dc81..4dda1f3d99 100644 --- a/src/context.rs +++ b/src/context.rs @@ -503,7 +503,7 @@ pub trait SwaggerService Future = Box>, > where - C: Clone + 'static + C: Has> + Has> + Has + Clone + 'static { } From 8c1a74778de17925a3bd5b485c7112b333210875 Mon Sep 17 00:00:00 2001 From: Jamie Gorman Date: Tue, 22 May 2018 11:25:13 +0100 Subject: [PATCH 80/98] cargo fmt --- src/context.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/context.rs b/src/context.rs index 8032261d07..162792a6a3 100644 --- a/src/context.rs +++ b/src/context.rs @@ -7,9 +7,9 @@ //! See the `context_tests` module below for examples of how to use. use super::XSpanIdString; +use auth::{AuthData, Authorization}; use hyper; use futures::future::Future; -use auth::{AuthData, Authorization}; use std::marker::Sized; /// Defines methods for accessing, modifying, adding and removing the data stored @@ -495,16 +495,16 @@ where } /// Swagger uses a specific specialization of the hyper Service trait. -pub trait SwaggerService - : Clone +pub trait SwaggerService: + Clone + hyper::server::Service< - Request = (hyper::server::Request, C), - Response = hyper::server::Response, - Error = hyper::Error, - Future = Box>, -> + Request = (hyper::server::Request, C), + Response = hyper::server::Response, + Error = hyper::Error, + Future = Box>, + > where - C: Has> + Has> + Has + Clone + 'static + C: Has> + Has> + Has + Clone + 'static, { } From ad27c58fa951a628672a9ee7f6d1497cf95f6475 Mon Sep 17 00:00:00 2001 From: Jamie Gorman Date: Tue, 22 May 2018 11:26:26 +0100 Subject: [PATCH 81/98] cargo fmt --- src/context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/context.rs b/src/context.rs index 162792a6a3..1aa7289849 100644 --- a/src/context.rs +++ b/src/context.rs @@ -8,8 +8,8 @@ use super::XSpanIdString; use auth::{AuthData, Authorization}; -use hyper; use futures::future::Future; +use hyper; use std::marker::Sized; /// Defines methods for accessing, modifying, adding and removing the data stored From 180e6116e978f5b47282e979e24930e150759fe3 Mon Sep 17 00:00:00 2001 From: Jamie Gorman Date: Tue, 22 May 2018 15:28:21 +0100 Subject: [PATCH 82/98] Add generic implementation for SwaggerService trait --- src/context.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/context.rs b/src/context.rs index 1aa7289849..814465310d 100644 --- a/src/context.rs +++ b/src/context.rs @@ -508,6 +508,19 @@ where { } +impl SwaggerService for T +where + T: Clone + + hyper::server::Service< + Request = (hyper::server::Request, C), + Response = hyper::server::Response, + Error = hyper::Error, + Future = Box>, + >, + C: Has> + Has> + Has + Clone + 'static, +{ +} + #[cfg(test)] mod context_tests { use super::*; From ca2256f0c1de2bbdf09ea2438edda1a7b60a387d Mon Sep 17 00:00:00 2001 From: Jamie Gorman Date: Tue, 22 May 2018 15:39:26 +0100 Subject: [PATCH 83/98] Cargo fmt --- src/context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/context.rs b/src/context.rs index 814465310d..14e379ada3 100644 --- a/src/context.rs +++ b/src/context.rs @@ -508,7 +508,7 @@ where { } -impl SwaggerService for T +impl SwaggerService for T where T: Clone + hyper::server::Service< From 1af5050435007d1cb11acd44291463bbb3cd914c Mon Sep 17 00:00:00 2001 From: Jamie Gorman Date: Wed, 23 May 2018 09:18:42 +0100 Subject: [PATCH 84/98] Add rust doc --- src/context.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/context.rs b/src/context.rs index 14e379ada3..8c9cd7673b 100644 --- a/src/context.rs +++ b/src/context.rs @@ -494,7 +494,18 @@ where } } -/// Swagger uses a specific specialization of the hyper Service trait. +/// Trait designed to ensure consistency in context used by swagger middlewares +/// +/// ```rust +/// impl hyper::server::Service for ExampleMiddleware +/// where +/// T: SwaggerService, +/// C: Has> + +/// Has> + +/// Has + +/// Clone + +/// 'static, +/// ``` pub trait SwaggerService: Clone + hyper::server::Service< From b2ae97673b4d7a37d699eb0644479e5d0042f01a Mon Sep 17 00:00:00 2001 From: Jamie Gorman Date: Wed, 23 May 2018 09:47:10 +0100 Subject: [PATCH 85/98] Rust doc failure --- src/context.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/context.rs b/src/context.rs index 8c9cd7673b..54bb5adb91 100644 --- a/src/context.rs +++ b/src/context.rs @@ -505,6 +505,8 @@ where /// Has + /// Clone + /// 'static, +/// { +/// } /// ``` pub trait SwaggerService: Clone From de784fae164042c8100a7c8089596a334186c80e Mon Sep 17 00:00:00 2001 From: Jamie Gorman Date: Wed, 23 May 2018 10:21:18 +0100 Subject: [PATCH 86/98] Rust doc failure --- src/context.rs | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/context.rs b/src/context.rs index 54bb5adb91..9fa8cb944a 100644 --- a/src/context.rs +++ b/src/context.rs @@ -497,14 +497,24 @@ where /// Trait designed to ensure consistency in context used by swagger middlewares /// /// ```rust +/// # extern crate hyper; +/// # extern crate swagger; +/// # use swagger::context::*; +/// # use std::marker::PhantomData; +/// +/// struct ExampleMiddleware { +/// inner: T, +/// marker: PhantomData, +/// } +/// /// impl hyper::server::Service for ExampleMiddleware -/// where -/// T: SwaggerService, -/// C: Has> + -/// Has> + -/// Has + -/// Clone + -/// 'static, +/// where +/// T: SwaggerService, +/// C: Has> + +/// Has> + +/// Has + +/// Clone + +/// 'static, /// { /// } /// ``` From a5f27c3097332a8ba7abb69be41cf5b7a6be5cb3 Mon Sep 17 00:00:00 2001 From: Jamie Gorman Date: Wed, 23 May 2018 10:30:44 +0100 Subject: [PATCH 87/98] Rust doc failure --- src/context.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/context.rs b/src/context.rs index 9fa8cb944a..7434ca184a 100644 --- a/src/context.rs +++ b/src/context.rs @@ -501,6 +501,8 @@ where /// # extern crate swagger; /// # use swagger::context::*; /// # use std::marker::PhantomData; +/// # use swagger::auth::{AuthData, Authorization}; +/// # use swagger::XSpanIdString; /// /// struct ExampleMiddleware { /// inner: T, @@ -516,6 +518,13 @@ where /// Clone + /// 'static, /// { +/// type Request = (hyper::Request, C); +/// type Response = T::Response; +/// type Error = T::Error; +/// type Future = T::Future; +/// fn call(&self, (req, context) : Self::Request) -> Self::Future { +/// self.inner.call((req, context)) +/// } /// } /// ``` pub trait SwaggerService: From c29ef77def38a2ddb6bf0671c8b9cc6f6c9ded4d Mon Sep 17 00:00:00 2001 From: Jamie Gorman Date: Wed, 23 May 2018 10:41:21 +0100 Subject: [PATCH 88/98] cargo fmt --- src/context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/context.rs b/src/context.rs index 7434ca184a..f70e93a80e 100644 --- a/src/context.rs +++ b/src/context.rs @@ -503,7 +503,7 @@ where /// # use std::marker::PhantomData; /// # use swagger::auth::{AuthData, Authorization}; /// # use swagger::XSpanIdString; -/// +/// /// struct ExampleMiddleware { /// inner: T, /// marker: PhantomData, From e999568a0cfe2376a8311aa1a77a906cbf9e719e Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Thu, 24 May 2018 12:12:13 +0100 Subject: [PATCH 89/98] Release 1.0.1 + add release instructions for future reference --- CHANGELOG.md | 8 ++++++-- Cargo.toml | 2 +- README.md | 8 ++++++++ release-changelog.sh | 12 ++++++++++++ 4 files changed, 27 insertions(+), 3 deletions(-) create mode 100755 release-changelog.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d080dbbcf..a824a9f0b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,12 +6,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] ### Added -- `SwaggerService` trait used by swagger-codegen middlewares. ### Changed ### Removed +## [1.0.1] - 2018-05-24 +### Added +- `SwaggerService` trait used by swagger-codegen middlewares. + ## [1.0.0] - 2018-04-30 No changes. We now think we've got enough to declare this crate stable. @@ -72,7 +75,8 @@ No changes. We now think we've got enough to declare this crate stable. ## [0.5.0] - 2017-09-18 - Start of changelog. -[Unreleased]: https://github.com/Metaswitch/swagger-rs/compare/1.0.0...HEAD +[Unreleased]: https://github.com/Metaswitch/swagger-rs/compare/1.0.1...HEAD +[1.0.1]: https://github.com/Metaswitch/swagger-rs/compare/1.0.1...1.0.0 [1.0.0]: https://github.com/Metaswitch/swagger-rs/compare/0.12.1...1.0.0 [0.12.1]: https://github.com/Metaswitch/swagger-rs/compare/0.12.0...0.12.1 [0.12.0]: https://github.com/Metaswitch/swagger-rs/compare/0.11.0...0.12.0 diff --git a/Cargo.toml b/Cargo.toml index b4e1a6a6a7..1a774e904d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "swagger" -version = "1.0.0" +version = "1.0.1" authors = ["Metaswitch Networks Ltd"] license = "Apache-2.0" description = "A set of common utilities for Rust code generated by swagger-codegen" diff --git a/README.md b/README.md index 7f60b1863e..b65b83214b 100644 --- a/README.md +++ b/README.md @@ -4,3 +4,11 @@ [![crates.io](https://img.shields.io/crates/v/swagger.svg)](https://crates.io/crates/swagger) A set of common utilities for crates generated by the `rust-server` [swagger-codegen](https://github.com/swagger-api/swagger-codegen) generator + +# Releasing a new version + +1. Update the version in Cargo.toml +2. Run `./release-changelog.sh ` to update the changelog +3. Commit and push your changes. +4. Wait for a travis build to complete successfully. +5. Run `cargo publish`. diff --git a/release-changelog.sh b/release-changelog.sh new file mode 100755 index 0000000000..61d6504955 --- /dev/null +++ b/release-changelog.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# Updated the changelog for a new release +set -exou pipefail + +version=$1 +date=$(date +%Y-%m-%d) + +sed -i "s/## \[Unreleased\]/## [Unreleased]\n### Added\n\n### Changed\n\n### Removed\n\n## [$version] - $date/" CHANGELOG.md + +sed -i "s#\[Unreleased\]: https://github.com/Metaswitch/swagger-rs/compare/\(.*\)...HEAD#[Unreleased]: https://github.com/Metaswitch/swagger-rs/compare/$version...HEAD\n[$version]: https://github.com/Metaswitch/swagger-rs/compare/$version...\1#" CHANGELOG.md + +echo "Now, delete any empty headers from $version in CHANGELOG.md" From 34f1298a1f363d4af4450b8433fa925e774045b3 Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Thu, 24 May 2018 12:19:17 +0100 Subject: [PATCH 90/98] Get comparison the correct way round --- CHANGELOG.md | 2 +- release-changelog.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a824a9f0b8..caaa11a39a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -76,7 +76,7 @@ No changes. We now think we've got enough to declare this crate stable. - Start of changelog. [Unreleased]: https://github.com/Metaswitch/swagger-rs/compare/1.0.1...HEAD -[1.0.1]: https://github.com/Metaswitch/swagger-rs/compare/1.0.1...1.0.0 +[1.0.1]: https://github.com/Metaswitch/swagger-rs/compare/1.0.0...1.0.1 [1.0.0]: https://github.com/Metaswitch/swagger-rs/compare/0.12.1...1.0.0 [0.12.1]: https://github.com/Metaswitch/swagger-rs/compare/0.12.0...0.12.1 [0.12.0]: https://github.com/Metaswitch/swagger-rs/compare/0.11.0...0.12.0 diff --git a/release-changelog.sh b/release-changelog.sh index 61d6504955..d4b950d29f 100755 --- a/release-changelog.sh +++ b/release-changelog.sh @@ -7,6 +7,6 @@ date=$(date +%Y-%m-%d) sed -i "s/## \[Unreleased\]/## [Unreleased]\n### Added\n\n### Changed\n\n### Removed\n\n## [$version] - $date/" CHANGELOG.md -sed -i "s#\[Unreleased\]: https://github.com/Metaswitch/swagger-rs/compare/\(.*\)...HEAD#[Unreleased]: https://github.com/Metaswitch/swagger-rs/compare/$version...HEAD\n[$version]: https://github.com/Metaswitch/swagger-rs/compare/$version...\1#" CHANGELOG.md +sed -i "s#\[Unreleased\]: https://github.com/Metaswitch/swagger-rs/compare/\(.*\)...HEAD#[Unreleased]: https://github.com/Metaswitch/swagger-rs/compare/$version...HEAD\n[$version]: https://github.com/Metaswitch/swagger-rs/compare/\1...$version#" CHANGELOG.md echo "Now, delete any empty headers from $version in CHANGELOG.md" From 4fe25e84359a09bf1bc4f504e05ebd6059194623 Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Thu, 31 May 2018 14:37:44 +0100 Subject: [PATCH 91/98] Update to clippy 0.0.206 Fixes https://github.com/Metaswitch/swagger-rs/issues/40 --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 54c77c9f89..2fcbbe0417 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,9 +15,9 @@ matrix: allow_failures: - rust: nightly include: - - rust: nightly-2018-03-07 + - rust: nightly-2018-05-30 before_script: - - cargo install clippy --vers 0.0.187 + - cargo install clippy --vers 0.0.206 script: - cargo clippy -- -D warnings - rust: stable From f51e9556eb0f9305d86a79c21dad0e23bf137fcc Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Thu, 19 Jul 2018 16:04:19 +0100 Subject: [PATCH 92/98] Use clippy-preview from 2018-07-16 --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2fcbbe0417..ecfdfe4ca8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,9 +15,9 @@ matrix: allow_failures: - rust: nightly include: - - rust: nightly-2018-05-30 + - rust: nightly-2018-07-16 before_script: - - cargo install clippy --vers 0.0.206 + - rustup component add clippy-preview script: - cargo clippy -- -D warnings - rust: stable From 6488ec3a22d27dfdad28a099b6e038b888cf7d6b Mon Sep 17 00:00:00 2001 From: Alexander Polyakov Date: Mon, 23 Jul 2018 16:35:13 +0300 Subject: [PATCH 93/98] Add https connector stubs for OSX/iOS/Windows --- src/connector.rs | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/connector.rs b/src/connector.rs index c0349a6c9b..68a8598d23 100644 --- a/src/connector.rs +++ b/src/connector.rs @@ -1,6 +1,8 @@ //! Utility methods for instantiating common connectors for clients. extern crate hyper_tls; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] extern crate native_tls; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] extern crate openssl; extern crate tokio_core; @@ -20,6 +22,7 @@ pub fn http_connector() -> Box hyper::client::HttpConnector + Sen /// # Arguments /// /// * `ca_certificate` - Path to CA certificate used to authenticate the server +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] pub fn https_connector( ca_certificate: CA, ) -> Box hyper_tls::HttpsConnector + Send + Sync> @@ -45,12 +48,25 @@ where }) } +/// Not currently implemented on Mac OS X, iOS and Windows. +/// This function will panic when called. +#[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] +pub fn https_connector( + _ca_certificate: CA, +) -> Box hyper_tls::HttpsConnector + Send + Sync> +where + CA: AsRef, +{ + unimplemented!("See issue #43 (https://github.com/Metaswitch/swagger-rs/issues/43)") +} + /// Returns a function which creates https-connectors for mutually authenticated connections. /// # Arguments /// /// * `ca_certificate` - Path to CA certificate used to authenticate the server /// * `client_key` - Path to the client private key /// * `client_certificate` - Path to the client's public certificate associated with the private key +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] pub fn https_mutual_connector( ca_certificate: CA, client_key: K, @@ -88,3 +104,19 @@ where connector }) } + +/// Not currently implemented on Mac OS X, iOS and Windows. +/// This function will panic when called. +#[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] +pub fn https_mutual_connector( + _ca_certificate: CA, + _client_key: K, + _client_certificate: C, +) -> Box hyper_tls::HttpsConnector + Send + Sync> +where + CA: AsRef, + K: AsRef, + C: AsRef, +{ + unimplemented!("See issue #43 (https://github.com/Metaswitch/swagger-rs/issues/43)") +} \ No newline at end of file From a80b1a1eb980d129032269e6ee944b230e3a22bb Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Mon, 23 Jul 2018 15:58:35 +0100 Subject: [PATCH 94/98] Release script now bumps manifest version --- README.md | 3 +-- release-changelog.sh | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b65b83214b..b418569c2d 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,7 @@ A set of common utilities for crates generated by the `rust-server` [swagger-cod # Releasing a new version -1. Update the version in Cargo.toml -2. Run `./release-changelog.sh ` to update the changelog +2. Run `./release-changelog.sh ` to update the changelog and `Cargo.toml` 3. Commit and push your changes. 4. Wait for a travis build to complete successfully. 5. Run `cargo publish`. diff --git a/release-changelog.sh b/release-changelog.sh index d4b950d29f..32d4f77954 100755 --- a/release-changelog.sh +++ b/release-changelog.sh @@ -1,10 +1,13 @@ #!/usr/bin/env bash # Updated the changelog for a new release -set -exou pipefail +set -eou pipefail version=$1 date=$(date +%Y-%m-%d) + +sed -i "s/^version = \".\+\"$/version = \"$version\"/" Cargo.toml + sed -i "s/## \[Unreleased\]/## [Unreleased]\n### Added\n\n### Changed\n\n### Removed\n\n## [$version] - $date/" CHANGELOG.md sed -i "s#\[Unreleased\]: https://github.com/Metaswitch/swagger-rs/compare/\(.*\)...HEAD#[Unreleased]: https://github.com/Metaswitch/swagger-rs/compare/$version...HEAD\n[$version]: https://github.com/Metaswitch/swagger-rs/compare/\1...$version#" CHANGELOG.md From 7f6567ed588b344fdd30b8b8be698f0fd6712070 Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Mon, 23 Jul 2018 15:59:34 +0100 Subject: [PATCH 95/98] Release v1.0.2 --- CHANGELOG.md | 7 ++++++- Cargo.toml | 2 +- README.md | 8 ++++---- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index caaa11a39a..f608af7ad7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Removed +## [1.0.2] - 2018-07-23 +### Added +- Added (non-HTTPS) support for Windows/MacOS/iOS + ## [1.0.1] - 2018-05-24 ### Added - `SwaggerService` trait used by swagger-codegen middlewares. @@ -75,7 +79,8 @@ No changes. We now think we've got enough to declare this crate stable. ## [0.5.0] - 2017-09-18 - Start of changelog. -[Unreleased]: https://github.com/Metaswitch/swagger-rs/compare/1.0.1...HEAD +[Unreleased]: https://github.com/Metaswitch/swagger-rs/compare/1.0.2...HEAD +[1.0.2]: https://github.com/Metaswitch/swagger-rs/compare/1.0.1...1.0.2 [1.0.1]: https://github.com/Metaswitch/swagger-rs/compare/1.0.0...1.0.1 [1.0.0]: https://github.com/Metaswitch/swagger-rs/compare/0.12.1...1.0.0 [0.12.1]: https://github.com/Metaswitch/swagger-rs/compare/0.12.0...0.12.1 diff --git a/Cargo.toml b/Cargo.toml index 1a774e904d..29cde04e74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "swagger" -version = "1.0.1" +version = "1.0.2" authors = ["Metaswitch Networks Ltd"] license = "Apache-2.0" description = "A set of common utilities for Rust code generated by swagger-codegen" diff --git a/README.md b/README.md index b418569c2d..591db06604 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A set of common utilities for crates generated by the `rust-server` [swagger-cod # Releasing a new version -2. Run `./release-changelog.sh ` to update the changelog and `Cargo.toml` -3. Commit and push your changes. -4. Wait for a travis build to complete successfully. -5. Run `cargo publish`. +1. Run `./release-changelog.sh ` to update the changelog and `Cargo.toml` +2. Commit and push your changes. +3. Wait for a travis build to complete successfully. +4. Run `cargo publish`. From 1dae52a835a2802c64ded4343e921961eea86863 Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Thu, 9 Aug 2018 13:40:01 +0100 Subject: [PATCH 96/98] Update rustfmt invocation for Rust 1.28.0 --- .travis.yml | 2 +- src/connector.rs | 2 +- src/context.rs | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index ecfdfe4ca8..0a329d411e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,4 +25,4 @@ matrix: before_script: - rustup component add rustfmt-preview script: - - cargo fmt -- --write-mode diff + - cargo fmt -- --check diff --git a/src/connector.rs b/src/connector.rs index 68a8598d23..968803079e 100644 --- a/src/connector.rs +++ b/src/connector.rs @@ -119,4 +119,4 @@ where C: AsRef, { unimplemented!("See issue #43 (https://github.com/Metaswitch/swagger-rs/issues/43)") -} \ No newline at end of file +} diff --git a/src/context.rs b/src/context.rs index f70e93a80e..602fcaa853 100644 --- a/src/context.rs +++ b/src/context.rs @@ -550,8 +550,7 @@ where Future = Box>, >, C: Has> + Has> + Has + Clone + 'static, -{ -} +{} #[cfg(test)] mod context_tests { From 956eea4c7f9fb82387f6717d5b809d6afb0f6aa0 Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Thu, 13 Sep 2018 18:54:12 +0100 Subject: [PATCH 97/98] Update to Rustfmt with Rust 1.29 --- src/connector.rs | 56 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/src/connector.rs b/src/connector.rs index 968803079e..55be444d7f 100644 --- a/src/connector.rs +++ b/src/connector.rs @@ -1,8 +1,24 @@ //! Utility methods for instantiating common connectors for clients. extern crate hyper_tls; -#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +#[cfg( + not( + any( + target_os = "macos", + target_os = "windows", + target_os = "ios" + ) + ) +)] extern crate native_tls; -#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +#[cfg( + not( + any( + target_os = "macos", + target_os = "windows", + target_os = "ios" + ) + ) +)] extern crate openssl; extern crate tokio_core; @@ -22,7 +38,15 @@ pub fn http_connector() -> Box hyper::client::HttpConnector + Sen /// # Arguments /// /// * `ca_certificate` - Path to CA certificate used to authenticate the server -#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +#[cfg( + not( + any( + target_os = "macos", + target_os = "windows", + target_os = "ios" + ) + ) +)] pub fn https_connector( ca_certificate: CA, ) -> Box hyper_tls::HttpsConnector + Send + Sync> @@ -50,7 +74,13 @@ where /// Not currently implemented on Mac OS X, iOS and Windows. /// This function will panic when called. -#[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] +#[cfg( + any( + target_os = "macos", + target_os = "windows", + target_os = "ios" + ) +)] pub fn https_connector( _ca_certificate: CA, ) -> Box hyper_tls::HttpsConnector + Send + Sync> @@ -66,7 +96,15 @@ where /// * `ca_certificate` - Path to CA certificate used to authenticate the server /// * `client_key` - Path to the client private key /// * `client_certificate` - Path to the client's public certificate associated with the private key -#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +#[cfg( + not( + any( + target_os = "macos", + target_os = "windows", + target_os = "ios" + ) + ) +)] pub fn https_mutual_connector( ca_certificate: CA, client_key: K, @@ -107,7 +145,13 @@ where /// Not currently implemented on Mac OS X, iOS and Windows. /// This function will panic when called. -#[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] +#[cfg( + any( + target_os = "macos", + target_os = "windows", + target_os = "ios" + ) +)] pub fn https_mutual_connector( _ca_certificate: CA, _client_key: K, From 2803aa4ca59311049c46f8959b9c5c45d17b373d Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Thu, 13 Sep 2018 18:58:44 +0100 Subject: [PATCH 98/98] Move to a more recent clippy --- .travis.yml | 2 +- src/composites.rs | 11 +++++++++-- src/lib.rs | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0a329d411e..a302cc7efc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ matrix: allow_failures: - rust: nightly include: - - rust: nightly-2018-07-16 + - rust: nightly-2018-09-12 before_script: - rustup component add clippy-preview script: diff --git a/src/composites.rs b/src/composites.rs index 36a2d19540..a32bf9981a 100644 --- a/src/composites.rs +++ b/src/composites.rs @@ -94,8 +94,15 @@ where V: NotFound + 'static, W: 'static; -// Clippy bug? This lint triggers despite having a #[derive(Default)] -#[cfg_attr(feature = "cargo-clippy", allow(new_without_default_derive))] +// Workaround for https://github.com/rust-lang-nursery/rust-clippy/issues/2226 +#[cfg_attr( + feature = "cargo-clippy", + allow( + renamed_and_removed_lints, + new_without_default_derive, + clippy::new_without_default_derive + ) +)] impl CompositeNewService { /// create an empty `CompositeNewService` pub fn new() -> Self { diff --git a/src/lib.rs b/src/lib.rs index c502c3fe28..471811db73 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ //! Support crate for Swagger codegen. - #![warn(missing_docs, missing_debug_implementations)] #![deny(unused_extern_crates)] +#![cfg_attr(feature = "cargo-clippy", feature(tool_lints))] #[cfg(feature = "serdejson")] extern crate serde;