Implement stack for Swagger Context (#612)

This commit is contained in:
Benjamin Gill 2018-07-26 18:48:43 +01:00 committed by William Cheng
parent 7e494e52ab
commit b6fc29050d
10 changed files with 200 additions and 178 deletions

View File

@ -198,7 +198,7 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig {
supportingFiles.add(new SupportingFile("lib.mustache", "src", "lib.rs"));
supportingFiles.add(new SupportingFile("models.mustache", "src", "models.rs"));
supportingFiles.add(new SupportingFile("server-mod.mustache", "src/server", "mod.rs"));
supportingFiles.add(new SupportingFile("server-auth.mustache", "src/server", "auth.rs"));
supportingFiles.add(new SupportingFile("server-context.mustache", "src/server", "context.rs"));
supportingFiles.add(new SupportingFile("client-mod.mustache", "src/client", "mod.rs"));
supportingFiles.add(new SupportingFile("mimetypes.mustache", "src", "mimetypes.rs"));
supportingFiles.add(new SupportingFile("example-server.mustache", "examples", "server.rs"));

View File

@ -19,7 +19,7 @@ chrono = { version = "0.4", features = ["serde"] }
futures = "0.1"
hyper = {version = "0.11", optional = true}
hyper-tls = {version = "0.1.2", optional = true}
swagger = "0.12.1"
swagger = "1.0.1"
# Not required by example server.
#

View File

@ -55,7 +55,7 @@ fn main() {
.get_matches();
let service_fn =
{{{externCrateName}}}::server::auth::NewService::<_, EmptyContext>::new(
{{{externCrateName}}}::server::context::NewAddContext::<_, EmptyContext>::new(
AllowAllAuthenticator::new(
server_lib::NewService::new(),
"cosmo"

View File

@ -8,76 +8,72 @@ use swagger::auth::{Authorization, AuthData, Scopes};
use swagger::{Has, Pop, Push, XSpanIdString};
use Api;
pub struct NewService<T, C>
where
C: Default + Push<XSpanIdString>,
C::Result: Push<Option<AuthData>>,
T: hyper::server::NewService<Request = (Request, <C::Result as Push<Option<AuthData>>>::Result), Response = Response, Error = Error>,
pub struct NewAddContext<T, A>
{
inner: T,
marker: PhantomData<C>,
marker: PhantomData<A>,
}
impl<T, C> NewService<T, C>
impl<T, A, B, C, D> NewAddContext<T, A>
where
C: Default + Push<XSpanIdString>,
C::Result: Push<Option<AuthData>>,
T: hyper::server::NewService<Request = (Request, <C::Result as Push<Option<AuthData>>>::Result), Response = Response, Error = Error> + 'static,
A: Default + Push<XSpanIdString, Result=B>,
B: Push<Option<AuthData>, Result=C>,
C: Push<Option<Authorization>, Result=D>,
T: hyper::server::NewService<Request = (Request, D), Response = Response, Error = Error> + 'static,
{
pub fn new(inner: T) -> NewService<T, C> {
NewService {
pub fn new(inner: T) -> NewAddContext<T, A> {
NewAddContext {
inner,
marker: PhantomData,
}
}
}
impl<T, C> hyper::server::NewService for NewService<T, C>
impl<T, A, B, C, D> hyper::server::NewService for NewAddContext<T, A>
where
C: Default + Push<XSpanIdString>,
C::Result: Push<Option<AuthData>>,
T: hyper::server::NewService<Request = (Request, <C::Result as Push<Option<AuthData>>>::Result), Response = Response, Error = Error> + 'static,
A: Default + Push<XSpanIdString, Result=B>,
B: Push<Option<AuthData>, Result=C>,
C: Push<Option<Authorization>, Result=D>,
T: hyper::server::NewService<Request = (Request, D), Response = Response, Error = Error> + 'static,
{
type Request = Request;
type Response = Response;
type Error = Error;
type Instance = Service<T::Instance, C>;
type Instance = AddContext<T::Instance, A>;
fn new_service(&self) -> Result<Self::Instance, io::Error> {
self.inner.new_service().map(|s| Service::new(s))
self.inner.new_service().map(|s| AddContext::new(s))
}
}
/// Middleware to extract authentication data from request
pub struct Service<T, C>
where
C: Default + Push<XSpanIdString>,
C::Result: Push<Option<AuthData>>,
T: hyper::server::Service<Request = (Request, <C::Result as Push<Option<AuthData>>>::Result), Response = Response, Error = Error>,
pub struct AddContext<T, A>
{
inner: T,
marker: PhantomData<C>,
marker: PhantomData<A>,
}
impl<T, C> Service<T, C>
impl<T, A, B, C, D> AddContext<T, A>
where
C: Default + Push<XSpanIdString>,
C::Result: Push<Option<AuthData>>,
T: hyper::server::Service<Request = (Request, <C::Result as Push<Option<AuthData>>>::Result), Response = Response, Error = Error>,
A: Default + Push<XSpanIdString, Result=B>,
B: Push<Option<AuthData>, Result=C>,
C: Push<Option<Authorization>, Result=D>,
T: hyper::server::Service<Request = (Request, D), Response = Response, Error = Error>,
{
pub fn new(inner: T) -> Service<T, C> {
Service {
pub fn new(inner: T) -> AddContext<T, A> {
AddContext {
inner,
marker: PhantomData,
}
}
}
impl<T, C> hyper::server::Service for Service<T, C>
impl<T, A, B, C, D> hyper::server::Service for AddContext<T, A>
where
C: Default + Push<XSpanIdString>,
C::Result: Push<Option<AuthData>>,
T: hyper::server::Service<Request = (Request, <C::Result as Push<Option<AuthData>>>::Result), Response = Response, Error = Error>,
A: Default + Push<XSpanIdString, Result=B>,
B: Push<Option<AuthData>, Result=C>,
C: Push<Option<Authorization>, Result=D>,
T: hyper::server::Service<Request = (Request, D), Response = Response, Error = Error>,
{
type Request = Request;
type Response = Response;
@ -85,27 +81,29 @@ impl<T, C> hyper::server::Service for Service<T, C>
type Future = T::Future;
fn call(&self, req: Self::Request) -> Self::Future {
let context = C::default().push(XSpanIdString::get_or_generate(&req));
let context = A::default().push(XSpanIdString::get_or_generate(&req));
{{#authMethods}}
{{#isBasic}}
{
use hyper::header::{Authorization, Basic, Bearer};
use hyper::header::{Authorization as HyperAuth, Basic, Bearer};
use std::ops::Deref;
if let Some(basic) = req.headers().get::<Authorization<Basic>>().cloned() {
if let Some(basic) = req.headers().get::<HyperAuth<Basic>>().cloned() {
let auth_data = AuthData::Basic(basic.deref().clone());
let context = context.push(Some(auth_data));
let context = context.push(None::<Authorization>);
return self.inner.call((req, context));
}
}
{{/isBasic}}
{{#isOAuth}}
{
use hyper::header::{Authorization, Basic, Bearer};
use hyper::header::{Authorization as HyperAuth, Basic, Bearer};
use std::ops::Deref;
if let Some(bearer) = req.headers().get::<Authorization<Bearer>>().cloned() {
if let Some(bearer) = req.headers().get::<HyperAuth<Bearer>>().cloned() {
let auth_data = AuthData::Bearer(bearer.deref().clone());
let context = context.push(Some(auth_data));
let context = context.push(None::<Authorization>);
return self.inner.call((req, context));
}
}
@ -117,6 +115,7 @@ impl<T, C> hyper::server::Service for Service<T, C>
if let Some(header) = req.headers().get::<ApiKey{{-index}}>().cloned() {
let auth_data = AuthData::ApiKey(header.0);
let context = context.push(Some(auth_data));
let context = context.push(None::<Authorization>);
return self.inner.call((req, context));
}
}
@ -130,6 +129,7 @@ impl<T, C> hyper::server::Service for Service<T, C>
if let Some(key) = key {
let auth_data = AuthData::ApiKey(key);
let context = context.push(Some(auth_data));
let context = context.push(None::<Authorization>);
return self.inner.call((req, context));
}
}
@ -137,7 +137,8 @@ impl<T, C> hyper::server::Service for Service<T, C>
{{/isApiKey}}
{{/authMethods}}
let context = context.push(None);
let context = context.push(None::<AuthData>);
let context = context.push(None::<Authorization>);
return self.inner.call((req, context));
}
}

View File

@ -42,7 +42,7 @@ use {Api{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}},
#[allow(unused_imports)]
use models;
pub mod auth;
pub mod context;
header! { (Warning, "Warning") => [String] }
@ -370,3 +370,13 @@ where
}
}
}
impl<T, C> Clone for Service<T, C>
{
fn clone(&self) -> Self {
Service {
api_impl: self.api_impl.clone(),
marker: self.marker.clone(),
}
}
}

View File

@ -17,7 +17,7 @@ chrono = { version = "0.4", features = ["serde"] }
futures = "0.1"
hyper = {version = "0.11", optional = true}
hyper-tls = {version = "0.1.2", optional = true}
swagger = "0.12.1"
swagger = "1.0.1"
# Not required by example server.
#

View File

@ -55,7 +55,7 @@ fn main() {
.get_matches();
let service_fn =
petstore_api::server::auth::NewService::<_, EmptyContext>::new(
petstore_api::server::context::NewAddContext::<_, EmptyContext>::new(
AllowAllAuthenticator::new(
server_lib::NewService::new(),
"cosmo"

View File

@ -1,131 +0,0 @@
use std::io;
use std::marker::PhantomData;
use std::default::Default;
use hyper;
use hyper::{Request, Response, Error, StatusCode};
use server::url::form_urlencoded;
use swagger::auth::{Authorization, AuthData, Scopes};
use swagger::{Has, Pop, Push, XSpanIdString};
use Api;
pub struct NewService<T, C>
where
C: Default + Push<XSpanIdString>,
C::Result: Push<Option<AuthData>>,
T: hyper::server::NewService<Request = (Request, <C::Result as Push<Option<AuthData>>>::Result), Response = Response, Error = Error>,
{
inner: T,
marker: PhantomData<C>,
}
impl<T, C> NewService<T, C>
where
C: Default + Push<XSpanIdString>,
C::Result: Push<Option<AuthData>>,
T: hyper::server::NewService<Request = (Request, <C::Result as Push<Option<AuthData>>>::Result), Response = Response, Error = Error> + 'static,
{
pub fn new(inner: T) -> NewService<T, C> {
NewService {
inner,
marker: PhantomData,
}
}
}
impl<T, C> hyper::server::NewService for NewService<T, C>
where
C: Default + Push<XSpanIdString>,
C::Result: Push<Option<AuthData>>,
T: hyper::server::NewService<Request = (Request, <C::Result as Push<Option<AuthData>>>::Result), Response = Response, Error = Error> + 'static,
{
type Request = Request;
type Response = Response;
type Error = Error;
type Instance = Service<T::Instance, C>;
fn new_service(&self) -> Result<Self::Instance, io::Error> {
self.inner.new_service().map(|s| Service::new(s))
}
}
/// Middleware to extract authentication data from request
pub struct Service<T, C>
where
C: Default + Push<XSpanIdString>,
C::Result: Push<Option<AuthData>>,
T: hyper::server::Service<Request = (Request, <C::Result as Push<Option<AuthData>>>::Result), Response = Response, Error = Error>,
{
inner: T,
marker: PhantomData<C>,
}
impl<T, C> Service<T, C>
where
C: Default + Push<XSpanIdString>,
C::Result: Push<Option<AuthData>>,
T: hyper::server::Service<Request = (Request, <C::Result as Push<Option<AuthData>>>::Result), Response = Response, Error = Error>,
{
pub fn new(inner: T) -> Service<T, C> {
Service {
inner,
marker: PhantomData,
}
}
}
impl<T, C> hyper::server::Service for Service<T, C>
where
C: Default + Push<XSpanIdString>,
C::Result: Push<Option<AuthData>>,
T: hyper::server::Service<Request = (Request, <C::Result as Push<Option<AuthData>>>::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 context = C::default().push(XSpanIdString::get_or_generate(&req));
{
header! { (ApiKey1, "api_key") => [String] }
if let Some(header) = req.headers().get::<ApiKey1>().cloned() {
let auth_data = AuthData::ApiKey(header.0);
let context = context.push(Some(auth_data));
return self.inner.call((req, context));
}
}
{
let key = form_urlencoded::parse(req.query().unwrap_or_default().as_bytes())
.filter(|e| e.0 == "api_key_query")
.map(|e| e.1.clone().into_owned())
.nth(0);
if let Some(key) = key {
let auth_data = AuthData::ApiKey(key);
let context = context.push(Some(auth_data));
return self.inner.call((req, context));
}
}
{
use hyper::header::{Authorization, Basic, Bearer};
use std::ops::Deref;
if let Some(basic) = req.headers().get::<Authorization<Basic>>().cloned() {
let auth_data = AuthData::Basic(basic.deref().clone());
let context = context.push(Some(auth_data));
return self.inner.call((req, context));
}
}
{
use hyper::header::{Authorization, Basic, Bearer};
use std::ops::Deref;
if let Some(bearer) = req.headers().get::<Authorization<Bearer>>().cloned() {
let auth_data = AuthData::Bearer(bearer.deref().clone());
let context = context.push(Some(auth_data));
return self.inner.call((req, context));
}
}
let context = context.push(None);
return self.inner.call((req, context));
}
}

View File

@ -0,0 +1,132 @@
use std::io;
use std::marker::PhantomData;
use std::default::Default;
use hyper;
use hyper::{Request, Response, Error, StatusCode};
use server::url::form_urlencoded;
use swagger::auth::{Authorization, AuthData, Scopes};
use swagger::{Has, Pop, Push, XSpanIdString};
use Api;
pub struct NewAddContext<T, A>
{
inner: T,
marker: PhantomData<A>,
}
impl<T, A, B, C, D> NewAddContext<T, A>
where
A: Default + Push<XSpanIdString, Result=B>,
B: Push<Option<AuthData>, Result=C>,
C: Push<Option<Authorization>, Result=D>,
T: hyper::server::NewService<Request = (Request, D), Response = Response, Error = Error> + 'static,
{
pub fn new(inner: T) -> NewAddContext<T, A> {
NewAddContext {
inner,
marker: PhantomData,
}
}
}
impl<T, A, B, C, D> hyper::server::NewService for NewAddContext<T, A>
where
A: Default + Push<XSpanIdString, Result=B>,
B: Push<Option<AuthData>, Result=C>,
C: Push<Option<Authorization>, Result=D>,
T: hyper::server::NewService<Request = (Request, D), Response = Response, Error = Error> + 'static,
{
type Request = Request;
type Response = Response;
type Error = Error;
type Instance = AddContext<T::Instance, A>;
fn new_service(&self) -> Result<Self::Instance, io::Error> {
self.inner.new_service().map(|s| AddContext::new(s))
}
}
/// Middleware to extract authentication data from request
pub struct AddContext<T, A>
{
inner: T,
marker: PhantomData<A>,
}
impl<T, A, B, C, D> AddContext<T, A>
where
A: Default + Push<XSpanIdString, Result=B>,
B: Push<Option<AuthData>, Result=C>,
C: Push<Option<Authorization>, Result=D>,
T: hyper::server::Service<Request = (Request, D), Response = Response, Error = Error>,
{
pub fn new(inner: T) -> AddContext<T, A> {
AddContext {
inner,
marker: PhantomData,
}
}
}
impl<T, A, B, C, D> hyper::server::Service for AddContext<T, A>
where
A: Default + Push<XSpanIdString, Result=B>,
B: Push<Option<AuthData>, Result=C>,
C: Push<Option<Authorization>, Result=D>,
T: hyper::server::Service<Request = (Request, D), 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 context = A::default().push(XSpanIdString::get_or_generate(&req));
{
header! { (ApiKey1, "api_key") => [String] }
if let Some(header) = req.headers().get::<ApiKey1>().cloned() {
let auth_data = AuthData::ApiKey(header.0);
let context = context.push(Some(auth_data));
let context = context.push(None::<Authorization>);
return self.inner.call((req, context));
}
}
{
let key = form_urlencoded::parse(req.query().unwrap_or_default().as_bytes())
.filter(|e| e.0 == "api_key_query")
.map(|e| e.1.clone().into_owned())
.nth(0);
if let Some(key) = key {
let auth_data = AuthData::ApiKey(key);
let context = context.push(Some(auth_data));
let context = context.push(None::<Authorization>);
return self.inner.call((req, context));
}
}
{
use hyper::header::{Authorization as HyperAuth, Basic, Bearer};
use std::ops::Deref;
if let Some(basic) = req.headers().get::<HyperAuth<Basic>>().cloned() {
let auth_data = AuthData::Basic(basic.deref().clone());
let context = context.push(Some(auth_data));
let context = context.push(None::<Authorization>);
return self.inner.call((req, context));
}
}
{
use hyper::header::{Authorization as HyperAuth, Basic, Bearer};
use std::ops::Deref;
if let Some(bearer) = req.headers().get::<HyperAuth<Bearer>>().cloned() {
let auth_data = AuthData::Bearer(bearer.deref().clone());
let context = context.push(Some(auth_data));
let context = context.push(None::<Authorization>);
return self.inner.call((req, context));
}
}
let context = context.push(None::<AuthData>);
let context = context.push(None::<Authorization>);
return self.inner.call((req, context));
}
}

View File

@ -73,7 +73,7 @@ use {Api,
#[allow(unused_imports)]
use models;
pub mod auth;
pub mod context;
header! { (Warning, "Warning") => [String] }
@ -2939,3 +2939,13 @@ where
}
}
}
impl<T, C> Clone for Service<T, C>
{
fn clone(&self) -> Self {
Service {
api_impl: self.api_impl.clone(),
marker: self.marker.clone(),
}
}
}