[Rust Server] Hyper 0.12 Support (#4519)

[Rust Server] Hyper 0.12 Support

- Hyper upgraded to Hyper 0.12.
  - NewService becomes MakeService
  - Request on MakeContext is not parameterised - instead, ReqBody, and ResBody are parameterized, and must implement hyper::body::Payload.
  - This means that our existing tuples (i.e. (Body, Context)) don't work - instead we have a type ContextualPayload, which implements Payload, and derefs to an inner payload (the body), and contains a context.
  - This is handled by the work done in Metaswitch/swagger-rs#63 but has some fall out here as well.

- tokio-proto/tokio-core is no longer supported, and hyper instead depends on tokio.

- Hyper depends on mime 0.3, but multipart depends on mime 0.2, so we now import both

- Hyper TLS 0.2 and native-tls 0.1

- Use Swagger Support library 3.x

- Futures are now Send. This forces ApiImpl to be need to Send as a result, and all forces Clients to be Send + Sync.
This commit is contained in:
Richard Whitehouse 2020-01-05 14:48:12 +00:00 committed by GitHub
parent e9d616bd02
commit e9459125bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
64 changed files with 9245 additions and 5705 deletions

View File

@ -26,6 +26,7 @@ public class CodegenParameter implements IJsonSchemaValidationProperties {
public String baseName, paramName, dataType, datatypeWithEnum, dataFormat,
collectionFormat, description, unescapedDescription, baseType, defaultValue, enumName, style;
public String nameInLowerCase; // property name in lower case
public String example; // example value (x-example)
public String jsonSchema;
public boolean isString, isNumeric, isInteger, isLong, isNumber, isFloat, isDouble, isByteArray, isBinary,

View File

@ -91,6 +91,7 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti
public boolean hasValidation; // true if pattern, maximum, etc are set (only used in the mustache template)
public boolean isInherited;
public String discriminatorValue;
public String nameInLowerCase; // property name in lower case
public String nameInCamelCase; // property name in camel case
public String nameInSnakeCase; // property name in upper snake case
// enum name based on the property name, usually use as a prefix (e.g. VAR_NAME) for enum name (e.g. VAR_NAME_VALUE1)
@ -393,6 +394,14 @@ public class CodegenProperty implements Cloneable, IJsonSchemaValidationProperti
this.vendorExtensions = vendorExtensions;
}
public String getNameInLowerCase() {
return nameInLowerCase;
}
public void setNameInLowerCase(String nameInLowerCase) {
this.nameInLowerCase = nameInLowerCase;
}
public String getNameInCamelCase() {
return nameInCamelCase;
}

View File

@ -205,7 +205,6 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig {
supportingFiles.add(new SupportingFile("example-server.mustache", "examples", "server.rs"));
supportingFiles.add(new SupportingFile("example-client.mustache", "examples", "client.rs"));
supportingFiles.add(new SupportingFile("example-server_lib.mustache", "examples/server_lib", "mod.rs"));
supportingFiles.add(new SupportingFile("example-server_server.mustache", "examples/server_lib", "server.rs"));
supportingFiles.add(new SupportingFile("example-ca.pem", "examples", "ca.pem"));
supportingFiles.add(new SupportingFile("example-server-chain.pem", "examples", "server-chain.pem"));
supportingFiles.add(new SupportingFile("example-server-key.pem", "examples", "server-key.pem"));
@ -564,7 +563,7 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig {
op.vendorExtensions.put("path", op.path.replace("{", ":").replace("}", ""));
op.vendorExtensions.put("PATH_ID", pathId);
op.vendorExtensions.put("hasPathParams", !op.pathParams.isEmpty());
op.vendorExtensions.put("HttpMethod", Character.toUpperCase(op.httpMethod.charAt(0)) + op.httpMethod.substring(1).toLowerCase(Locale.ROOT));
op.vendorExtensions.put("HttpMethod", op.httpMethod.toUpperCase(Locale.ROOT));
for (CodegenParameter param : op.allParams) {
processParam(param, op);
}
@ -757,13 +756,20 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig {
additionalProperties.put("apiUsesUuid", true);
}
header.nameInCamelCase = toModelName(header.baseName);
header.nameInLowerCase = header.baseName.toLowerCase(Locale.ROOT);
}
}
for (CodegenParameter header : op.headerParams) {
header.nameInLowerCase = header.baseName.toLowerCase(Locale.ROOT);
}
for (CodegenProperty header : op.responseHeaders) {
if (header.dataType.equals(uuidType)) {
additionalProperties.put("apiUsesUuid", true);
}
header.nameInCamelCase = toModelName(header.baseName);
header.nameInLowerCase = header.baseName.toLowerCase(Locale.ROOT);
}
return op;
@ -829,11 +835,16 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig {
processParam(param, op);
}
for (CodegenParameter header : op.headerParams) {
header.nameInLowerCase = header.baseName.toLowerCase(Locale.ROOT);
}
for (CodegenProperty header : op.responseHeaders) {
if (header.dataType.equals(uuidType)) {
additionalProperties.put("apiUsesUuid", true);
}
header.nameInCamelCase = toModelName(header.baseName);
header.nameInLowerCase = header.baseName.toLowerCase(Locale.ROOT);
}
if (op.authMethods != null) {
@ -1036,6 +1047,10 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig {
if (xmlName != null) {
prop.vendorExtensions.put("itemXmlName", xmlName);
}
if (prop.dataType.equals(uuidType)) {
additionalProperties.put("apiUsesUuid", true);
}
}
}
@ -1242,6 +1257,10 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig {
// get them recognised correctly.
cm.isAlias = false;
cm.dataType = typeMapping.get(cm.dataType);
if (uuidType.equals(cm.dataType)) {
additionalProperties.put("apiUsesUuid", true);
}
}
cm.vendorExtensions.put("isString", "String".equals(cm.dataType));

View File

@ -9,52 +9,70 @@ license = "Unlicense"
[features]
default = ["client", "server"]
client = [{{#usesUrlEncodedForm}}"serde_urlencoded", {{/usesUrlEncodedForm}}"serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url"]
server = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url"]
client = [
{{#apiUsesMultipart}}
"multipart", "multipart/client", "swagger/multipart",
{{/apiUsesMultipart}}
{{#usesUrlEncodedForm}}
"serde_urlencoded",
{{/usesUrlEncodedForm}}
"serde_json", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio", "url"
]
server = [
{{#apiUsesMultipart}}
"multipart", "multipart/server",
{{/apiUsesMultipart}}
"serde_json", "serde_ignored", "hyper", "native-tls", "openssl", "tokio", "tokio-tls", "regex", "percent-encoding", "url", "lazy_static"
]
conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"]
[dependencies]
# Common
chrono = { version = "0.4", features = ["serde"] }
futures = "0.1"
swagger = "2"
lazy_static = "1.4"
swagger = "3.0"
log = "0.3.0"
mime = "0.2.6"
multipart = "0.13.3"
mime = "0.3"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
# Crates included if required by the API definition
{{#apiUsesUuid}}
uuid = {version = "0.5", features = ["serde", "v4"]}
{{/apiUsesUuid}}
{{#usesXml}}
# TODO: this should be updated to point at the official crate once
# https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream
serde-xml-rs = {git = "git://github.com/Metaswitch/serde-xml-rs.git" , branch = "master"}
{{/usesXml}}
{{#apiUsesMultipart}}
mime_0_2 = { package = "mime", version = "0.2.6" }
multipart = { version = "0.16", default-features = false, optional = true }
{{/apiUsesMultipart}}
{{#apiUsesUuid}}
uuid = {version = "0.7", features = ["serde", "v4"]}
{{/apiUsesUuid}}
# Common between server and client features
hyper = {version = "0.11", optional = true}
hyper-tls = {version = "0.1.2", optional = true}
hyper = {version = "0.12", optional = true}
hyper-tls = {version = "0.2.1", optional = true}
native-tls = {version = "0.1.4", optional = true}
openssl = {version = "0.9.14", optional = true}
serde_json = {version = "1.0", optional = true}
serde_ignored = {version = "0.0.4", optional = true}
tokio-core = {version = "0.1.6", optional = true}
tokio = {version = "0.1.17", optional = true}
url = {version = "1.5", optional = true}
# Client-specific
{{#usesUrlEncodedForm}}serde_urlencoded = {version = "0.5.1", optional = true}{{/usesUrlEncodedForm}}
{{#usesUrlEncodedForm}}
serde_urlencoded = {version = "0.5.1", optional = true}
{{/usesUrlEncodedForm}}
# Server-specific
lazy_static = { version = "1.4", optional = true }
percent-encoding = {version = "1.0.0", optional = true}
regex = {version = "0.2", optional = true}
tokio-proto = {version = "0.1.1", optional = true}
tokio-tls = {version = "0.1.3", optional = true, features = ["tokio-proto"]}
tokio-tls = {version = "0.1.3", optional = true}
# Other optional crates
# Conversion
frunk = { version = "0.3.0", optional = true }
frunk_derives = { version = "0.3.0", optional = true }
frunk_core = { version = "0.3.0", optional = true }

View File

@ -1,30 +1,18 @@
#![allow(unused_extern_crates)]
extern crate tokio_core;
extern crate native_tls;
extern crate hyper_tls;
extern crate openssl;
extern crate mime;
extern crate chrono;
extern crate url;
{{#usesUrlEncodedForm}}
extern crate serde_urlencoded;
{{/usesUrlEncodedForm}}
{{#apiUsesMultipart}}
extern crate multipart;
{{/apiUsesMultipart}}
{{#apiUsesUuid}}
extern crate uuid;
{{/apiUsesUuid}}
use hyper;
use hyper::header::{Headers, ContentType};
use hyper::Uri;
use self::url::percent_encoding::{utf8_percent_encode, PATH_SEGMENT_ENCODE_SET, QUERY_ENCODE_SET};
use hyper::client::HttpConnector;
use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE};
use hyper::{Body, Uri, Response};
use hyper_tls::HttpsConnector;
use url::form_urlencoded;
use url::percent_encoding::{utf8_percent_encode, PATH_SEGMENT_ENCODE_SET, QUERY_ENCODE_SET};
use futures;
use futures::{Future, Stream};
use futures::{future, stream};
use self::tokio_core::reactor::Handle;
use serde_json;
use std::borrow::Cow;
#[allow(unused_imports)]
use std::collections::{HashMap, BTreeMap};
use std::io::{Read, Error, ErrorKind};
use std::error;
use std::fmt;
@ -33,27 +21,27 @@ use std::sync::Arc;
use std::str;
use std::str::FromStr;
use std::string::ToString;
use swagger;
use swagger::{ApiError, XSpanIdString, Has, AuthData};
use swagger::client::Service;
{{#apiUsesMultipart}}
use hyper::mime::Mime;
use std::io::Cursor;
use client::multipart::client::lazy::Multipart;
use mime::Mime;
use std::io::Cursor;
use multipart::client::lazy::Multipart;
{{/apiUsesMultipart}}
use mimetypes;
use serde_json;
{{#apiUsesUuid}}
use uuid;
{{/apiUsesUuid}}
{{#usesXml}}
use serde_xml_rs;
{{/usesXml}}
#[allow(unused_imports)]
use std::collections::{HashMap, BTreeMap};
#[allow(unused_imports)]
use swagger;
use swagger::{ApiError, XSpanId, XSpanIdString, Has, AuthData};
use {Api{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}},
{{{operationId}}}Response{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
};
use mimetypes;
use models;
define_encode_set! {
@ -69,7 +57,7 @@ fn into_base_path(input: &str, correct_scheme: Option<&'static str>) -> Result<S
// First convert to Uri, since a base path is a subset of Uri.
let uri = Uri::from_str(input)?;
let scheme = uri.scheme().ok_or(ClientInitError::InvalidScheme)?;
let scheme = uri.scheme_part().ok_or(ClientInitError::InvalidScheme)?;
// Check the scheme if necessary
if let Some(correct_scheme) = correct_scheme {
@ -79,104 +67,36 @@ fn into_base_path(input: &str, correct_scheme: Option<&'static str>) -> Result<S
}
let host = uri.host().ok_or_else(|| ClientInitError::MissingHost)?;
let port = uri.port().map(|x| format!(":{}", x)).unwrap_or_default();
let port = uri.port_part().map(|x| format!(":{}", x)).unwrap_or_default();
Ok(format!("{}://{}{}", scheme, host, port))
}
/// A client that implements the API by making HTTP calls out to a server.
pub struct Client<F> where
F: Future<Item=hyper::Response, Error=hyper::Error> + 'static {
client_service: Arc<Box<dyn hyper::client::Service<Request=hyper::Request<hyper::Body>, Response=hyper::Response, Error=hyper::Error, Future=F>>>,
pub struct Client<F>
{
client_service: Arc<Box<dyn Service<ReqBody=Body, Future=F> + Send + Sync>>,
base_path: String,
}
impl<F> fmt::Debug for Client<F> where
F: Future<Item=hyper::Response, Error=hyper::Error> + 'static {
impl<F> fmt::Debug for Client<F>
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Client {{ base_path: {} }}", self.base_path)
}
}
impl<F> Clone for Client<F> where
F: Future<Item=hyper::Response, Error=hyper::Error> + 'static {
impl<F> Clone for Client<F>
{
fn clone(&self) -> Self {
Client {
client_service: self.client_service.clone(),
base_path: self.base_path.clone()
base_path: self.base_path.clone(),
}
}
}
impl Client<hyper::client::FutureResponse> {
/// Create an HTTP client.
///
/// # Arguments
/// * `handle` - tokio reactor handle to use for execution
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
pub fn try_new_http(handle: Handle, base_path: &str) -> Result<Client<hyper::client::FutureResponse>, ClientInitError> {
let http_connector = swagger::http_connector();
Self::try_new_with_connector::<hyper::client::HttpConnector>(
handle,
base_path,
Some("http"),
http_connector,
)
}
/// Create a client with a TLS connection to the server.
///
/// # Arguments
/// * `handle` - tokio reactor handle to use for execution
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
/// * `ca_certificate` - Path to CA certificate used to authenticate the server
pub fn try_new_https<CA>(
handle: Handle,
base_path: &str,
ca_certificate: CA,
) -> Result<Client<hyper::client::FutureResponse>, ClientInitError>
where
CA: AsRef<Path>,
{
let https_connector = swagger::https_connector(ca_certificate);
Self::try_new_with_connector::<hyper_tls::HttpsConnector<hyper::client::HttpConnector>>(
handle,
base_path,
Some("https"),
https_connector,
)
}
/// Create a client with a mutually authenticated TLS connection to the server.
///
/// # Arguments
/// * `handle` - tokio reactor handle to use for execution
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
/// * `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
pub fn try_new_https_mutual<CA, K, C>(
handle: Handle,
base_path: &str,
ca_certificate: CA,
client_key: K,
client_certificate: C,
) -> Result<Client<hyper::client::FutureResponse>, ClientInitError>
where
CA: AsRef<Path>,
K: AsRef<Path>,
C: AsRef<Path>,
{
let https_connector =
swagger::https_mutual_connector(ca_certificate, client_key, client_certificate);
Self::try_new_with_connector::<hyper_tls::HttpsConnector<hyper::client::HttpConnector>>(
handle,
base_path,
Some("https"),
https_connector,
)
}
impl Client<hyper::client::ResponseFuture>
{
/// Create a client with a custom implementation of hyper::client::Connect.
///
/// Intended for use with custom implementations of connect for e.g. protocol logging
@ -189,23 +109,21 @@ impl Client<hyper::client::FutureResponse> {
///
/// # Arguments
///
/// * `handle` - tokio reactor handle to use for execution
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
/// * `protocol` - Which protocol to use when constructing the request url, e.g. `Some("http")`
/// * `connector_fn` - Function which returns an implementation of `hyper::client::Connect`
pub fn try_new_with_connector<C>(
handle: Handle,
base_path: &str,
protocol: Option<&'static str>,
connector_fn: Box<dyn Fn(&Handle) -> C + Send + Sync>,
) -> Result<Client<hyper::client::FutureResponse>, ClientInitError>
where
C: hyper::client::Connect + hyper::client::Service,
connector_fn: Box<dyn Fn() -> C + Send + Sync>,
) -> Result<Self, ClientInitError> where
C: hyper::client::connect::Connect + 'static,
C::Transport: 'static,
C::Future: 'static,
{
let connector = connector_fn(&handle);
let client_service = Box::new(hyper::Client::configure().connector(connector).build(
&handle,
));
let connector = connector_fn();
let client_service = Box::new(hyper::client::Client::builder().build(connector));
Ok(Client {
client_service: Arc::new(client_service),
@ -213,40 +131,67 @@ impl Client<hyper::client::FutureResponse> {
})
}
/// Constructor for creating a `Client` by passing in a pre-made `hyper` client.
/// Create an HTTP client.
///
/// One should avoid relying on this function if possible, since it adds a dependency on the underlying transport
/// implementation, which it would be better to abstract away. Therefore, using this function may lead to a loss of
/// code generality, which may make it harder to move the application to a serverless environment, for example.
/// # Arguments
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
pub fn try_new_http(
base_path: &str,
) -> Result<Self, ClientInitError> {
let http_connector = swagger::http_connector();
Self::try_new_with_connector(base_path, Some("http"), http_connector)
}
/// Create a client with a TLS connection to the server.
///
/// The reason for this function's existence is to support legacy test code, which did mocking at the hyper layer.
/// This is not a recommended way to write new tests. If other reasons are found for using this function, they
/// should be mentioned here.
#[deprecated(note="Use try_new_with_client_service instead")]
pub fn try_new_with_hyper_client(
hyper_client: Arc<Box<dyn hyper::client::Service<Request=hyper::Request<hyper::Body>, Response=hyper::Response, Error=hyper::Error, Future=hyper::client::FutureResponse>>>,
handle: Handle,
base_path: &str
) -> Result<Client<hyper::client::FutureResponse>, ClientInitError>
/// # Arguments
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
/// * `ca_certificate` - Path to CA certificate used to authenticate the server
pub fn try_new_https<CA>(
base_path: &str,
ca_certificate: CA,
) -> Result<Self, ClientInitError>
where
CA: AsRef<Path>,
{
Ok(Client {
client_service: hyper_client,
base_path: into_base_path(base_path, None)?,
})
let https_connector = swagger::https_connector(ca_certificate);
Self::try_new_with_connector(base_path, Some("https"), https_connector)
}
/// Create a client with a mutually authenticated TLS connection to the server.
///
/// # Arguments
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
/// * `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
pub fn try_new_https_mutual<CA, K, D>(
base_path: &str,
ca_certificate: CA,
client_key: K,
client_certificate: D,
) -> Result<Self, ClientInitError>
where
CA: AsRef<Path>,
K: AsRef<Path>,
D: AsRef<Path>,
{
let https_connector =
swagger::https_mutual_connector(ca_certificate, client_key, client_certificate);
Self::try_new_with_connector(base_path, Some("https"), https_connector)
}
}
impl<F> Client<F> where
F: Future<Item=hyper::Response, Error=hyper::Error> + 'static
impl<F> Client<F>
{
/// Constructor for creating a `Client` by passing in a pre-made `hyper` client Service.
/// Constructor for creating a `Client` by passing in a pre-made `swagger::client::Service`
///
/// This allows adding custom wrappers around the underlying transport, for example for logging.
pub fn try_new_with_client_service(client_service: Arc<Box<dyn hyper::client::Service<Request=hyper::Request<hyper::Body>, Response=hyper::Response, Error=hyper::Error, Future=F>>>,
handle: Handle,
base_path: &str)
-> Result<Client<F>, ClientInitError>
{
pub fn try_new_with_client_service(
client_service: Arc<Box<dyn Service<ReqBody=Body, Future=F> + Send + Sync>>,
base_path: &str,
) -> Result<Self, ClientInitError> {
Ok(Client {
client_service: client_service,
base_path: into_base_path(base_path, None)?,
@ -254,26 +199,39 @@ impl<F> Client<F> where
}
}
impl<F, C> Api<C> for Client<F> where
F: Future<Item=hyper::Response, Error=hyper::Error> + 'static,
C: Has<XSpanIdString> {{#hasAuthMethods}}+ Has<Option<AuthData>>{{/hasAuthMethods}}{
impl<C, F> Api<C> for Client<F> where
C: Has<XSpanIdString> {{#hasAuthMethods}}+ Has<Option<AuthData>>{{/hasAuthMethods}},
F: Future<Item=Response<Body>, Error=hyper::Error> + Send + 'static
{
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}(&self{{#allParams}}, param_{{{paramName}}}: {{^required}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{/required}}{{/allParams}}, context: &C) -> Box<dyn Future<Item={{{operationId}}}Response, Error=ApiError>> {
fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}(&self{{#allParams}}, param_{{{paramName}}}: {{^required}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{/required}}{{/allParams}}, context: &C) -> Box<dyn Future<Item={{{operationId}}}Response, Error=ApiError> + Send> {
let mut uri = format!(
"{}{{{basePathWithoutHost}}}{{path}}",
self.base_path{{#pathParams}}, {{{baseName}}}=utf8_percent_encode(&param_{{{paramName}}}.to_string(), ID_ENCODE_SET){{/pathParams}}
);
let mut query_string = self::url::form_urlencoded::Serializer::new("".to_owned());
{{#queryParams}}{{#required}} query_string.append_pair("{{{baseName}}}", &param_{{{paramName}}}{{#isListContainer}}.join(","){{/isListContainer}}{{^isListContainer}}.to_string(){{/isListContainer}});{{/required}}
{{^required}} if let Some({{{paramName}}}) = param_{{{paramName}}} {
query_string.append_pair("{{{baseName}}}", &{{{paramName}}}{{#isListContainer}}.join(","){{/isListContainer}}{{^isListContainer}}.to_string(){{/isListContainer}});
}{{/required}}{{/queryParams}}
{{#authMethods}}{{#isApiKey}}{{#isKeyInQuery}} if let Some(auth_data) = (context as &dyn Has<Option<AuthData>>).get().as_ref() {
// Query parameters
let mut query_string = url::form_urlencoded::Serializer::new("".to_owned());
{{#queryParams}}
{{^required}}
if let Some(param_{{{paramName}}}) = param_{{{paramName}}} {
{{/required}}
query_string.append_pair("{{{baseName}}}", &param_{{{paramName}}}{{#isListContainer}}.join(","){{/isListContainer}}{{^isListContainer}}.to_string(){{/isListContainer}});
{{^required}}
}
{{/required}}
{{/queryParams}}
{{#authMethods}}
{{#isApiKey}}
{{#isKeyInQuery}}
if let Some(auth_data) = (context as &dyn Has<Option<AuthData>>).get().as_ref() {
if let AuthData::ApiKey(ref api_key) = *auth_data {
query_string.append_pair("{{keyParamName}}", api_key);
}
}{{/isKeyInQuery}}{{/isApiKey}}{{/authMethods}}
}
{{/isKeyInQuery}}
{{/isApiKey}}
{{/authMethods}}
let query_string_str = query_string.finish();
if !query_string_str.is_empty() {
uri += "?";
@ -282,10 +240,16 @@ impl<F, C> Api<C> for Client<F> where
let uri = match Uri::from_str(&uri) {
Ok(uri) => uri,
Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to build URI: {}", err))))),
Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))),
};
let mut request = hyper::Request::new(hyper::Method::{{#vendorExtensions}}{{{HttpMethod}}}{{/vendorExtensions}}, uri);
let mut request = match hyper::Request::builder()
.method("{{{vendorExtensions.HttpMethod}}}")
.uri(uri)
.body(Body::empty()) {
Ok(req) => req,
Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e))))
};
{{#vendorExtensions}}
{{#consumesMultipart}}
@ -301,56 +265,54 @@ impl<F, C> Api<C> for Client<F> where
let {{{paramName}}}_str = match serde_json::to_string(&param_{{{paramName}}}) {
Ok(str) => str,
Err(e) => return Box::new(futures::done(Err(ApiError(format!("Unable to parse {{{paramName}}} to string: {}", e))))),
Err(e) => return Box::new(future::err(ApiError(format!("Unable to parse {{{paramName}}} to string: {}", e)))),
};
let {{{paramName}}}_vec = {{{paramName}}}_str.as_bytes().to_vec();
let {{{paramName}}}_mime = mime::Mime::from_str("application/json").expect("impossible to fail to parse");
let {{{paramName}}}_mime = mime_0_2::Mime::from_str("application/json").expect("impossible to fail to parse");
let {{{paramName}}}_cursor = Cursor::new({{{paramName}}}_vec);
multipart.add_stream("{{{paramName}}}", {{{paramName}}}_cursor, None as Option<&str>, Some({{{paramName}}}_mime));
{{/jsonSchema}}
{{/isByteArray}}
{{#isByteArray}}
let {{{paramName}}}_vec = param_{{{paramName}}}.to_vec();
let {{{paramName}}}_mime = match mime::Mime::from_str("application/octet-stream") {
let {{{paramName}}}_mime = match mime_0_2::Mime::from_str("application/octet-stream") {
Ok(mime) => mime,
Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to get mime type: {:?}", err))))),
Err(err) => return Box::new(future::err(ApiError(format!("Unable to get mime type: {:?}", err)))),
};
let {{{paramName}}}_cursor = Cursor::new({{{paramName}}}_vec);
let filename = None as Option<&str> ;
multipart.add_stream("{{{paramName}}}", {{{paramName}}}_cursor, filename, Some({{{paramName}}}_mime));
multipart.add_stream("{{{paramName}}}", {{{paramName}}}_cursor, filename, Some({{{paramName}}}_mime));
{{/isByteArray}}
{{#-last}}
{{/-last}}
{{/formParams}}
{{/vendorExtensions}}
let mut fields = match multipart.prepare() {
Ok(fields) => fields,
Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to build request: {}", err))))),
Err(err) => return Box::new(future::err(ApiError(format!("Unable to build request: {}", err)))),
};
let mut body_string = String::new();
fields.to_body().read_to_string(&mut body_string).unwrap();
match fields.read_to_string(&mut body_string) {
Ok(_) => (),
Err(err) => return Box::new(future::err(ApiError(format!("Unable to build body: {}", err)))),
}
let boundary = fields.boundary();
let multipart_header = match Mime::from_str(&format!("multipart/form-data;boundary={}", boundary)) {
Ok(multipart_header) => multipart_header,
Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to build multipart header: {:?}", err))))),
};
request.set_body(body_string.into_bytes());
request.headers_mut().set(ContentType(multipart_header));
let multipart_header = format!("multipart/form-data;boundary={}", boundary);
*request.body_mut() = Body::from(body_string);
request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(&multipart_header) {
Ok(h) => h,
Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", multipart_header, e))))
});
{{/consumesMultipart}}
{{/vendorExtensions}}
{{#vendorExtensions}}
@ -365,8 +327,12 @@ impl<F, C> Api<C> for Client<F> where
];
let body = serde_urlencoded::to_string(params).expect("impossible to fail to serialize");
request.headers_mut().set(ContentType(mimetypes::requests::{{#vendorExtensions}}{{{uppercase_operation_id}}}{{/vendorExtensions}}.clone()));
request.set_body(body.into_bytes());
let header = &mimetypes::requests::{{#vendorExtensions}}{{{uppercase_operation_id}}}{{/vendorExtensions}};
request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) {
Ok(h) => h,
Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e))))
});
*request.body_mut() = Body::from(body.into_bytes());
{{/-last}}
{{/formParams}}
{{/vendorExtensions}}
@ -403,87 +369,124 @@ impl<F, C> Api<C> for Client<F> where
{{/required}}
{{/vendorExtensions}}
{{^required}}
if let Some(body) = body {
{{/required}}
request.set_body(body);
{{^required}}
{{/required}}
*request.body_mut() = Body::from(body);
{{^required}}
}
{{/required}}
{{/required}}
request.headers_mut().set(ContentType(mimetypes::requests::{{#vendorExtensions}}{{{uppercase_operation_id}}}{{/vendorExtensions}}.clone()));
let header = &mimetypes::requests::{{#vendorExtensions}}{{{uppercase_operation_id}}}{{/vendorExtensions}};
request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) {
Ok(h) => h,
Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e))))
});
{{/bodyParam}}
{{/consumesMultipart}}
{{/vendorExtensions}}
request.headers_mut().set(XSpanId((context as &dyn Has<XSpanIdString>).get().0.clone()));
{{#vendorExtensions.hasHeaderAuthMethods}}
let header = HeaderValue::from_str((context as &dyn Has<XSpanIdString>).get().0.clone().to_string().as_str());
request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header {
Ok(h) => h,
Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e))))
});
(context as &dyn Has<Option<AuthData>>).get().as_ref().map(|auth_data| {
{{#vendorExtensions.hasHeaderAuthMethods}}
if let Some(auth_data) = (context as &dyn Has<Option<AuthData>>).get().as_ref() {
// Currently only authentication with Basic, API Key, and Bearer are supported
match auth_data {
{{#authMethods}}
{{#isApiKey}}
{{#isKeyInHeader}}
&AuthData::ApiKey(ref api_key) => {
header! { ({{#vendorExtensions}}{{x-apiKeyName}}{{/vendorExtensions}}, "{{keyParamName}}") => [String] }
request.headers_mut().set(
{{#vendorExtensions}}{{x-apiKeyName}}{{/vendorExtensions}}(api_key.to_string())
)
let header = match HeaderValue::from_str(&format!("{}", api_key)) {
Ok(h) => h,
Err(e) => return Box::new(future::err(ApiError(format!("Unable to create {{ vendorExtensions.x-apiKeyName }} header: {}", e))))
};
request.headers_mut().insert(
"{{vendorExtensions.x-apiKeyName}}",
header);
},
{{/isKeyInHeader}}
{{/isApiKey}}
{{#isBasicBasic}}
&AuthData::Basic(ref basic_header) => {
request.headers_mut().set(hyper::header::Authorization(
basic_header.clone(),
))
let auth = swagger::auth::Header(basic_header.clone());
let header = match HeaderValue::from_str(&format!("{}", auth)) {
Ok(h) => h,
Err(e) => return Box::new(future::err(ApiError(format!("Unable to create Authorization header: {}", e))))
};
request.headers_mut().insert(
hyper::header::AUTHORIZATION,
header);
},
{{/isBasicBasic}}
{{#isBasicBearer}}
&AuthData::Bearer(ref bearer_header) => {
request.headers_mut().set(hyper::header::Authorization(
bearer_header.clone(),
))
let auth = swagger::auth::Header(bearer_header.clone());
let header = match HeaderValue::from_str(&format!("{}", auth)) {
Ok(h) => h,
Err(e) => return Box::new(future::err(ApiError(format!("Unable to create Authorization header: {}", e))))
};
request.headers_mut().insert(
hyper::header::AUTHORIZATION,
header);
},
{{/isBasicBearer}}
{{#isOAuth}}
{{^isBasicBearer}}
&AuthData::Bearer(ref bearer_header) => {
request.headers_mut().set(hyper::header::Authorization(
bearer_header.clone(),
))
let auth = swagger::auth::Header(bearer_header.clone());
let header = match HeaderValue::from_str(&format!("{}", auth)) {
Ok(h) => h,
Err(e) => return Box::new(future::err(ApiError(format!("Unable to create Authorization header: {}", e))))
};
request.headers_mut().insert(
hyper::header::AUTHORIZATION,
header);
},
{{/isBasicBearer}}
{{/isOAuth}}
{{/authMethods}}
_ => {}
}
});
}
{{/vendorExtensions.hasHeaderAuthMethods}}
{{#headerParams}}
{{#-first}}
// Header parameters
{{/-first}}{{^isMapContainer}} header! { (Request{{vendorExtensions.typeName}}, "{{{baseName}}}") => {{#isListContainer}}({{{baseType}}})*{{/isListContainer}}{{^isListContainer}}[{{{dataType}}}]{{/isListContainer}} }
{{#required}} request.headers_mut().set(Request{{vendorExtensions.typeName}}(param_{{{paramName}}}{{#isListContainer}}.clone(){{/isListContainer}}));
{{/required}}{{^required}} param_{{{paramName}}}.map(|header| request.headers_mut().set(Request{{vendorExtensions.typeName}}(header{{#isListContainer}}.clone(){{/isListContainer}})));
{{/required}}{{/isMapContainer}}{{#isMapContainer}} let param_{{{paramName}}}: Option<{{{dataType}}}> = None;
{{/-first}}
{{^isMapContainer}}
{{#required}}
request.headers_mut().append(
HeaderName::from_static("{{{nameInLowerCase}}}"),
swagger::IntoHeaderValue(param_{{{paramName}}}.clone()).into());
{{/required}}
{{^required}}
param_{{{paramName}}}.map(|value| request.headers_mut().append(
HeaderName::from_static("{{{nameInLowerCase}}}"),
swagger::IntoHeaderValue(value.clone()).into()));
{{/required}}
{{/isMapContainer}}
{{#isMapContainer}}
let param_{{{paramName}}}: Option<{{{dataType}}}> = None;
{{/isMapContainer}}
{{/headerParams}}
Box::new(self.client_service.call(request)
Box::new(self.client_service.request(request)
.map_err(|e| ApiError(format!("No response received: {}", e)))
.and_then(|mut response| {
match response.status().as_u16() {
{{#responses}}
{{{code}}} => {
{{#headers}} header! { (Response{{{nameInCamelCase}}}, "{{{baseName}}}") => [{{{datatype}}}] }
let response_{{{name}}} = match response.headers().get::<Response{{{nameInCamelCase}}}>() {
Some(response_{{{name}}}) => response_{{{name}}}.0.clone(),
None => return Box::new(future::err(ApiError(String::from("Required response header {{{baseName}}} for response {{{code}}} was not found.")))) as Box<dyn Future<Item=_, Error=_>>,
{{#headers}}
let response_{{{name}}} = match response.headers().get(HeaderName::from_static("{{{nameInLowerCase}}}")) {
Some(response_{{{name}}}) => response_{{{name}}}.clone(),
None => return Box::new(future::err(ApiError(String::from("Required response header {{{baseName}}} for response {{{code}}} was not found.")))) as Box<dyn Future<Item=_, Error=_> + Send>,
};
{{/headers}}
let body = response.body();
let body = response.into_body();
Box::new(
{{#dataType}}
body
@ -516,28 +519,42 @@ impl<F, C> Api<C> for Client<F> where
{{/vendorExtensions}}
)
.map(move |body| {
{{{operationId}}}Response::{{#vendorExtensions}}{{x-responseId}}{{/vendorExtensions}}{{^headers}}(body){{/headers}}{{#headers}}{{#-first}}{ body: body, {{/-first}}{{{name}}}: response_{{{name}}}{{^-last}}, {{/-last}}{{#-last}} }{{/-last}}{{/headers}}
{{{operationId}}}Response::{{#vendorExtensions}}{{x-responseId}}{{/vendorExtensions}}
{{^headers}}
(body)
{{/headers}}
{{#headers}}
{{#-first}}
{
body: body,
{{/-first}}
{{{name}}}: (*Into::<swagger::IntoHeaderValue<{{{dataType}}}>>::into(response_{{{name}}})).clone(),
{{#-last}}
}
{{/-last}}
{{/headers}}
})
{{/dataType}}{{^dataType}}
{{/dataType}}
{{^dataType}}
future::ok(
{{{operationId}}}Response::{{#vendorExtensions}}{{x-responseId}}{{/vendorExtensions}}
{{#headers}}
{{#-first}}
{
{{/-first}}
{{{name}}}: response_{{{name}}},
{{{name}}}: (*Into::<swagger::IntoHeaderValue<{{{dataType}}}>>::into(response_{{{name}}})).clone(),
{{#-last}}
}
{{/-last}}
{{/headers}}
)
{{/dataType}}
) as Box<dyn Future<Item=_, Error=_>>
) as Box<dyn Future<Item=_, Error=_> + Send>
},
{{/responses}}
code => {
let headers = response.headers().clone();
Box::new(response.body()
Box::new(response.into_body()
.take(100)
.concat2()
.then(move |body|
@ -552,7 +569,7 @@ impl<F, C> Api<C> for Client<F> where
Err(e) => Cow::from(format!("<Failed to read body: {}>", e)),
})))
)
) as Box<dyn Future<Item=_, Error=_>>
) as Box<dyn Future<Item=_, Error=_> + Send>
}
}
}))
@ -564,13 +581,13 @@ impl<F, C> Api<C> for Client<F> where
#[derive(Debug)]
pub enum ClientInitError {
InvalidScheme,
InvalidUri(hyper::error::UriError),
InvalidUri(hyper::http::uri::InvalidUri),
MissingHost,
SslError(openssl::error::ErrorStack)
}
impl From<hyper::error::UriError> for ClientInitError {
fn from(err: hyper::error::UriError) -> ClientInitError {
impl From<hyper::http::uri::InvalidUri> for ClientInitError {
fn from(err: hyper::http::uri::InvalidUri) -> ClientInitError {
ClientInitError::InvalidUri(err)
}
}

View File

@ -1,23 +1,18 @@
#![allow(missing_docs, unused_variables, trivial_casts)]
extern crate {{{externCrateName}}};
#[allow(unused_extern_crates)]
extern crate futures;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate swagger;
#[allow(unused_extern_crates)]
extern crate clap;
extern crate tokio_core;
extern crate uuid;
extern crate tokio;
use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData};
#[allow(unused_imports)]
use futures::{Future, future, Stream, stream};
use tokio_core::reactor;
#[allow(unused_imports)]
use {{{externCrateName}}}::{ApiNoContext, ContextWrapperExt,
use {{{externCrateName}}}::{Api, ApiNoContext, Client, ContextWrapperExt,
ApiError{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}},
{{{operationId}}}Response{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
};
@ -28,8 +23,10 @@ fn main() {
.arg(Arg::with_name("operation")
.help("Sets the operation to run")
.possible_values(&[
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}{{#vendorExtensions}}{{^noClientExample}} "{{{operationId}}}",
{{/noClientExample}}{{/vendorExtensions}}{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}])
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}{{#vendorExtensions}}{{^noClientExample}}
"{{{operationId}}}",
{{/noClientExample}}{{/vendorExtensions}}{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
])
.required(true)
.index(1))
.arg(Arg::with_name("https")
@ -47,37 +44,50 @@ fn main() {
.help("Port to contact"))
.get_matches();
let mut core = reactor::Core::new().unwrap();
let is_https = matches.is_present("https");
let base_url = format!("{}://{}:{}",
if is_https { "https" } else { "http" },
matches.value_of("host").unwrap(),
matches.value_of("port").unwrap());
let client = if matches.is_present("https") {
// Using Simple HTTPS
{{{externCrateName}}}::Client::try_new_https(core.handle(), &base_url, "examples/ca.pem")
Client::try_new_https(
&base_url,
"examples/ca.pem")
.expect("Failed to create HTTPS client")
} else {
// Using HTTP
{{{externCrateName}}}::Client::try_new_http(core.handle(), &base_url)
Client::try_new_http(
&base_url)
.expect("Failed to create HTTP client")
};
let context: make_context_ty!(ContextBuilder, EmptyContext, Option<AuthData>, XSpanIdString) =
make_context!(ContextBuilder, EmptyContext, None as Option<AuthData>, XSpanIdString(self::uuid::Uuid::new_v4().to_string()));
make_context!(ContextBuilder, EmptyContext, None as Option<AuthData>, XSpanIdString::default());
let client = client.with_context(context);
match matches.value_of("operation") {
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
{{#vendorExtensions}}{{#noClientExample}}// Disabled because there's no example.
// {{/noClientExample}}Some("{{{operationId}}}") => {
{{#noClientExample}}// {{/noClientExample}} let result = core.run(client.{{{operation_id}}}{{/vendorExtensions}}({{#allParams}}{{^-first}}, {{/-first}}{{#vendorExtensions}}{{{example}}}{{/vendorExtensions}}{{/allParams}}));
{{#vendorExtensions}}{{#noClientExample}}// {{/noClientExample}}{{/vendorExtensions}} println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
{{#vendorExtensions}}{{#noClientExample}}// {{/noClientExample}}{{/vendorExtensions}} },
{{#vendorExtensions.noClientExample}}
/* Disabled because there's no example.
{{/vendorExtensions.noClientExample}}
Some("{{{operationId}}}") => {
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.{{{vendorExtensions.operation_id}}}(
{{#allParams}}
{{{vendorExtensions.example}}}{{^-last}},{{/-last}}
{{/allParams}}
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
{{#vendorExtensions.noClientExample}}
*/
{{/vendorExtensions.noClientExample}}
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
_ => {
panic!("Invalid operation provided")
}
}
}

View File

@ -8,9 +8,9 @@ extern crate {{{externCrateName}}};
extern crate swagger;
extern crate hyper;
extern crate openssl;
extern crate native_tls;
extern crate tokio_proto;
extern crate tokio;
extern crate tokio_tls;
extern crate native_tls;
extern crate clap;
// Imports required by server library.
@ -24,14 +24,18 @@ extern crate error_chain;
extern crate uuid;
{{/apiUsesUuid}}
use futures::{Future, Stream};
use hyper::service::MakeService;
use hyper::server::conn::Http;
use openssl::x509::X509_FILETYPE_PEM;
use openssl::ssl::{SslAcceptorBuilder, SslMethod};
use openssl::error::ErrorStack;
use hyper::server::Http;
use tokio_proto::TcpServer;
use tokio::net::TcpListener;
use clap::{App, Arg};
use swagger::auth::AllowAllAuthenticator;
use std::sync::{Arc, Mutex};
use swagger::auth::MakeAllowAllAuthenticator;
use swagger::EmptyContext;
use tokio_tls::TlsAcceptorExt;
mod server_lib;
@ -56,12 +60,15 @@ fn main() {
.help("Whether to use HTTPS or not"))
.get_matches();
let server = server_lib::Server::new();
let service_fn = {{{externCrateName}}}::server::MakeService::new(server);
let service_fn = MakeAllowAllAuthenticator::new(service_fn, "cosmo");
let service_fn =
{{{externCrateName}}}::server::context::NewAddContext::<_, EmptyContext>::new(
AllowAllAuthenticator::new(
server_lib::NewService::new(),
"cosmo"
)
{{{externCrateName}}}::server::context::MakeAddContext::<_, EmptyContext>::new(
service_fn
);
let addr = "127.0.0.1:{{{serverPort}}}".parse().expect("Failed to parse bind address");
@ -69,9 +76,29 @@ fn main() {
let ssl = ssl().expect("Failed to load SSL keys");
let builder: native_tls::TlsAcceptorBuilder = native_tls::backend::openssl::TlsAcceptorBuilderExt::from_openssl(ssl);
let tls_acceptor = builder.build().expect("Failed to build TLS acceptor");
TcpServer::new(tokio_tls::proto::Server::new(Http::new(), tls_acceptor), addr).serve(service_fn);
let service_fn = Arc::new(Mutex::new(service_fn));
let tls_listener = TcpListener::bind(&addr).unwrap().incoming().for_each(move |tcp| {
let addr = tcp.peer_addr().expect("Unable to get remote address");
let service_fn = service_fn.clone();
hyper::rt::spawn(tls_acceptor.accept_async(tcp).map_err(|_| ()).and_then(move |tls| {
let ms = {
let mut service_fn = service_fn.lock().unwrap();
service_fn.make_service(&addr)
};
ms.and_then(move |service| {
Http::new().serve_connection(tls, service)
}).map_err(|_| ())
}));
Ok(())
}).map_err(|_| ());
hyper::rt::run(tls_listener);
} else {
// Using HTTP
TcpServer::new(Http::new(), addr).serve(service_fn);
hyper::rt::run(hyper::server::Server::bind(&addr).serve(service_fn).map_err(|e| panic!("{:?}", e)));
}
}

View File

@ -1,40 +1,44 @@
//! Main library entry point for {{{externCrateName}}} implementation.
mod server;
#![allow(unused_imports)]
mod errors {
error_chain!{}
}
pub use self::errors::*;
use std::io;
use std::clone::Clone;
use futures::{self, Future};
use chrono;
use std::collections::HashMap;
use std::marker::PhantomData;
use hyper;
use {{{externCrateName}}};
{{#apiUsesUuid}}use uuid;{{/apiUsesUuid}}
use swagger;
use swagger::{Has, XSpanIdString};
{{#hasAuthMethods}}
use swagger::auth::Authorization;
{{/hasAuthMethods}}
pub struct NewService<C>{
marker: PhantomData<C>
use {{{externCrateName}}}::{Api, ApiError{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}},
{{{operationId}}}Response{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
};
use {{{externCrateName}}}::models;
#[derive(Copy, Clone)]
pub struct Server<C> {
marker: PhantomData<C>,
}
impl<C> NewService<C>{
impl<C> Server<C> {
pub fn new() -> Self {
NewService{marker:PhantomData}
Server{marker: PhantomData}
}
}
impl<C> hyper::server::NewService for NewService<C> where C: Has<XSpanIdString> {{#hasAuthMethods}}+ Has<Option<Authorization>>{{/hasAuthMethods}} + Clone + 'static {
type Request = (hyper::Request, C);
type Response = hyper::Response;
type Error = hyper::Error;
type Instance = {{{externCrateName}}}::server::Service<server::Server<C>, C>;
/// Instantiate a new server.
fn new_service(&self) -> io::Result<Self::Instance> {
Ok({{{externCrateName}}}::server::Service::new(server::Server::new()))
impl<C> Api<C> for Server<C> where C: Has<XSpanIdString>{
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
{{#summary}} /// {{{summary}}}{{/summary}}
fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}(&self{{#allParams}}, {{{paramName}}}: {{^required}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{/required}}{{/allParams}}, context: &C) -> Box<Future<Item={{{operationId}}}Response, Error=ApiError> + Send> {
let context = context.clone();
println!("{{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}({{#allParams}}{{#vendorExtensions}}{{{formatString}}}{{/vendorExtensions}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) - X-Span-ID: {:?}"{{#allParams}}, {{{paramName}}}{{/allParams}}, context.get().0.clone());{{#allParams}}{{/allParams}}
Box::new(futures::failed("Generic failure".into()))
}
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
}

View File

@ -1,40 +0,0 @@
//! Server implementation of {{{externCrateName}}}.
#![allow(unused_imports)]
use futures::{self, Future};
use chrono;
use std::collections::HashMap;
use std::marker::PhantomData;
use swagger;
use swagger::{Has, XSpanIdString};
{{#apiUsesUuid}}
use uuid;
{{/apiUsesUuid}}
use {{{externCrateName}}}::{Api, ApiError{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}},
{{{operationId}}}Response{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
};
use {{{externCrateName}}}::models;
#[derive(Copy, Clone)]
pub struct Server<C> {
marker: PhantomData<C>,
}
impl<C> Server<C> {
pub fn new() -> Self {
Server{marker: PhantomData}
}
}
impl<C> Api<C> for Server<C> where C: Has<XSpanIdString>{
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
{{#summary}} /// {{{summary}}}{{/summary}}
fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}(&self{{#allParams}}, {{{paramName}}}: {{^required}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{/required}}{{/allParams}}, context: &C) -> Box<dyn Future<Item={{{operationId}}}Response, Error=ApiError>> {
let context = context.clone();
println!("{{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}({{#allParams}}{{#vendorExtensions}}{{{formatString}}}{{/vendorExtensions}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) - X-Span-ID: {:?}"{{#allParams}}, {{{paramName}}}{{/allParams}}, context.get().0.clone());{{#allParams}}{{/allParams}}
Box::new(futures::failed("Generic failure".into()))
}
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
}

View File

@ -1,18 +1,17 @@
#![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)]
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
// Crates with macros
#[macro_use]
extern crate serde_derive;
#[cfg(any(feature = "client", feature = "server"))]
#[cfg(any(feature = "server"))]
#[macro_use]
extern crate hyper;
extern crate lazy_static;
#[cfg(any(feature = "client", feature = "server"))]
#[macro_use]
extern crate url;
#[macro_use]
extern crate log;
// Crates for conversion support
#[cfg(feature = "conversion")]
@ -26,15 +25,42 @@ extern crate frunk_core;
extern crate mime;
extern crate serde;
extern crate serde_json;
{{#usesXml}}extern crate serde_xml_rs;{{/usesXml}}
extern crate futures;
extern crate chrono;
extern crate swagger;
{{#apiUsesUuid}}
extern crate uuid;
{{/apiUsesUuid}}
#[cfg(any(feature = "client", feature = "server"))]
extern crate hyper;
#[cfg(any(feature = "client"))]
extern crate hyper_tls;
#[cfg(any(feature = "client", feature = "server"))]
extern crate openssl;
#[cfg(any(feature = "client", feature = "server"))]
extern crate native_tls;
#[cfg(feature = "server")]
extern crate percent_encoding;
#[cfg(any(feature = "client", feature = "server"))]
extern crate serde_json;
#[cfg(any(feature = "client", feature = "server"))]
extern crate serde_ignored;
#[cfg(any(feature = "client", feature = "server"))]
extern crate tokio;
#[cfg(any(feature = "client", feature = "server"))]
{{#apiUsesUuid}}extern crate uuid;{{/apiUsesUuid}}
{{#usesXml}}extern crate serde_xml_rs;{{/usesXml}}
{{#apiUsesMultipart}}
#[cfg(any(feature = "client", feature = "server"))]
extern crate multipart;
extern crate mime_0_2;
{{/apiUsesMultipart}}
#[cfg(any(feature = "client", feature = "server"))]
{{#usesUrlEncodedForm}}extern crate serde_urlencoded;{{/usesUrlEncodedForm}}
use hyper::header::HeaderValue;
use futures::Stream;
use std::io::Error;
@ -92,7 +118,7 @@ pub enum {{{operationId}}}Response {
pub trait Api<C> {
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
{{#summary}} /// {{{summary}}}{{/summary}}
fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}(&self{{#allParams}}, {{{paramName}}}: {{^required}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{/required}}{{/allParams}}, context: &C) -> Box<dyn Future<Item={{{operationId}}}Response, Error=ApiError>>;
fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}(&self{{#allParams}}, {{{paramName}}}: {{^required}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{/required}}{{/allParams}}, context: &C) -> Box<dyn Future<Item={{{operationId}}}Response, Error=ApiError> + Send>;
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
}
@ -100,7 +126,7 @@ pub trait Api<C> {
pub trait ApiNoContext {
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
{{#summary}} /// {{{summary}}}{{/summary}}
fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}(&self{{#allParams}}, {{{paramName}}}: {{^required}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{/required}}{{/allParams}}) -> Box<dyn Future<Item={{{operationId}}}Response, Error=ApiError>>;
fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}(&self{{#allParams}}, {{{paramName}}}: {{^required}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{/required}}{{/allParams}}) -> Box<dyn Future<Item={{{operationId}}}Response, Error=ApiError> + Send>;
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
}
@ -119,7 +145,7 @@ impl<'a, T: Api<C> + Sized, C> ContextWrapperExt<'a, C> for T {
impl<'a, T: Api<C>, C> ApiNoContext for ContextWrapper<'a, T, C> {
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
{{#summary}} /// {{{summary}}}{{/summary}}
fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}(&self{{#allParams}}, {{{paramName}}}: {{^required}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{/required}}{{/allParams}}) -> Box<dyn Future<Item={{{operationId}}}Response, Error=ApiError>> {
fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}(&self{{#allParams}}, {{{paramName}}}: {{^required}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{/required}}{{/allParams}}) -> Box<dyn Future<Item={{{operationId}}}Response, Error=ApiError> + Send> {
self.api().{{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}({{#allParams}}{{{paramName}}}, {{/allParams}}&self.context())
}
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}

View File

@ -1,28 +1,19 @@
/// mime types for requests and responses
pub mod responses {
use hyper::mime::*;
// The macro is called per-operation to beat the recursion limit
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}{{#responses}}{{#produces}}{{#-first}}{{#dataType}}
lazy_static! {
/// Create Mime objects for the response content types for {{{operationId}}}
pub static ref {{#vendorExtensions}}{{{uppercase_operation_id}}}_{{x-uppercaseResponseId}}: Mime = "{{{mimeType}}}".parse().unwrap();{{/vendorExtensions}}
}
/// Create &str objects for the response content types for {{{operationId}}}
pub static {{#vendorExtensions}}{{{uppercase_operation_id}}}_{{x-uppercaseResponseId}}: &str = "{{{mimeType}}}";{{/vendorExtensions}}
{{/dataType}}{{/-first}}{{/produces}}{{/responses}}{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
}
pub mod requests {
use hyper::mime::*;
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}{{#bodyParam}}
lazy_static! {
/// Create Mime objects for the request content types for {{{operationId}}}
pub static ref {{#vendorExtensions}}{{{uppercase_operation_id}}}{{/vendorExtensions}}: Mime = "{{#consumes}}{{#-first}}{{{mediaType}}}{{/-first}}{{/consumes}}{{^consumes}}application/json{{/consumes}}".parse().unwrap();
}
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}{{^vendorExtensions.consumesMultipart}}{{#bodyParam}}
/// Create &str objects for the request content types for {{{operationId}}}
pub static {{{vendorExtensions.uppercase_operation_id}}}: &str = "{{#consumes}}{{#-first}}{{{mediaType}}}{{/-first}}{{/consumes}}{{^consumes}}application/json{{/consumes}}";
{{/bodyParam}}{{^bodyParam}}{{#vendorExtensions}}{{#formParams}}{{#-first}}
lazy_static! {
/// Create Mime objects for the request content types for {{{operationId}}}
pub static ref {{#vendorExtensions}}{{{uppercase_operation_id}}}{{/vendorExtensions}}: Mime = "{{#consumes}}{{#-first}}{{{mediaType}}}{{/-first}}{{/consumes}}{{^consumes}}application/x-www-form-urlencoded{{/consumes}}".parse().unwrap();
}
{{/-first}}{{/formParams}}{{/vendorExtensions}}{{/bodyParam}}{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
/// Create &str objects for the request content types for {{{operationId}}}
pub static {{{uppercase_operation_id}}}: &str = "{{#consumes}}{{#-first}}{{{mediaType}}}{{/-first}}{{/consumes}}{{^consumes}}application/x-www-form-urlencoded{{/consumes}}";
{{/-first}}{{/formParams}}{{/vendorExtensions}}{{/bodyParam}}{{/vendorExtensions.consumesMultipart}}{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
}

View File

@ -1,5 +1,4 @@
#![allow(unused_imports, unused_qualifications, unused_extern_crates)]
extern crate chrono;
#![allow(unused_imports, unused_qualifications)]
{{#usesXml}}
use serde_xml_rs;

View File

@ -1,64 +1,86 @@
use futures::Future;
use hyper;
use hyper::header::HeaderName;
use hyper::{Error, Request, Response, StatusCode, service::Service, body::Payload};
use url::form_urlencoded;
use std::default::Default;
use std::io;
use std::marker::PhantomData;
use 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 swagger::auth::{AuthData, Authorization, Bearer, Scopes};
use swagger::context::ContextualPayload;
use swagger::{EmptyContext, Has, Pop, Push, XSpanIdString};
use Api;
pub struct NewAddContext<T, A>
{
pub struct MakeAddContext<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,
impl<T, A, B, C, D> MakeAddContext<T, A>
where
A: Default + Push<XSpanIdString, Result = B>,
B: Push<Option<AuthData>, Result = C>,
C: Push<Option<Authorization>, Result = D>,
{
pub fn new(inner: T) -> NewAddContext<T, A> {
NewAddContext {
pub fn new(inner: T) -> MakeAddContext<T, A> {
MakeAddContext {
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,
// Make a service that adds context.
impl<'a, T, SC, A, B, C, D, E, ME, S, OB, F> hyper::service::MakeService<&'a SC> for
MakeAddContext<T, A>
where
A: Default + Push<XSpanIdString, Result = B>,
B: Push<Option<AuthData>, Result = C>,
C: Push<Option<Authorization>, Result = D>,
D: Send + 'static,
T: hyper::service::MakeService<
&'a SC,
Error = E,
MakeError = ME,
Service = S,
ReqBody = ContextualPayload<hyper::Body, D>,
ResBody = OB,
Future = F
>,
S: Service<
Error = E,
ReqBody = ContextualPayload<hyper::Body, D>,
ResBody = OB> + 'static,
ME: swagger::ErrorBound,
E: swagger::ErrorBound,
F: Future<Item=S, Error=ME> + Send + 'static,
S::Future: Send,
OB: Payload,
{
type Request = Request;
type Response = Response;
type Error = Error;
type Instance = AddContext<T::Instance, A>;
type ReqBody = hyper::Body;
type ResBody = OB;
type Error = E;
type MakeError = ME;
type Service = AddContext<S, A>;
type Future = Box<dyn Future<Item = Self::Service, Error = ME> + Send + 'static>;
fn new_service(&self) -> Result<Self::Instance, io::Error> {
self.inner.new_service().map(|s| AddContext::new(s))
fn make_service(&mut self, ctx: &'a SC) -> Self::Future {
Box::new(self.inner.make_service(ctx).map(|s| AddContext::new(s)))
}
}
/// Middleware to extract authentication data from request
pub struct AddContext<T, A>
{
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>,
where
A: Default + Push<XSpanIdString, Result = B>,
B: Push<Option<AuthData>, Result = C>,
C: Push<Option<Authorization>, Result = D>,
T: Service,
{
pub fn new(inner: T) -> AddContext<T, A> {
AddContext {
@ -68,61 +90,84 @@ impl<T, A, B, C, D> AddContext<T, A>
}
}
impl<T, A, B, C, D> hyper::server::Service for AddContext<T, A>
impl<T, A, B, C, D> Service for AddContext<T, A>
where
A: Default + Push<XSpanIdString, Result=B>,
B: Push<Option<AuthData>, Result=C>,
C: Push<Option<Authorization>, Result=D>,
T: hyper::server::Service<Request = (Request, D), Response = Response, Error = Error>,
D: Send + 'static,
T: Service<ReqBody = ContextualPayload<hyper::Body, D>>,
T::Future: Future<Item=Response<T::ResBody>, Error=T::Error> + Send + 'static
{
type Request = Request;
type Response = Response;
type Error = Error;
type Future = T::Future;
type ReqBody = hyper::Body;
type ResBody = T::ResBody;
type Error = T::Error;
type Future = Box<dyn Future<Item=Response<T::ResBody>, Error=T::Error> + Send + 'static>;
fn call(&self, req: Self::Request) -> Self::Future {
fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future {
let context = A::default().push(XSpanIdString::get_or_generate(&req));
let (head, body) = req.into_parts();
let headers = head.headers.clone();
{{#authMethods}}
{{#isBasic}}
{
use hyper::header::{Authorization as HyperAuth, Basic, Bearer};
use swagger::auth::Basic;
use std::ops::Deref;
if let Some(basic) = req.headers().get::<HyperAuth<Basic>>().cloned() {
let auth_data = AuthData::Basic(basic.deref().clone());
if let Some(basic) = swagger::auth::from_headers::<Basic>(&headers) {
let auth_data = AuthData::Basic(basic);
let context = context.push(Some(auth_data));
let context = context.push(None::<Authorization>);
return self.inner.call((req, context));
let body = ContextualPayload {
inner: body,
context: context,
};
return Box::new(self.inner.call(hyper::Request::from_parts(head, body)));
}
}
{{/isBasic}}
{{#isOAuth}}
{
use hyper::header::{Authorization as HyperAuth, Basic, Bearer};
use swagger::auth::Bearer;
use std::ops::Deref;
if let Some(bearer) = req.headers().get::<HyperAuth<Bearer>>().cloned() {
let auth_data = AuthData::Bearer(bearer.deref().clone());
if let Some(bearer) = swagger::auth::from_headers::<Bearer>(&headers) {
let auth_data = AuthData::Bearer(bearer);
let context = context.push(Some(auth_data));
let context = context.push(None::<Authorization>);
return self.inner.call((req, context));
let body = ContextualPayload {
inner: body,
context: context,
};
return Box::new(self.inner.call(hyper::Request::from_parts(head, body)));
}
}
{{/isOAuth}}
{{#isApiKey}}
{{#isKeyInHeader}}
{
header! { (ApiKey{{-index}}, "{{{keyParamName}}}") => [String] }
if let Some(header) = req.headers().get::<ApiKey{{-index}}>().cloned() {
let auth_data = AuthData::ApiKey(header.0);
use swagger::auth::api_key_from_header;
if let Some(header) = api_key_from_header(&headers, "{{{keyParamName}}}") {
let auth_data = AuthData::ApiKey(header);
let context = context.push(Some(auth_data));
let context = context.push(None::<Authorization>);
return self.inner.call((req, context));
let body = ContextualPayload {
inner: body,
context: context,
};
return Box::new(self.inner.call(hyper::Request::from_parts(head, body)));
}
}
{{/isKeyInHeader}}
{{#isKeyInQuery}}
{
let key = form_urlencoded::parse(req.query().unwrap_or_default().as_bytes())
let key = form_urlencoded::parse(head.uri.query().unwrap_or_default().as_bytes())
.filter(|e| e.0 == "api_key_query")
.map(|e| e.1.clone().into_owned())
.nth(0);
@ -130,7 +175,12 @@ impl<T, A, B, C, D> hyper::server::Service for AddContext<T, A>
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));
let body = ContextualPayload {
inner: body,
context: context,
};
return Box::new(self.inner.call(hyper::Request::from_parts(head, body)));
}
}
{{/isKeyInQuery}}
@ -139,6 +189,11 @@ impl<T, A, B, C, D> hyper::server::Service for AddContext<T, A>
let context = context.push(None::<AuthData>);
let context = context.push(None::<Authorization>);
return self.inner.call((req, context));
let body = ContextualPayload {
inner: body,
context: context,
};
Box::new(self.inner.call(hyper::Request::from_parts(head, body)))
}
}

View File

@ -1,61 +1,42 @@
#![allow(unused_extern_crates)]
extern crate serde_ignored;
extern crate tokio_core;
extern crate native_tls;
extern crate hyper_tls;
extern crate openssl;
extern crate mime;
extern crate chrono;
extern crate percent_encoding;
extern crate url;
{{#apiUsesUuid}}
extern crate uuid;
{{/apiUsesUuid}}
{{#apiUsesMultipart}}
extern crate multipart;
{{/apiUsesMultipart}}
use std::sync::Arc;
#[allow(unused_imports)]
use std::collections::{HashMap, BTreeMap, BTreeSet};
use std::marker::PhantomData;
use futures::{Future, future, Stream, stream};
use hyper;
use hyper::{Request, Response, Error, StatusCode};
use hyper::header::{Headers, ContentType};
use self::url::form_urlencoded;
use mimetypes;
{{#apiUsesMultipart}}
use self::multipart::server::Multipart;
use self::multipart::server::save::SaveResult;
use std::fs;
{{/apiUsesMultipart}}
use hyper::{Request, Response, Error, StatusCode, Body, HeaderMap};
use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE};
use serde_json;
use std::io;
#[allow(unused_imports)]
use swagger;
use swagger::{ApiError, XSpanIdString, Has, RequestParser};
use swagger::auth::Scopes;
use swagger::context::ContextualPayload;
use url::form_urlencoded;
{{#apiUsesMultipart}}
use multipart::server::Multipart;
use multipart::server::save::SaveResult;
{{/apiUsesMultipart}}
{{#usesXml}}
use serde_xml_rs;
{{/usesXml}}
{{#apiUsesUuid}}
use uuid;
{{/apiUsesUuid}}
#[allow(unused_imports)]
use std::collections::{HashMap, BTreeMap};
#[allow(unused_imports)]
use swagger;
use std::io;
#[allow(unused_imports)]
use std::collections::BTreeSet;
use mimetypes;
pub use swagger::auth::Authorization;
use swagger::{ApiError, XSpanId, XSpanIdString, Has, RequestParser};
use swagger::auth::Scopes;
use {Api{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}},
{{{operationId}}}Response{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
};
#[allow(unused_imports)]
use models;
pub mod context;
header! { (Warning, "Warning") => [String] }
mod paths {
extern crate regex;
@ -64,76 +45,92 @@ mod paths {
{{#pathSet}}
r"^{{{basePathWithoutHost}}}{{{pathRegEx}}}"{{^-last}},{{/-last}}
{{/pathSet}}
]).unwrap();
])
.expect("Unable to create global regex set");
}
{{#pathSet}}
pub static ID_{{{PATH_ID}}}: usize = {{{index}}};
{{#hasPathParams}}
lazy_static! {
pub static ref REGEX_{{{PATH_ID}}}: regex::Regex = regex::Regex::new(r"^{{{basePathWithoutHost}}}{{{pathRegEx}}}").unwrap();
pub static ref REGEX_{{{PATH_ID}}}: regex::Regex =
regex::Regex::new(r"^{{{basePathWithoutHost}}}{{{pathRegEx}}}")
.expect("Unable to create regex for {{{PATH_ID}}}");
}
{{/hasPathParams}}
{{/pathSet}}
}
pub struct NewService<T, C> {
api_impl: Arc<T>,
marker: PhantomData<C>,
pub struct MakeService<T, RC> {
api_impl: T,
marker: PhantomData<RC>,
}
impl<T, C> NewService<T, C>
impl<T, RC> MakeService<T, RC>
where
T: Api<C> + Clone + 'static,
C: Has<XSpanIdString> {{#hasAuthMethods}}+ Has<Option<Authorization>>{{/hasAuthMethods}} + 'static
T: Api<RC> + Clone + Send + 'static,
RC: Has<XSpanIdString> {{#hasAuthMethods}}+ Has<Option<Authorization>>{{/hasAuthMethods}} + 'static
{
pub fn new<U: Into<Arc<T>>>(api_impl: U) -> NewService<T, C> {
NewService{api_impl: api_impl.into(), marker: PhantomData}
pub fn new(api_impl: T) -> Self {
MakeService {
api_impl,
marker: PhantomData
}
}
}
impl<T, C> hyper::server::NewService for NewService<T, C>
impl<'a, T, SC, RC> hyper::service::MakeService<&'a SC> for MakeService<T, RC>
where
T: Api<C> + Clone + 'static,
C: Has<XSpanIdString> {{#hasAuthMethods}}+ Has<Option<Authorization>>{{/hasAuthMethods}} + 'static
T: Api<RC> + Clone + Send + 'static,
RC: Has<XSpanIdString> {{#hasAuthMethods}}+ Has<Option<Authorization>>{{/hasAuthMethods}} + 'static + Send
{
type Request = (Request, C);
type Response = Response;
type ReqBody = ContextualPayload<Body, RC>;
type ResBody = Body;
type Error = Error;
type Instance = Service<T, C>;
type Service = Service<T, RC>;
type Future = future::FutureResult<Self::Service, Self::MakeError>;
type MakeError = Error;
fn new_service(&self) -> Result<Self::Instance, io::Error> {
Ok(Service::new(self.api_impl.clone()))
fn make_service(&mut self, _ctx: &'a SC) -> Self::Future {
future::FutureResult::from(Ok(Service::new(
self.api_impl.clone(),
)))
}
}
pub struct Service<T, C> {
api_impl: Arc<T>,
marker: PhantomData<C>,
pub struct Service<T, RC> {
api_impl: T,
marker: PhantomData<RC>,
}
impl<T, C> Service<T, C>
impl<T, RC> Service<T, RC>
where
T: Api<C> + Clone + 'static,
C: Has<XSpanIdString> {{#hasAuthMethods}}+ Has<Option<Authorization>>{{/hasAuthMethods}} + 'static {
pub fn new<U: Into<Arc<T>>>(api_impl: U) -> Service<T, C> {
Service{api_impl: api_impl.into(), marker: PhantomData}
T: Api<RC> + Clone + Send + 'static,
RC: Has<XSpanIdString> {{#hasAuthMethods}}+ Has<Option<Authorization>>{{/hasAuthMethods}} + 'static {
pub fn new(api_impl: T) -> Self {
Service {
api_impl: api_impl,
marker: PhantomData
}
}
}
impl<T, C> hyper::server::Service for Service<T, C>
impl<T, C> hyper::service::Service for Service<T, C>
where
T: Api<C> + Clone + 'static,
C: Has<XSpanIdString> {{#hasAuthMethods}}+ Has<Option<Authorization>>{{/hasAuthMethods}} + 'static
T: Api<C> + Clone + Send + 'static,
C: Has<XSpanIdString> {{#hasAuthMethods}}+ Has<Option<Authorization>>{{/hasAuthMethods}} + 'static + Send
{
type Request = (Request, C);
type Response = Response;
type ReqBody = ContextualPayload<Body, C>;
type ResBody = Body;
type Error = Error;
type Future = Box<dyn Future<Item=Response, Error=Error>>;
type Future = Box<dyn Future<Item = Response<Self::ResBody>, Error = Self::Error> + Send>;
fn call(&self, (req, mut context): Self::Request) -> Self::Future {
fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future {
let api_impl = self.api_impl.clone();
let (method, uri, _, headers, body) = req.deconstruct();
let (parts, body) = req.into_parts();
let (method, uri, headers) = (parts.method, parts.uri, parts.headers);
let path = paths::GLOBAL_REGEX_SET.matches(uri.path());
let mut context = body.context;
let body = body.inner;
// This match statement is duplicated below in `parse_operation_id()`.
// Please update both places if changing how this code is autogenerated.
@ -145,9 +142,10 @@ where
{
let authorization = match (&context as &dyn Has<Option<Authorization>>).get() {
&Some(ref authorization) => authorization,
&None => return Box::new(future::ok(Response::new()
.with_status(StatusCode::Forbidden)
.with_body("Unauthenticated"))),
&None => return Box::new(future::ok(Response::builder()
.status(StatusCode::FORBIDDEN)
.body(Body::from("Unauthenticated"))
.expect("Unable to create Authentication Forbidden response"))),
};
{{#authMethods}}
@ -162,12 +160,13 @@ where
if !required_scopes.is_subset(scopes) {
let missing_scopes = required_scopes.difference(scopes);
return Box::new(future::ok(Response::new()
.with_status(StatusCode::Forbidden)
.with_body(missing_scopes.fold(
return Box::new(future::ok(Response::builder()
.status(StatusCode::FORBIDDEN)
.body(Body::from(missing_scopes.fold(
"Insufficient authorization, missing scopes".to_string(),
|s, scope| format!("{} {}", s, scope)
|s, scope| format!("{} {}", s, scope))
))
.expect("Unable to create Authentication Insufficient response")
));
}
}
@ -177,14 +176,17 @@ where
{{/hasAuthMethods}}
{{#vendorExtensions}}
{{#consumesMultipart}}
let boundary = match multipart_boundary(&headers) {
let boundary = match swagger::multipart::boundary(&headers) {
Some(boundary) => boundary.to_string(),
None => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body("Couldn't find valid multipart body"))),
None => return Box::new(future::ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from("Couldn't find valid multipart body".to_string()))
.expect("Unable to create Bad Request response for incorrect boundary"))),
};
{{/consumesMultipart}}
{{#hasPathParams}}
// Path parameters
let path = uri.path().to_string();
let path: &str = &uri.path().to_string();
let path_params =
paths::REGEX_{{{PATH_ID}}}
.captures(&path)
@ -197,28 +199,42 @@ where
let param_{{{paramName}}} = match percent_encoding::percent_decode(path_params["{{{baseName}}}"].as_bytes()).decode_utf8() {
Ok(param_{{{paramName}}}) => match param_{{{paramName}}}.parse::<{{{dataType}}}>() {
Ok(param_{{{paramName}}}) => param_{{{paramName}}},
Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse path parameter {{{baseName}}}: {:?}", e)))),
Err(e) => return Box::new(future::ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("Couldn't parse path parameter {{{baseName}}}: {}", e)))
.expect("Unable to create Bad Request response for invalid path parameter"))),
},
Err(_) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["{{{baseName}}}"]))))
Err(_) => return Box::new(future::ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["{{{baseName}}}"])))
.expect("Unable to create Bad Request response for invalid percent decode")))
};
{{/pathParams}}
{{#headerParams}}
{{#-first}}
// Header parameters
{{/-first}}
header! { (Request{{vendorExtensions.typeName}}, "{{{baseName}}}") => {{#isListContainer}}({{{baseType}}})*{{/isListContainer}}{{^isListContainer}}[{{{dataType}}}]{{/isListContainer}} }
let param_{{{paramName}}} = headers.get(HeaderName::from_static("{{{nameInLowerCase}}}"));
{{#required}}
let param_{{{paramName}}} = match headers.get::<Request{{vendorExtensions.typeName}}>() {
Some(param_{{{paramName}}}) => param_{{{paramName}}}.0.clone(),
None => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body("Missing or invalid required header {{{baseName}}}"))),
let param_{{{paramName}}} = match param_{{{paramName}}})) {
Some(v) => Some(swagger::IntoHeaderValue::<{{{dataType}}}>::from(v)).0),
None => return Box::new(future::ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from("Missing or invalid required header {{{baseName}}}"))
.expect("Unable to create Bad Request response for missing required header {{{baseName}}}")))
};
{{/required}}
{{^required}}
let param_{{{paramName}}} = headers.get::<Request{{vendorExtensions.typeName}}>().map(|header| header.0.clone());
let param_{{{paramName}}} = param_{{{paramName}}}.map(|p| {
swagger::IntoHeaderValue::<{{{dataType}}}>::from((*p).clone()).0
});
{{/required}}
{{/headerParams}}
{{#queryParams}}
{{#-first}}
// Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response)
let query_params = form_urlencoded::parse(uri.query().unwrap_or_default().as_bytes()).collect::<Vec<_>>();
{{/-first}}
@ -240,9 +256,15 @@ where
let param_{{{paramName}}} = match param_{{{paramName}}} {
Some(param_{{{paramName}}}) => match param_{{{paramName}}}.parse::<{{{dataType}}}>() {
Ok(param_{{{paramName}}}) => param_{{{paramName}}},
Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse query parameter {{{baseName}}} - doesn't match schema: {}", e)))),
Err(e) => return Box::new(future::ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("Couldn't parse query parameter {{{baseName}}} - doesn't match schema: {}", e)))
.expect("Unable to create Bad Request response for invalid query parameter {{{baseName}}}"))),
},
None => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body("Missing required query parameter {{{baseName}}}"))),
None => return Box::new(future::ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from("Missing required query parameter {{{baseName}}}"))
.expect("Unable to create Bad Request response for missing qeury parameter {{{baseName}}}"))),
};
{{/required}}{{^required}}
let param_{{{paramName}}} = param_{{{paramName}}}.and_then(|param_{{{paramName}}}| param_{{{paramName}}}.parse::<{{{baseType}}}>().ok());
@ -257,7 +279,7 @@ where
// values, rather than causing a 400 response). Produce warning header and logs for
// any unused fields.
Box::new(body.concat2()
.then(move |result| -> Box<dyn Future<Item=Response, Error=Error>> {
.then(move |result| -> Self::Future {
match result {
Ok(body) => {
{{#vendorExtensions}}
@ -278,7 +300,10 @@ where
}) {
Ok(param_{{{paramName}}}) => param_{{{paramName}}},
{{#required}}
Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse body parameter {{{baseName}}} - doesn't match schema: {}", e)))),
Err(e) => return Box::new(future::ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("Couldn't parse body parameter {{{baseName}}} - doesn't match schema: {}", e)))
.expect("Unable to create Bad Request response for invalid body parameter {{{baseName}}} due to schema"))),
{{/required}}
{{^required}}
Err(_) => None,
@ -290,7 +315,13 @@ where
Some(swagger::ByteArray(body.to_vec()))
{{/isByteArray}}
{{#isString}}
Some(String::from_utf8(body.to_vec()).unwrap())
match String::from_utf8(body.to_vec()) {
Ok(param_{{{paramName}}}) => Some(param_{{{paramName}}}),
Err(e) => return Box::new(future::ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("Couldn't parse body parameter {{{baseName}}} - not valid UTF-8: {}", e)))
.expect("Unable to create Bad Request response for invalid body parameter {{{baseName}}} due to UTF-8"))),
}
{{/isString}}
{{/consumesPlainText}}
{{/vendorExtensions}}
@ -300,7 +331,10 @@ where
{{#required}}
let param_{{{paramName}}} = match param_{{{paramName}}} {
Some(param_{{{paramName}}}) => param_{{{paramName}}},
None => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body("Missing required body parameter {{{baseName}}}"))),
None => return Box::new(future::ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from("Missing required body parameter {{{baseName}}}"))
.expect("Unable to create Bad Request response for missing body parameter {{{baseName}}}"))),
};
{{/required}}
{{/-first}}
@ -313,75 +347,70 @@ where
// values, rather than causing a 400 response). Produce warning header and logs for
// any unused fields.
Box::new(body.concat2()
.then(move |result| -> Box<dyn Future<Item=Response, Error=Error>> {
.then(move |result| -> Self::Future {
match result {
Ok(body) => {
use std::io::Read;
// Read Form Parameters from body
let mut entries = match Multipart::with_body(&body.to_vec()[..], boundary).save().temp() {
SaveResult::Full(entries) => {
entries
},
_ => {
return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Unable to process all message parts"))))
return Box::new(future::ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("Unable to process all message parts")))
.expect("Unable to create Bad Request response due to failure to process all message")))
},
};
{{#formParams}}{{#-first}}{{/-first}}
let field_{{{paramName}}} = entries.fields.remove("{{{paramName}}}");
let param_{{{paramName}}} = match field_{{{paramName}}} {
Some(field) => {
let mut reader = field[0].data.readable().expect("Unable to read field for {{{paramName}}}");
{{^required}}
Some({
{{/required}}
{{#isByteArray}}
let file_{{{paramName}}} = entries.files.remove("{{{paramName}}}");
{{#required}}
let param_{{{paramName}}} = match file_{{{paramName}}} {
Some(file) => {
let path = &file[0].path;
let {{{paramName}}}_str = fs::read_to_string(path).unwrap();
swagger::ByteArray({{{paramName}}}_str.as_bytes().to_vec())
}
None => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Missing required form parameter {{{paramName}}}")))),
};
{{/required}}
{{^required}}
let param_{{{paramName}}} = match file_{{{paramName}}} {
Some(file) => {
let path = &file[0].path;
let {{{paramName}}}_str = fs::read_to_string(path).unwrap();
Some(swagger::ByteArray({{{paramName}}}_str.as_bytes().to_vec()))
}
None => None,
};
{{/required}}
let mut data = vec![];
reader.read_to_end(&mut data).expect("Reading saved binary data should never fail");
swagger::ByteArray(data)
{{/isByteArray}}
{{^isByteArray}}{{#jsonSchema}}
let file_{{{paramName}}} = entries.files.remove("{{{paramName}}}");
{{#required}}
let param_{{{paramName}}} = match file_{{{paramName}}} {
Some(file) => {
let path = &file[0].path;
let {{{paramName}}}_str = fs::read_to_string(path).expect("Reading saved String should never fail");
let {{{paramName}}}_model: {{{dataType}}} = match serde_json::from_str(&{{{paramName}}}_str) {
{{^isByteArray}}
{{#jsonSchema}}
let mut data = String::new();
reader.read_to_string(&mut data).expect("Reading saved String should never fail");
let {{{paramName}}}_model: {{{dataType}}} = match serde_json::from_str(&data) {
Ok(model) => model,
Err(e) => {
return Box::new(future::ok(
Response::new()
.with_status(StatusCode::BadRequest)
.with_body(format!("{{{paramName}}} data does not match API definition: {}", e))))
Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("{{{paramName}}} data does not match API definition: {}", e)))
.expect("Unable to create Bad Request response due to failure to process all message")))
}
};
{{{paramName}}}_model
{{/jsonSchema}}
{{/isByteArray}}
{{^required}}
})
{{/required}}
},
None => {
{{#required}}
return Box::new(future::ok(
Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("Missing required form parameter {{{paramName}}}")))
.expect("Unable to create Bad Request due to missing required form parameter {{{paramName}}}")))
{{/required}}
{{^required}}
None
{{/required}}
}
None => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Missing required form parameter {{{paramName}}}")))),
};
{{/required}}
{{^required}}
let param_{{{paramName}}} = match file_{{{paramName}}} {
Some(file) => {
let path = &file[0].path;
let {{{paramName}}}_str = fs::read_to_string(path).unwrap();
let {{{paramName}}}_model: {{{dataType}}} = serde_json::from_str(&{{{paramName}}}_str).expect("Impossible to fail to serialise");
Some({{{paramName}}}_model)
}
None => None,
};
{{/required}}
{{/jsonSchema}}{{/isByteArray}}
{{/formParams}}
{{/vendorExtensions}}
{{/bodyParams}}
@ -395,19 +424,35 @@ where
{{#-first}}
// Form parameters
{{/-first}}
let param_{{{paramName}}} = {{^isContainer}}{{#vendorExtensions}}{{{example}}};{{/vendorExtensions}}{{/isContainer}}{{#isListContainer}}{{#required}}Vec::new();{{/required}}{{^required}}None;{{/required}}{{/isListContainer}}{{#isMapContainer}}None;{{/isMapContainer}}
let param_{{{paramName}}} =
{{^isContainer}}{{#vendorExtensions}}{{{example}}};{{/vendorExtensions}}{{/isContainer}}
{{#isListContainer}}{{#required}}Vec::new();{{/required}}{{^required}}None;{{/required}}{{/isListContainer}}
{{#isMapContainer}}None;{{/isMapContainer}}
{{/formParams}}
{{/vendorExtensions}}
{{/bodyParams}}
{{/consumesMultipart}}
{{/vendorExtensions}}
Box::new(api_impl.{{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}({{#allParams}}param_{{{paramName}}}{{#isListContainer}}.as_ref(){{/isListContainer}}, {{/allParams}}&context)
.then(move |result| {
let mut response = Response::new();
response.headers_mut().set(XSpanId((&context as &dyn Has<XSpanIdString>).get().0.to_string()));
Box::new(
api_impl.{{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}(
{{#allParams}}
param_{{{paramName}}}{{#isListContainer}}.as_ref(){{/isListContainer}},
{{/allParams}}
&context
).then(move |result| {
let mut response = Response::new(Body::empty());
response.headers_mut().insert(
HeaderName::from_static("x-span-id"),
HeaderValue::from_str((&context as &dyn Has<XSpanIdString>).get().0.clone().to_string().as_str())
.expect("Unable to create X-Span-ID header value"));
{{#bodyParams}}{{#vendorExtensions}}{{^consumesPlainText}}
if !unused_elements.is_empty() {
response.headers_mut().set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements)));
response.headers_mut().insert(
HeaderName::from_static("warning"),
HeaderValue::from_str(format!("Ignoring unknown fields in body: {:?}", unused_elements).as_str())
.expect("Unable to create Warning header value"));
}
{{/consumesPlainText}}{{/vendorExtensions}}{{/bodyParams}}
match result {
@ -435,13 +480,20 @@ where
{{/-last}}
{{/headers}}{{/dataType}}
=> {
response.set_status(StatusCode::try_from({{{code}}}).unwrap());
*response.status_mut() = StatusCode::from_u16({{{code}}}).expect("Unable to turn {{{code}}} into a StatusCode");
{{#headers}}
header! { (Response{{{nameInCamelCase}}}, "{{{baseName}}}") => [{{{dataType}}}] }
response.headers_mut().set(Response{{{nameInCamelCase}}}({{{name}}}));
response.headers_mut().insert(
HeaderName::from_static("{{{nameInLowerCase}}}"),
swagger::IntoHeaderValue({{name}}).into()
);
{{/headers}}
{{#produces}}{{#-first}}{{#dataType}}
response.headers_mut().set(ContentType(mimetypes::responses::{{#vendorExtensions}}{{{uppercase_operation_id}}}_{{x-uppercaseResponseId}}{{/vendorExtensions}}.clone()));
{{#vendorExtensions}}
response.headers_mut().insert(
CONTENT_TYPE,
HeaderValue::from_str(mimetypes::responses::{{{uppercase_operation_id}}}_{{x-uppercaseResponseId}})
.expect("Unable to create Content-Type header for {{{uppercase_operation_id}}}_{{x-uppercaseResponseId}}"));
{{/vendorExtensions}}
{{/dataType}}{{/-first}}{{/produces}}
{{#dataType}}
{{#vendorExtensions}}
@ -466,7 +518,7 @@ where
let body = body;
{{/producesPlainText}}
{{/vendorExtensions}}
response.set_body(body);
*response.body_mut() = Body::from(body);
{{/dataType}}
},
{{/responses}}
@ -474,8 +526,8 @@ where
Err(_) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.set_status(StatusCode::InternalServerError);
response.set_body("An internal error occurred");
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
*response.body_mut() = Body::from("An internal error occurred");
},
}
@ -486,25 +538,31 @@ where
{{^consumesMultipart}}
{{^bodyParams}}
}}
}) as Box<dyn Future<Item=Response, Error=Error>>
}) as Self::Future
{{/bodyParams}}
{{/consumesMultipart}}
{{/vendorExtensions}}
{{#bodyParams}}
{{#-first}}
},
Err(e) => Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't read body parameter {{{baseName}}}: {}", e)))),
Err(e) => Box::new(future::ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("Couldn't read body parameter {{{baseName}}}: {}", e)))
.expect("Unable to create Bad Request response due to unable to read body parameter {{{baseName}}}"))),
}
})
) as Box<dyn Future<Item=Response, Error=Error>>
) as Self::Future
{{/-first}}
{{/bodyParams}}
{{#vendorExtensions}}
{{#consumesMultipart}}
{{^bodyParams}}
as Box<dyn Future<Item=Response, Error=Error>>
as Self::Future
},
Err(e) => Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't read multipart body")))),
Err(e) => Box::new(future::ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("Couldn't read multipart body")))
.expect("Unable to create Bad Request response due to unable read multipart body"))),
}
})
)
@ -513,12 +571,16 @@ where
{{/vendorExtensions}}
},
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
_ => Box::new(future::ok(Response::new().with_status(StatusCode::NotFound))) as Box<dyn Future<Item=Response, Error=Error>>,
_ => Box::new(future::ok(
Response::builder().status(StatusCode::NOT_FOUND)
.body(Body::empty())
.expect("Unable to create Not Found response")
)) as Self::Future
}
}
}
impl<T, C> Clone for Service<T, C>
impl<T, C> Clone for Service<T, C> where T: Clone
{
fn clone(&self) -> Self {
Service {
@ -528,24 +590,10 @@ impl<T, C> Clone for Service<T, C>
}
}
{{#apiUsesMultipart}}
/// Utility function to get the multipart boundary marker (if any) from the Headers.
fn multipart_boundary<'a>(headers: &'a Headers) -> Option<&'a str> {
headers.get::<ContentType>().and_then(|content_type| {
let ContentType(ref mime) = *content_type;
if mime.type_() == hyper::mime::MULTIPART && mime.subtype() == hyper::mime::FORM_DATA {
mime.get_param(hyper::mime::BOUNDARY).map(|x| x.as_str())
} else {
None
}
})
}
{{/apiUsesMultipart}}
/// Request parser for `Api`.
pub struct ApiRequestParser;
impl RequestParser for ApiRequestParser {
fn parse_operation_id(request: &Request) -> Result<&'static str, ()> {
impl<T> RequestParser<T> for ApiRequestParser {
fn parse_operation_id(request: &Request<T>) -> Result<&'static str, ()> {
let path = paths::GLOBAL_REGEX_SET.matches(request.uri().path());
match request.method() {
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}

View File

@ -7,44 +7,50 @@ license = "Unlicense"
[features]
default = ["client", "server"]
client = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url"]
server = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url"]
client = [
"multipart", "multipart/client", "swagger/multipart",
"serde_json", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio", "url"
]
server = [
"multipart", "multipart/server",
"serde_json", "serde_ignored", "hyper", "native-tls", "openssl", "tokio", "tokio-tls", "regex", "percent-encoding", "url", "lazy_static"
]
conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"]
[dependencies]
# Common
chrono = { version = "0.4", features = ["serde"] }
futures = "0.1"
swagger = "2"
lazy_static = "1.4"
swagger = "3.0"
log = "0.3.0"
mime = "0.2.6"
multipart = "0.13.3"
mime = "0.3"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
# Crates included if required by the API definition
mime_0_2 = { package = "mime", version = "0.2.6" }
multipart = { version = "0.16", default-features = false, optional = true }
# Common between server and client features
hyper = {version = "0.11", optional = true}
hyper-tls = {version = "0.1.2", optional = true}
hyper = {version = "0.12", optional = true}
hyper-tls = {version = "0.2.1", optional = true}
native-tls = {version = "0.1.4", optional = true}
openssl = {version = "0.9.14", optional = true}
serde_json = {version = "1.0", optional = true}
serde_ignored = {version = "0.0.4", optional = true}
tokio-core = {version = "0.1.6", optional = true}
tokio = {version = "0.1.17", optional = true}
url = {version = "1.5", optional = true}
# Client-specific
# Server-specific
lazy_static = { version = "1.4", optional = true }
percent-encoding = {version = "1.0.0", optional = true}
regex = {version = "0.2", optional = true}
tokio-proto = {version = "0.1.1", optional = true}
tokio-tls = {version = "0.1.3", optional = true, features = ["tokio-proto"]}
tokio-tls = {version = "0.1.3", optional = true}
# Other optional crates
# Conversion
frunk = { version = "0.3.0", optional = true }
frunk_derives = { version = "0.3.0", optional = true }
frunk_core = { version = "0.3.0", optional = true }

View File

@ -1,23 +1,18 @@
#![allow(missing_docs, unused_variables, trivial_casts)]
extern crate multipart_v3;
#[allow(unused_extern_crates)]
extern crate futures;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate swagger;
#[allow(unused_extern_crates)]
extern crate clap;
extern crate tokio_core;
extern crate uuid;
extern crate tokio;
use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData};
#[allow(unused_imports)]
use futures::{Future, future, Stream, stream};
use tokio_core::reactor;
#[allow(unused_imports)]
use multipart_v3::{ApiNoContext, ContextWrapperExt,
use multipart_v3::{Api, ApiNoContext, Client, ContextWrapperExt,
ApiError,
MultipartRequestPostResponse
};
@ -28,8 +23,10 @@ fn main() {
.arg(Arg::with_name("operation")
.help("Sets the operation to run")
.possible_values(&[
"MultipartRequestPost",
])
"MultipartRequestPost",
])
.required(true)
.index(1))
.arg(Arg::with_name("https")
@ -47,36 +44,45 @@ fn main() {
.help("Port to contact"))
.get_matches();
let mut core = reactor::Core::new().unwrap();
let is_https = matches.is_present("https");
let base_url = format!("{}://{}:{}",
if is_https { "https" } else { "http" },
matches.value_of("host").unwrap(),
matches.value_of("port").unwrap());
let client = if matches.is_present("https") {
// Using Simple HTTPS
multipart_v3::Client::try_new_https(core.handle(), &base_url, "examples/ca.pem")
Client::try_new_https(
&base_url,
"examples/ca.pem")
.expect("Failed to create HTTPS client")
} else {
// Using HTTP
multipart_v3::Client::try_new_http(core.handle(), &base_url)
Client::try_new_http(
&base_url)
.expect("Failed to create HTTP client")
};
let context: make_context_ty!(ContextBuilder, EmptyContext, Option<AuthData>, XSpanIdString) =
make_context!(ContextBuilder, EmptyContext, None as Option<AuthData>, XSpanIdString(self::uuid::Uuid::new_v4().to_string()));
make_context!(ContextBuilder, EmptyContext, None as Option<AuthData>, XSpanIdString::default());
let client = client.with_context(context);
match matches.value_of("operation") {
Some("MultipartRequestPost") => {
let result = core.run(client.multipart_request_post("string_field_example".to_string(), swagger::ByteArray(Vec::from("BYTE_ARRAY_DATA_HERE")), Some("optional_string_field_example".to_string()), None));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.multipart_request_post(
"string_field_example".to_string(),
swagger::ByteArray(Vec::from("BYTE_ARRAY_DATA_HERE")),
Some("optional_string_field_example".to_string()),
None
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
_ => {
panic!("Invalid operation provided")
}
}
}

View File

@ -8,9 +8,9 @@ extern crate multipart_v3;
extern crate swagger;
extern crate hyper;
extern crate openssl;
extern crate native_tls;
extern crate tokio_proto;
extern crate tokio;
extern crate tokio_tls;
extern crate native_tls;
extern crate clap;
// Imports required by server library.
@ -21,14 +21,18 @@ extern crate chrono;
#[macro_use]
extern crate error_chain;
use futures::{Future, Stream};
use hyper::service::MakeService;
use hyper::server::conn::Http;
use openssl::x509::X509_FILETYPE_PEM;
use openssl::ssl::{SslAcceptorBuilder, SslMethod};
use openssl::error::ErrorStack;
use hyper::server::Http;
use tokio_proto::TcpServer;
use tokio::net::TcpListener;
use clap::{App, Arg};
use swagger::auth::AllowAllAuthenticator;
use std::sync::{Arc, Mutex};
use swagger::auth::MakeAllowAllAuthenticator;
use swagger::EmptyContext;
use tokio_tls::TlsAcceptorExt;
mod server_lib;
@ -53,12 +57,15 @@ fn main() {
.help("Whether to use HTTPS or not"))
.get_matches();
let server = server_lib::Server::new();
let service_fn = multipart_v3::server::MakeService::new(server);
let service_fn = MakeAllowAllAuthenticator::new(service_fn, "cosmo");
let service_fn =
multipart_v3::server::context::NewAddContext::<_, EmptyContext>::new(
AllowAllAuthenticator::new(
server_lib::NewService::new(),
"cosmo"
)
multipart_v3::server::context::MakeAddContext::<_, EmptyContext>::new(
service_fn
);
let addr = "127.0.0.1:80".parse().expect("Failed to parse bind address");
@ -66,9 +73,29 @@ fn main() {
let ssl = ssl().expect("Failed to load SSL keys");
let builder: native_tls::TlsAcceptorBuilder = native_tls::backend::openssl::TlsAcceptorBuilderExt::from_openssl(ssl);
let tls_acceptor = builder.build().expect("Failed to build TLS acceptor");
TcpServer::new(tokio_tls::proto::Server::new(Http::new(), tls_acceptor), addr).serve(service_fn);
let service_fn = Arc::new(Mutex::new(service_fn));
let tls_listener = TcpListener::bind(&addr).unwrap().incoming().for_each(move |tcp| {
let addr = tcp.peer_addr().expect("Unable to get remote address");
let service_fn = service_fn.clone();
hyper::rt::spawn(tls_acceptor.accept_async(tcp).map_err(|_| ()).and_then(move |tls| {
let ms = {
let mut service_fn = service_fn.lock().unwrap();
service_fn.make_service(&addr)
};
ms.and_then(move |service| {
Http::new().serve_connection(tls, service)
}).map_err(|_| ())
}));
Ok(())
}).map_err(|_| ());
hyper::rt::run(tls_listener);
} else {
// Using HTTP
TcpServer::new(Http::new(), addr).serve(service_fn);
hyper::rt::run(hyper::server::Server::bind(&addr).serve(service_fn).map_err(|e| panic!("{:?}", e)));
}
}

View File

@ -1,37 +1,44 @@
//! Main library entry point for multipart_v3 implementation.
mod server;
#![allow(unused_imports)]
mod errors {
error_chain!{}
}
pub use self::errors::*;
use std::io;
use std::clone::Clone;
use futures::{self, Future};
use chrono;
use std::collections::HashMap;
use std::marker::PhantomData;
use hyper;
use multipart_v3;
use swagger;
use swagger::{Has, XSpanIdString};
pub struct NewService<C>{
marker: PhantomData<C>
use multipart_v3::{Api, ApiError,
MultipartRequestPostResponse
};
use multipart_v3::models;
#[derive(Copy, Clone)]
pub struct Server<C> {
marker: PhantomData<C>,
}
impl<C> NewService<C>{
impl<C> Server<C> {
pub fn new() -> Self {
NewService{marker:PhantomData}
Server{marker: PhantomData}
}
}
impl<C> hyper::server::NewService for NewService<C> where C: Has<XSpanIdString> + Clone + 'static {
type Request = (hyper::Request, C);
type Response = hyper::Response;
type Error = hyper::Error;
type Instance = multipart_v3::server::Service<server::Server<C>, C>;
impl<C> Api<C> for Server<C> where C: Has<XSpanIdString>{
/// Instantiate a new server.
fn new_service(&self) -> io::Result<Self::Instance> {
Ok(multipart_v3::server::Service::new(server::Server::new()))
fn multipart_request_post(&self, string_field: String, binary_field: swagger::ByteArray, optional_string_field: Option<String>, object_field: Option<models::MultipartRequestObjectField>, context: &C) -> Box<Future<Item=MultipartRequestPostResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("multipart_request_post(\"{}\", {:?}, {:?}, {:?}) - X-Span-ID: {:?}", string_field, binary_field, optional_string_field, object_field, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
}

View File

@ -1,22 +1,18 @@
#![allow(unused_extern_crates)]
extern crate tokio_core;
extern crate native_tls;
extern crate hyper_tls;
extern crate openssl;
extern crate mime;
extern crate chrono;
extern crate url;
extern crate multipart;
use hyper;
use hyper::header::{Headers, ContentType};
use hyper::Uri;
use self::url::percent_encoding::{utf8_percent_encode, PATH_SEGMENT_ENCODE_SET, QUERY_ENCODE_SET};
use hyper::client::HttpConnector;
use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE};
use hyper::{Body, Uri, Response};
use hyper_tls::HttpsConnector;
use url::form_urlencoded;
use url::percent_encoding::{utf8_percent_encode, PATH_SEGMENT_ENCODE_SET, QUERY_ENCODE_SET};
use futures;
use futures::{Future, Stream};
use futures::{future, stream};
use self::tokio_core::reactor::Handle;
use serde_json;
use std::borrow::Cow;
#[allow(unused_imports)]
use std::collections::{HashMap, BTreeMap};
use std::io::{Read, Error, ErrorKind};
use std::error;
use std::fmt;
@ -25,22 +21,19 @@ use std::sync::Arc;
use std::str;
use std::str::FromStr;
use std::string::ToString;
use hyper::mime::Mime;
use std::io::Cursor;
use client::multipart::client::lazy::Multipart;
use mimetypes;
use serde_json;
#[allow(unused_imports)]
use std::collections::{HashMap, BTreeMap};
#[allow(unused_imports)]
use swagger;
use swagger::{ApiError, XSpanIdString, Has, AuthData};
use swagger::client::Service;
use swagger::{ApiError, XSpanId, XSpanIdString, Has, AuthData};
use mime::Mime;
use std::io::Cursor;
use multipart::client::lazy::Multipart;
use {Api,
MultipartRequestPostResponse
};
use mimetypes;
use models;
define_encode_set! {
@ -56,7 +49,7 @@ fn into_base_path(input: &str, correct_scheme: Option<&'static str>) -> Result<S
// First convert to Uri, since a base path is a subset of Uri.
let uri = Uri::from_str(input)?;
let scheme = uri.scheme().ok_or(ClientInitError::InvalidScheme)?;
let scheme = uri.scheme_part().ok_or(ClientInitError::InvalidScheme)?;
// Check the scheme if necessary
if let Some(correct_scheme) = correct_scheme {
@ -66,104 +59,36 @@ fn into_base_path(input: &str, correct_scheme: Option<&'static str>) -> Result<S
}
let host = uri.host().ok_or_else(|| ClientInitError::MissingHost)?;
let port = uri.port().map(|x| format!(":{}", x)).unwrap_or_default();
let port = uri.port_part().map(|x| format!(":{}", x)).unwrap_or_default();
Ok(format!("{}://{}{}", scheme, host, port))
}
/// A client that implements the API by making HTTP calls out to a server.
pub struct Client<F> where
F: Future<Item=hyper::Response, Error=hyper::Error> + 'static {
client_service: Arc<Box<dyn hyper::client::Service<Request=hyper::Request<hyper::Body>, Response=hyper::Response, Error=hyper::Error, Future=F>>>,
pub struct Client<F>
{
client_service: Arc<Box<dyn Service<ReqBody=Body, Future=F> + Send + Sync>>,
base_path: String,
}
impl<F> fmt::Debug for Client<F> where
F: Future<Item=hyper::Response, Error=hyper::Error> + 'static {
impl<F> fmt::Debug for Client<F>
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Client {{ base_path: {} }}", self.base_path)
}
}
impl<F> Clone for Client<F> where
F: Future<Item=hyper::Response, Error=hyper::Error> + 'static {
impl<F> Clone for Client<F>
{
fn clone(&self) -> Self {
Client {
client_service: self.client_service.clone(),
base_path: self.base_path.clone()
base_path: self.base_path.clone(),
}
}
}
impl Client<hyper::client::FutureResponse> {
/// Create an HTTP client.
///
/// # Arguments
/// * `handle` - tokio reactor handle to use for execution
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
pub fn try_new_http(handle: Handle, base_path: &str) -> Result<Client<hyper::client::FutureResponse>, ClientInitError> {
let http_connector = swagger::http_connector();
Self::try_new_with_connector::<hyper::client::HttpConnector>(
handle,
base_path,
Some("http"),
http_connector,
)
}
/// Create a client with a TLS connection to the server.
///
/// # Arguments
/// * `handle` - tokio reactor handle to use for execution
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
/// * `ca_certificate` - Path to CA certificate used to authenticate the server
pub fn try_new_https<CA>(
handle: Handle,
base_path: &str,
ca_certificate: CA,
) -> Result<Client<hyper::client::FutureResponse>, ClientInitError>
where
CA: AsRef<Path>,
{
let https_connector = swagger::https_connector(ca_certificate);
Self::try_new_with_connector::<hyper_tls::HttpsConnector<hyper::client::HttpConnector>>(
handle,
base_path,
Some("https"),
https_connector,
)
}
/// Create a client with a mutually authenticated TLS connection to the server.
///
/// # Arguments
/// * `handle` - tokio reactor handle to use for execution
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
/// * `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
pub fn try_new_https_mutual<CA, K, C>(
handle: Handle,
base_path: &str,
ca_certificate: CA,
client_key: K,
client_certificate: C,
) -> Result<Client<hyper::client::FutureResponse>, ClientInitError>
where
CA: AsRef<Path>,
K: AsRef<Path>,
C: AsRef<Path>,
{
let https_connector =
swagger::https_mutual_connector(ca_certificate, client_key, client_certificate);
Self::try_new_with_connector::<hyper_tls::HttpsConnector<hyper::client::HttpConnector>>(
handle,
base_path,
Some("https"),
https_connector,
)
}
impl Client<hyper::client::ResponseFuture>
{
/// Create a client with a custom implementation of hyper::client::Connect.
///
/// Intended for use with custom implementations of connect for e.g. protocol logging
@ -176,23 +101,21 @@ impl Client<hyper::client::FutureResponse> {
///
/// # Arguments
///
/// * `handle` - tokio reactor handle to use for execution
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
/// * `protocol` - Which protocol to use when constructing the request url, e.g. `Some("http")`
/// * `connector_fn` - Function which returns an implementation of `hyper::client::Connect`
pub fn try_new_with_connector<C>(
handle: Handle,
base_path: &str,
protocol: Option<&'static str>,
connector_fn: Box<dyn Fn(&Handle) -> C + Send + Sync>,
) -> Result<Client<hyper::client::FutureResponse>, ClientInitError>
where
C: hyper::client::Connect + hyper::client::Service,
connector_fn: Box<dyn Fn() -> C + Send + Sync>,
) -> Result<Self, ClientInitError> where
C: hyper::client::connect::Connect + 'static,
C::Transport: 'static,
C::Future: 'static,
{
let connector = connector_fn(&handle);
let client_service = Box::new(hyper::Client::configure().connector(connector).build(
&handle,
));
let connector = connector_fn();
let client_service = Box::new(hyper::client::Client::builder().build(connector));
Ok(Client {
client_service: Arc::new(client_service),
@ -200,40 +123,67 @@ impl Client<hyper::client::FutureResponse> {
})
}
/// Constructor for creating a `Client` by passing in a pre-made `hyper` client.
/// Create an HTTP client.
///
/// One should avoid relying on this function if possible, since it adds a dependency on the underlying transport
/// implementation, which it would be better to abstract away. Therefore, using this function may lead to a loss of
/// code generality, which may make it harder to move the application to a serverless environment, for example.
/// # Arguments
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
pub fn try_new_http(
base_path: &str,
) -> Result<Self, ClientInitError> {
let http_connector = swagger::http_connector();
Self::try_new_with_connector(base_path, Some("http"), http_connector)
}
/// Create a client with a TLS connection to the server.
///
/// The reason for this function's existence is to support legacy test code, which did mocking at the hyper layer.
/// This is not a recommended way to write new tests. If other reasons are found for using this function, they
/// should be mentioned here.
#[deprecated(note="Use try_new_with_client_service instead")]
pub fn try_new_with_hyper_client(
hyper_client: Arc<Box<dyn hyper::client::Service<Request=hyper::Request<hyper::Body>, Response=hyper::Response, Error=hyper::Error, Future=hyper::client::FutureResponse>>>,
handle: Handle,
base_path: &str
) -> Result<Client<hyper::client::FutureResponse>, ClientInitError>
/// # Arguments
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
/// * `ca_certificate` - Path to CA certificate used to authenticate the server
pub fn try_new_https<CA>(
base_path: &str,
ca_certificate: CA,
) -> Result<Self, ClientInitError>
where
CA: AsRef<Path>,
{
Ok(Client {
client_service: hyper_client,
base_path: into_base_path(base_path, None)?,
})
let https_connector = swagger::https_connector(ca_certificate);
Self::try_new_with_connector(base_path, Some("https"), https_connector)
}
/// Create a client with a mutually authenticated TLS connection to the server.
///
/// # Arguments
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
/// * `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
pub fn try_new_https_mutual<CA, K, D>(
base_path: &str,
ca_certificate: CA,
client_key: K,
client_certificate: D,
) -> Result<Self, ClientInitError>
where
CA: AsRef<Path>,
K: AsRef<Path>,
D: AsRef<Path>,
{
let https_connector =
swagger::https_mutual_connector(ca_certificate, client_key, client_certificate);
Self::try_new_with_connector(base_path, Some("https"), https_connector)
}
}
impl<F> Client<F> where
F: Future<Item=hyper::Response, Error=hyper::Error> + 'static
impl<F> Client<F>
{
/// Constructor for creating a `Client` by passing in a pre-made `hyper` client Service.
/// Constructor for creating a `Client` by passing in a pre-made `swagger::client::Service`
///
/// This allows adding custom wrappers around the underlying transport, for example for logging.
pub fn try_new_with_client_service(client_service: Arc<Box<dyn hyper::client::Service<Request=hyper::Request<hyper::Body>, Response=hyper::Response, Error=hyper::Error, Future=F>>>,
handle: Handle,
base_path: &str)
-> Result<Client<F>, ClientInitError>
{
pub fn try_new_with_client_service(
client_service: Arc<Box<dyn Service<ReqBody=Body, Future=F> + Send + Sync>>,
base_path: &str,
) -> Result<Self, ClientInitError> {
Ok(Client {
client_service: client_service,
base_path: into_base_path(base_path, None)?,
@ -241,19 +191,19 @@ impl<F> Client<F> where
}
}
impl<F, C> Api<C> for Client<F> where
F: Future<Item=hyper::Response, Error=hyper::Error> + 'static,
C: Has<XSpanIdString> {
impl<C, F> Api<C> for Client<F> where
C: Has<XSpanIdString> ,
F: Future<Item=Response<Body>, Error=hyper::Error> + Send + 'static
{
fn multipart_request_post(&self, param_string_field: String, param_binary_field: swagger::ByteArray, param_optional_string_field: Option<String>, param_object_field: Option<models::MultipartRequestObjectField>, context: &C) -> Box<dyn Future<Item=MultipartRequestPostResponse, Error=ApiError>> {
fn multipart_request_post(&self, param_string_field: String, param_binary_field: swagger::ByteArray, param_optional_string_field: Option<String>, param_object_field: Option<models::MultipartRequestObjectField>, context: &C) -> Box<dyn Future<Item=MultipartRequestPostResponse, Error=ApiError> + Send> {
let mut uri = format!(
"{}/multipart_request",
self.base_path
);
let mut query_string = self::url::form_urlencoded::Serializer::new("".to_owned());
// Query parameters
let mut query_string = url::form_urlencoded::Serializer::new("".to_owned());
let query_string_str = query_string.finish();
if !query_string_str.is_empty() {
uri += "?";
@ -262,10 +212,16 @@ impl<F, C> Api<C> for Client<F> where
let uri = match Uri::from_str(&uri) {
Ok(uri) => uri,
Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to build URI: {}", err))))),
Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))),
};
let mut request = hyper::Request::new(hyper::Method::Post, uri);
let mut request = match hyper::Request::builder()
.method("POST")
.uri(uri)
.body(Body::empty()) {
Ok(req) => req,
Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e))))
};
let mut multipart = Multipart::new();
@ -273,94 +229,97 @@ impl<F, C> Api<C> for Client<F> where
let string_field_str = match serde_json::to_string(&param_string_field) {
Ok(str) => str,
Err(e) => return Box::new(futures::done(Err(ApiError(format!("Unable to parse string_field to string: {}", e))))),
Err(e) => return Box::new(future::err(ApiError(format!("Unable to parse string_field to string: {}", e)))),
};
let string_field_vec = string_field_str.as_bytes().to_vec();
let string_field_mime = mime::Mime::from_str("application/json").expect("impossible to fail to parse");
let string_field_mime = mime_0_2::Mime::from_str("application/json").expect("impossible to fail to parse");
let string_field_cursor = Cursor::new(string_field_vec);
multipart.add_stream("string_field", string_field_cursor, None as Option<&str>, Some(string_field_mime));
let optional_string_field_str = match serde_json::to_string(&param_optional_string_field) {
Ok(str) => str,
Err(e) => return Box::new(futures::done(Err(ApiError(format!("Unable to parse optional_string_field to string: {}", e))))),
Err(e) => return Box::new(future::err(ApiError(format!("Unable to parse optional_string_field to string: {}", e)))),
};
let optional_string_field_vec = optional_string_field_str.as_bytes().to_vec();
let optional_string_field_mime = mime::Mime::from_str("application/json").expect("impossible to fail to parse");
let optional_string_field_mime = mime_0_2::Mime::from_str("application/json").expect("impossible to fail to parse");
let optional_string_field_cursor = Cursor::new(optional_string_field_vec);
multipart.add_stream("optional_string_field", optional_string_field_cursor, None as Option<&str>, Some(optional_string_field_mime));
let object_field_str = match serde_json::to_string(&param_object_field) {
Ok(str) => str,
Err(e) => return Box::new(futures::done(Err(ApiError(format!("Unable to parse object_field to string: {}", e))))),
Err(e) => return Box::new(future::err(ApiError(format!("Unable to parse object_field to string: {}", e)))),
};
let object_field_vec = object_field_str.as_bytes().to_vec();
let object_field_mime = mime::Mime::from_str("application/json").expect("impossible to fail to parse");
let object_field_mime = mime_0_2::Mime::from_str("application/json").expect("impossible to fail to parse");
let object_field_cursor = Cursor::new(object_field_vec);
multipart.add_stream("object_field", object_field_cursor, None as Option<&str>, Some(object_field_mime));
let binary_field_vec = param_binary_field.to_vec();
let binary_field_mime = match mime::Mime::from_str("application/octet-stream") {
let binary_field_mime = match mime_0_2::Mime::from_str("application/octet-stream") {
Ok(mime) => mime,
Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to get mime type: {:?}", err))))),
Err(err) => return Box::new(future::err(ApiError(format!("Unable to get mime type: {:?}", err)))),
};
let binary_field_cursor = Cursor::new(binary_field_vec);
let filename = None as Option<&str> ;
multipart.add_stream("binary_field", binary_field_cursor, filename, Some(binary_field_mime));
multipart.add_stream("binary_field", binary_field_cursor, filename, Some(binary_field_mime));
let mut fields = match multipart.prepare() {
Ok(fields) => fields,
Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to build request: {}", err))))),
Err(err) => return Box::new(future::err(ApiError(format!("Unable to build request: {}", err)))),
};
let mut body_string = String::new();
fields.to_body().read_to_string(&mut body_string).unwrap();
match fields.read_to_string(&mut body_string) {
Ok(_) => (),
Err(err) => return Box::new(future::err(ApiError(format!("Unable to build body: {}", err)))),
}
let boundary = fields.boundary();
let multipart_header = match Mime::from_str(&format!("multipart/form-data;boundary={}", boundary)) {
Ok(multipart_header) => multipart_header,
Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to build multipart header: {:?}", err))))),
};
let multipart_header = format!("multipart/form-data;boundary={}", boundary);
request.set_body(body_string.into_bytes());
request.headers_mut().set(ContentType(multipart_header));
*request.body_mut() = Body::from(body_string);
request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(&multipart_header) {
Ok(h) => h,
Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", multipart_header, e))))
});
let header = HeaderValue::from_str((context as &dyn Has<XSpanIdString>).get().0.clone().to_string().as_str());
request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header {
Ok(h) => h,
Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e))))
});
request.headers_mut().set(XSpanId((context as &dyn Has<XSpanIdString>).get().0.clone()));
Box::new(self.client_service.call(request)
Box::new(self.client_service.request(request)
.map_err(|e| ApiError(format!("No response received: {}", e)))
.and_then(|mut response| {
match response.status().as_u16() {
201 => {
let body = response.body();
let body = response.into_body();
Box::new(
future::ok(
MultipartRequestPostResponse::OK
)
) as Box<dyn Future<Item=_, Error=_>>
) as Box<dyn Future<Item=_, Error=_> + Send>
},
code => {
let headers = response.headers().clone();
Box::new(response.body()
Box::new(response.into_body()
.take(100)
.concat2()
.then(move |body|
@ -375,7 +334,7 @@ impl<F, C> Api<C> for Client<F> where
Err(e) => Cow::from(format!("<Failed to read body: {}>", e)),
})))
)
) as Box<dyn Future<Item=_, Error=_>>
) as Box<dyn Future<Item=_, Error=_> + Send>
}
}
}))
@ -387,13 +346,13 @@ impl<F, C> Api<C> for Client<F> where
#[derive(Debug)]
pub enum ClientInitError {
InvalidScheme,
InvalidUri(hyper::error::UriError),
InvalidUri(hyper::http::uri::InvalidUri),
MissingHost,
SslError(openssl::error::ErrorStack)
}
impl From<hyper::error::UriError> for ClientInitError {
fn from(err: hyper::error::UriError) -> ClientInitError {
impl From<hyper::http::uri::InvalidUri> for ClientInitError {
fn from(err: hyper::http::uri::InvalidUri) -> ClientInitError {
ClientInitError::InvalidUri(err)
}
}

View File

@ -1,18 +1,17 @@
#![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)]
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
// Crates with macros
#[macro_use]
extern crate serde_derive;
#[cfg(any(feature = "client", feature = "server"))]
#[cfg(any(feature = "server"))]
#[macro_use]
extern crate hyper;
extern crate lazy_static;
#[cfg(any(feature = "client", feature = "server"))]
#[macro_use]
extern crate url;
#[macro_use]
extern crate log;
// Crates for conversion support
#[cfg(feature = "conversion")]
@ -26,12 +25,40 @@ extern crate frunk_core;
extern crate mime;
extern crate serde;
extern crate serde_json;
extern crate futures;
extern crate chrono;
extern crate swagger;
#[cfg(any(feature = "client", feature = "server"))]
extern crate hyper;
#[cfg(any(feature = "client"))]
extern crate hyper_tls;
#[cfg(any(feature = "client", feature = "server"))]
extern crate openssl;
#[cfg(any(feature = "client", feature = "server"))]
extern crate native_tls;
#[cfg(feature = "server")]
extern crate percent_encoding;
#[cfg(any(feature = "client", feature = "server"))]
extern crate serde_json;
#[cfg(any(feature = "client", feature = "server"))]
extern crate serde_ignored;
#[cfg(any(feature = "client", feature = "server"))]
extern crate tokio;
#[cfg(any(feature = "client", feature = "server"))]
#[cfg(any(feature = "client", feature = "server"))]
extern crate multipart;
extern crate mime_0_2;
#[cfg(any(feature = "client", feature = "server"))]
use hyper::header::HeaderValue;
use futures::Stream;
use std::io::Error;
@ -61,7 +88,7 @@ pub enum MultipartRequestPostResponse {
pub trait Api<C> {
fn multipart_request_post(&self, string_field: String, binary_field: swagger::ByteArray, optional_string_field: Option<String>, object_field: Option<models::MultipartRequestObjectField>, context: &C) -> Box<dyn Future<Item=MultipartRequestPostResponse, Error=ApiError>>;
fn multipart_request_post(&self, string_field: String, binary_field: swagger::ByteArray, optional_string_field: Option<String>, object_field: Option<models::MultipartRequestObjectField>, context: &C) -> Box<dyn Future<Item=MultipartRequestPostResponse, Error=ApiError> + Send>;
}
@ -69,7 +96,7 @@ pub trait Api<C> {
pub trait ApiNoContext {
fn multipart_request_post(&self, string_field: String, binary_field: swagger::ByteArray, optional_string_field: Option<String>, object_field: Option<models::MultipartRequestObjectField>) -> Box<dyn Future<Item=MultipartRequestPostResponse, Error=ApiError>>;
fn multipart_request_post(&self, string_field: String, binary_field: swagger::ByteArray, optional_string_field: Option<String>, object_field: Option<models::MultipartRequestObjectField>) -> Box<dyn Future<Item=MultipartRequestPostResponse, Error=ApiError> + Send>;
}
@ -88,7 +115,7 @@ impl<'a, T: Api<C> + Sized, C> ContextWrapperExt<'a, C> for T {
impl<'a, T: Api<C>, C> ApiNoContext for ContextWrapper<'a, T, C> {
fn multipart_request_post(&self, string_field: String, binary_field: swagger::ByteArray, optional_string_field: Option<String>, object_field: Option<models::MultipartRequestObjectField>) -> Box<dyn Future<Item=MultipartRequestPostResponse, Error=ApiError>> {
fn multipart_request_post(&self, string_field: String, binary_field: swagger::ByteArray, optional_string_field: Option<String>, object_field: Option<models::MultipartRequestObjectField>) -> Box<dyn Future<Item=MultipartRequestPostResponse, Error=ApiError> + Send> {
self.api().multipart_request_post(string_field, binary_field, optional_string_field, object_field, &self.context())
}

View File

@ -1,18 +1,10 @@
/// mime types for requests and responses
pub mod responses {
use hyper::mime::*;
// The macro is called per-operation to beat the recursion limit
}
pub mod requests {
use hyper::mime::*;
lazy_static! {
/// Create Mime objects for the request content types for MultipartRequestPost
pub static ref MULTIPART_REQUEST_POST: Mime = "multipart/form-data".parse().unwrap();
}
}

View File

@ -1,5 +1,4 @@
#![allow(unused_imports, unused_qualifications, unused_extern_crates)]
extern crate chrono;
#![allow(unused_imports, unused_qualifications)]
use serde::ser::Serializer;

View File

@ -1,64 +1,86 @@
use futures::Future;
use hyper;
use hyper::header::HeaderName;
use hyper::{Error, Request, Response, StatusCode, service::Service, body::Payload};
use url::form_urlencoded;
use std::default::Default;
use std::io;
use std::marker::PhantomData;
use 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 swagger::auth::{AuthData, Authorization, Bearer, Scopes};
use swagger::context::ContextualPayload;
use swagger::{EmptyContext, Has, Pop, Push, XSpanIdString};
use Api;
pub struct NewAddContext<T, A>
{
pub struct MakeAddContext<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,
impl<T, A, B, C, D> MakeAddContext<T, A>
where
A: Default + Push<XSpanIdString, Result = B>,
B: Push<Option<AuthData>, Result = C>,
C: Push<Option<Authorization>, Result = D>,
{
pub fn new(inner: T) -> NewAddContext<T, A> {
NewAddContext {
pub fn new(inner: T) -> MakeAddContext<T, A> {
MakeAddContext {
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,
// Make a service that adds context.
impl<'a, T, SC, A, B, C, D, E, ME, S, OB, F> hyper::service::MakeService<&'a SC> for
MakeAddContext<T, A>
where
A: Default + Push<XSpanIdString, Result = B>,
B: Push<Option<AuthData>, Result = C>,
C: Push<Option<Authorization>, Result = D>,
D: Send + 'static,
T: hyper::service::MakeService<
&'a SC,
Error = E,
MakeError = ME,
Service = S,
ReqBody = ContextualPayload<hyper::Body, D>,
ResBody = OB,
Future = F
>,
S: Service<
Error = E,
ReqBody = ContextualPayload<hyper::Body, D>,
ResBody = OB> + 'static,
ME: swagger::ErrorBound,
E: swagger::ErrorBound,
F: Future<Item=S, Error=ME> + Send + 'static,
S::Future: Send,
OB: Payload,
{
type Request = Request;
type Response = Response;
type Error = Error;
type Instance = AddContext<T::Instance, A>;
type ReqBody = hyper::Body;
type ResBody = OB;
type Error = E;
type MakeError = ME;
type Service = AddContext<S, A>;
type Future = Box<dyn Future<Item = Self::Service, Error = ME> + Send + 'static>;
fn new_service(&self) -> Result<Self::Instance, io::Error> {
self.inner.new_service().map(|s| AddContext::new(s))
fn make_service(&mut self, ctx: &'a SC) -> Self::Future {
Box::new(self.inner.make_service(ctx).map(|s| AddContext::new(s)))
}
}
/// Middleware to extract authentication data from request
pub struct AddContext<T, A>
{
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>,
where
A: Default + Push<XSpanIdString, Result = B>,
B: Push<Option<AuthData>, Result = C>,
C: Push<Option<Authorization>, Result = D>,
T: Service,
{
pub fn new(inner: T) -> AddContext<T, A> {
AddContext {
@ -68,24 +90,33 @@ impl<T, A, B, C, D> AddContext<T, A>
}
}
impl<T, A, B, C, D> hyper::server::Service for AddContext<T, A>
impl<T, A, B, C, D> Service for AddContext<T, A>
where
A: Default + Push<XSpanIdString, Result=B>,
B: Push<Option<AuthData>, Result=C>,
C: Push<Option<Authorization>, Result=D>,
T: hyper::server::Service<Request = (Request, D), Response = Response, Error = Error>,
D: Send + 'static,
T: Service<ReqBody = ContextualPayload<hyper::Body, D>>,
T::Future: Future<Item=Response<T::ResBody>, Error=T::Error> + Send + 'static
{
type Request = Request;
type Response = Response;
type Error = Error;
type Future = T::Future;
type ReqBody = hyper::Body;
type ResBody = T::ResBody;
type Error = T::Error;
type Future = Box<dyn Future<Item=Response<T::ResBody>, Error=T::Error> + Send + 'static>;
fn call(&self, req: Self::Request) -> Self::Future {
fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future {
let context = A::default().push(XSpanIdString::get_or_generate(&req));
let (head, body) = req.into_parts();
let headers = head.headers.clone();
let context = context.push(None::<AuthData>);
let context = context.push(None::<Authorization>);
return self.inner.call((req, context));
let body = ContextualPayload {
inner: body,
context: context,
};
Box::new(self.inner.call(hyper::Request::from_parts(head, body)))
}
}

View File

@ -1,209 +1,261 @@
#![allow(unused_extern_crates)]
extern crate serde_ignored;
extern crate tokio_core;
extern crate native_tls;
extern crate hyper_tls;
extern crate openssl;
extern crate mime;
extern crate chrono;
extern crate percent_encoding;
extern crate url;
extern crate multipart;
use std::sync::Arc;
#[allow(unused_imports)]
use std::collections::{HashMap, BTreeMap, BTreeSet};
use std::marker::PhantomData;
use futures::{Future, future, Stream, stream};
use hyper;
use hyper::{Request, Response, Error, StatusCode};
use hyper::header::{Headers, ContentType};
use self::url::form_urlencoded;
use mimetypes;
use self::multipart::server::Multipart;
use self::multipart::server::save::SaveResult;
use std::fs;
use hyper::{Request, Response, Error, StatusCode, Body, HeaderMap};
use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE};
use serde_json;
#[allow(unused_imports)]
use std::collections::{HashMap, BTreeMap};
use std::io;
#[allow(unused_imports)]
use swagger;
use std::io;
use swagger::{ApiError, XSpanIdString, Has, RequestParser};
use swagger::auth::Scopes;
use swagger::context::ContextualPayload;
use url::form_urlencoded;
use multipart::server::Multipart;
use multipart::server::save::SaveResult;
#[allow(unused_imports)]
use std::collections::BTreeSet;
use mimetypes;
pub use swagger::auth::Authorization;
use swagger::{ApiError, XSpanId, XSpanIdString, Has, RequestParser};
use swagger::auth::Scopes;
use {Api,
MultipartRequestPostResponse
};
#[allow(unused_imports)]
use models;
pub mod context;
header! { (Warning, "Warning") => [String] }
mod paths {
extern crate regex;
lazy_static! {
pub static ref GLOBAL_REGEX_SET: regex::RegexSet = regex::RegexSet::new(vec![
r"^/multipart_request$"
]).unwrap();
])
.expect("Unable to create global regex set");
}
pub static ID_MULTIPART_REQUEST: usize = 0;
}
pub struct NewService<T, C> {
api_impl: Arc<T>,
marker: PhantomData<C>,
pub struct MakeService<T, RC> {
api_impl: T,
marker: PhantomData<RC>,
}
impl<T, C> NewService<T, C>
impl<T, RC> MakeService<T, RC>
where
T: Api<C> + Clone + 'static,
C: Has<XSpanIdString> + 'static
T: Api<RC> + Clone + Send + 'static,
RC: Has<XSpanIdString> + 'static
{
pub fn new<U: Into<Arc<T>>>(api_impl: U) -> NewService<T, C> {
NewService{api_impl: api_impl.into(), marker: PhantomData}
pub fn new(api_impl: T) -> Self {
MakeService {
api_impl,
marker: PhantomData
}
}
}
impl<T, C> hyper::server::NewService for NewService<T, C>
impl<'a, T, SC, RC> hyper::service::MakeService<&'a SC> for MakeService<T, RC>
where
T: Api<C> + Clone + 'static,
C: Has<XSpanIdString> + 'static
T: Api<RC> + Clone + Send + 'static,
RC: Has<XSpanIdString> + 'static + Send
{
type Request = (Request, C);
type Response = Response;
type ReqBody = ContextualPayload<Body, RC>;
type ResBody = Body;
type Error = Error;
type Instance = Service<T, C>;
type Service = Service<T, RC>;
type Future = future::FutureResult<Self::Service, Self::MakeError>;
type MakeError = Error;
fn new_service(&self) -> Result<Self::Instance, io::Error> {
Ok(Service::new(self.api_impl.clone()))
fn make_service(&mut self, _ctx: &'a SC) -> Self::Future {
future::FutureResult::from(Ok(Service::new(
self.api_impl.clone(),
)))
}
}
pub struct Service<T, C> {
api_impl: Arc<T>,
marker: PhantomData<C>,
pub struct Service<T, RC> {
api_impl: T,
marker: PhantomData<RC>,
}
impl<T, C> Service<T, C>
impl<T, RC> Service<T, RC>
where
T: Api<C> + Clone + 'static,
C: Has<XSpanIdString> + 'static {
pub fn new<U: Into<Arc<T>>>(api_impl: U) -> Service<T, C> {
Service{api_impl: api_impl.into(), marker: PhantomData}
T: Api<RC> + Clone + Send + 'static,
RC: Has<XSpanIdString> + 'static {
pub fn new(api_impl: T) -> Self {
Service {
api_impl: api_impl,
marker: PhantomData
}
}
}
impl<T, C> hyper::server::Service for Service<T, C>
impl<T, C> hyper::service::Service for Service<T, C>
where
T: Api<C> + Clone + 'static,
C: Has<XSpanIdString> + 'static
T: Api<C> + Clone + Send + 'static,
C: Has<XSpanIdString> + 'static + Send
{
type Request = (Request, C);
type Response = Response;
type ReqBody = ContextualPayload<Body, C>;
type ResBody = Body;
type Error = Error;
type Future = Box<dyn Future<Item=Response, Error=Error>>;
type Future = Box<dyn Future<Item = Response<Self::ResBody>, Error = Self::Error> + Send>;
fn call(&self, (req, mut context): Self::Request) -> Self::Future {
fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future {
let api_impl = self.api_impl.clone();
let (method, uri, _, headers, body) = req.deconstruct();
let (parts, body) = req.into_parts();
let (method, uri, headers) = (parts.method, parts.uri, parts.headers);
let path = paths::GLOBAL_REGEX_SET.matches(uri.path());
let mut context = body.context;
let body = body.inner;
// This match statement is duplicated below in `parse_operation_id()`.
// Please update both places if changing how this code is autogenerated.
match &method {
// MultipartRequestPost - POST /multipart_request
&hyper::Method::Post if path.matched(paths::ID_MULTIPART_REQUEST) => {
let boundary = match multipart_boundary(&headers) {
&hyper::Method::POST if path.matched(paths::ID_MULTIPART_REQUEST) => {
let boundary = match swagger::multipart::boundary(&headers) {
Some(boundary) => boundary.to_string(),
None => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body("Couldn't find valid multipart body"))),
None => return Box::new(future::ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from("Couldn't find valid multipart body".to_string()))
.expect("Unable to create Bad Request response for incorrect boundary"))),
};
// Form Body parameters (note that non-required body parameters will ignore garbage
// values, rather than causing a 400 response). Produce warning header and logs for
// any unused fields.
Box::new(body.concat2()
.then(move |result| -> Box<dyn Future<Item=Response, Error=Error>> {
.then(move |result| -> Self::Future {
match result {
Ok(body) => {
use std::io::Read;
// Read Form Parameters from body
let mut entries = match Multipart::with_body(&body.to_vec()[..], boundary).save().temp() {
SaveResult::Full(entries) => {
entries
},
_ => {
return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Unable to process all message parts"))))
return Box::new(future::ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("Unable to process all message parts")))
.expect("Unable to create Bad Request response due to failure to process all message")))
},
};
let file_string_field = entries.files.remove("string_field");
let param_string_field = match file_string_field {
Some(file) => {
let path = &file[0].path;
let string_field_str = fs::read_to_string(path).expect("Reading saved String should never fail");
let string_field_model: String = match serde_json::from_str(&string_field_str) {
let field_string_field = entries.fields.remove("string_field");
let param_string_field = match field_string_field {
Some(field) => {
let mut reader = field[0].data.readable().expect("Unable to read field for string_field");
let mut data = String::new();
reader.read_to_string(&mut data).expect("Reading saved String should never fail");
let string_field_model: String = match serde_json::from_str(&data) {
Ok(model) => model,
Err(e) => {
return Box::new(future::ok(
Response::new()
.with_status(StatusCode::BadRequest)
.with_body(format!("string_field data does not match API definition: {}", e))))
Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("string_field data does not match API definition: {}", e)))
.expect("Unable to create Bad Request response due to failure to process all message")))
}
};
string_field_model
},
None => {
return Box::new(future::ok(
Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("Missing required form parameter string_field")))
.expect("Unable to create Bad Request due to missing required form parameter string_field")))
}
None => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Missing required form parameter string_field")))),
};
let file_optional_string_field = entries.files.remove("optional_string_field");
let param_optional_string_field = match file_optional_string_field {
Some(file) => {
let path = &file[0].path;
let optional_string_field_str = fs::read_to_string(path).unwrap();
let optional_string_field_model: String = serde_json::from_str(&optional_string_field_str).expect("Impossible to fail to serialise");
Some(optional_string_field_model)
let field_optional_string_field = entries.fields.remove("optional_string_field");
let param_optional_string_field = match field_optional_string_field {
Some(field) => {
let mut reader = field[0].data.readable().expect("Unable to read field for optional_string_field");
Some({
let mut data = String::new();
reader.read_to_string(&mut data).expect("Reading saved String should never fail");
let optional_string_field_model: String = match serde_json::from_str(&data) {
Ok(model) => model,
Err(e) => {
return Box::new(future::ok(
Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("optional_string_field data does not match API definition: {}", e)))
.expect("Unable to create Bad Request response due to failure to process all message")))
}
};
optional_string_field_model
})
},
None => {
None
}
None => None,
};
let file_object_field = entries.files.remove("object_field");
let param_object_field = match file_object_field {
Some(file) => {
let path = &file[0].path;
let object_field_str = fs::read_to_string(path).unwrap();
let object_field_model: models::MultipartRequestObjectField = serde_json::from_str(&object_field_str).expect("Impossible to fail to serialise");
Some(object_field_model)
let field_object_field = entries.fields.remove("object_field");
let param_object_field = match field_object_field {
Some(field) => {
let mut reader = field[0].data.readable().expect("Unable to read field for object_field");
Some({
let mut data = String::new();
reader.read_to_string(&mut data).expect("Reading saved String should never fail");
let object_field_model: models::MultipartRequestObjectField = match serde_json::from_str(&data) {
Ok(model) => model,
Err(e) => {
return Box::new(future::ok(
Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("object_field data does not match API definition: {}", e)))
.expect("Unable to create Bad Request response due to failure to process all message")))
}
};
object_field_model
})
},
None => {
None
}
None => None,
};
let file_binary_field = entries.files.remove("binary_field");
let param_binary_field = match file_binary_field {
Some(file) => {
let path = &file[0].path;
let binary_field_str = fs::read_to_string(path).unwrap();
swagger::ByteArray(binary_field_str.as_bytes().to_vec())
let field_binary_field = entries.fields.remove("binary_field");
let param_binary_field = match field_binary_field {
Some(field) => {
let mut reader = field[0].data.readable().expect("Unable to read field for binary_field");
let mut data = vec![];
reader.read_to_end(&mut data).expect("Reading saved binary data should never fail");
swagger::ByteArray(data)
},
None => {
return Box::new(future::ok(
Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("Missing required form parameter binary_field")))
.expect("Unable to create Bad Request due to missing required form parameter binary_field")))
}
None => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Missing required form parameter binary_field")))),
};
Box::new(api_impl.multipart_request_post(param_string_field, param_binary_field, param_optional_string_field, param_object_field, &context)
.then(move |result| {
let mut response = Response::new();
response.headers_mut().set(XSpanId((&context as &dyn Has<XSpanIdString>).get().0.to_string()));
Box::new(
api_impl.multipart_request_post(
param_string_field,
param_binary_field,
param_optional_string_field,
param_object_field,
&context
).then(move |result| {
let mut response = Response::new(Body::empty());
response.headers_mut().insert(
HeaderName::from_static("x-span-id"),
HeaderValue::from_str((&context as &dyn Has<XSpanIdString>).get().0.clone().to_string().as_str())
.expect("Unable to create X-Span-ID header value"));
match result {
Ok(rsp) => match rsp {
@ -211,35 +263,42 @@ where
=> {
response.set_status(StatusCode::try_from(201).unwrap());
*response.status_mut() = StatusCode::from_u16(201).expect("Unable to turn 201 into a StatusCode");
},
},
Err(_) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.set_status(StatusCode::InternalServerError);
response.set_body("An internal error occurred");
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
*response.body_mut() = Body::from("An internal error occurred");
},
}
future::ok(response)
}
))
as Box<dyn Future<Item=Response, Error=Error>>
as Self::Future
},
Err(e) => Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't read multipart body")))),
Err(e) => Box::new(future::ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("Couldn't read multipart body")))
.expect("Unable to create Bad Request response due to unable read multipart body"))),
}
})
)
},
_ => Box::new(future::ok(Response::new().with_status(StatusCode::NotFound))) as Box<dyn Future<Item=Response, Error=Error>>,
_ => Box::new(future::ok(
Response::builder().status(StatusCode::NOT_FOUND)
.body(Body::empty())
.expect("Unable to create Not Found response")
)) as Self::Future
}
}
}
impl<T, C> Clone for Service<T, C>
impl<T, C> Clone for Service<T, C> where T: Clone
{
fn clone(&self) -> Self {
Service {
@ -249,27 +308,15 @@ impl<T, C> Clone for Service<T, C>
}
}
/// Utility function to get the multipart boundary marker (if any) from the Headers.
fn multipart_boundary<'a>(headers: &'a Headers) -> Option<&'a str> {
headers.get::<ContentType>().and_then(|content_type| {
let ContentType(ref mime) = *content_type;
if mime.type_() == hyper::mime::MULTIPART && mime.subtype() == hyper::mime::FORM_DATA {
mime.get_param(hyper::mime::BOUNDARY).map(|x| x.as_str())
} else {
None
}
})
}
/// Request parser for `Api`.
pub struct ApiRequestParser;
impl RequestParser for ApiRequestParser {
fn parse_operation_id(request: &Request) -> Result<&'static str, ()> {
impl<T> RequestParser<T> for ApiRequestParser {
fn parse_operation_id(request: &Request<T>) -> Result<&'static str, ()> {
let path = paths::GLOBAL_REGEX_SET.matches(request.uri().path());
match request.method() {
// MultipartRequestPost - POST /multipart_request
&hyper::Method::Post if path.matched(paths::ID_MULTIPART_REQUEST) => Ok("MultipartRequestPost"),
&hyper::Method::POST if path.matched(paths::ID_MULTIPART_REQUEST) => Ok("MultipartRequestPost"),
_ => Err(()),
}
}

View File

@ -7,48 +7,50 @@ license = "Unlicense"
[features]
default = ["client", "server"]
client = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url"]
server = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url"]
client = [
"serde_json", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio", "url"
]
server = [
"serde_json", "serde_ignored", "hyper", "native-tls", "openssl", "tokio", "tokio-tls", "regex", "percent-encoding", "url", "lazy_static"
]
conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"]
[dependencies]
# Common
chrono = { version = "0.4", features = ["serde"] }
futures = "0.1"
swagger = "2"
lazy_static = "1.4"
swagger = "3.0"
log = "0.3.0"
mime = "0.2.6"
multipart = "0.13.3"
mime = "0.3"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
# Crates included if required by the API definition
uuid = {version = "0.5", features = ["serde", "v4"]}
# TODO: this should be updated to point at the official crate once
# https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream
serde-xml-rs = {git = "git://github.com/Metaswitch/serde-xml-rs.git" , branch = "master"}
uuid = {version = "0.7", features = ["serde", "v4"]}
# Common between server and client features
hyper = {version = "0.11", optional = true}
hyper-tls = {version = "0.1.2", optional = true}
hyper = {version = "0.12", optional = true}
hyper-tls = {version = "0.2.1", optional = true}
native-tls = {version = "0.1.4", optional = true}
openssl = {version = "0.9.14", optional = true}
serde_json = {version = "1.0", optional = true}
serde_ignored = {version = "0.0.4", optional = true}
tokio-core = {version = "0.1.6", optional = true}
tokio = {version = "0.1.17", optional = true}
url = {version = "1.5", optional = true}
# Client-specific
# Server-specific
lazy_static = { version = "1.4", optional = true }
percent-encoding = {version = "1.0.0", optional = true}
regex = {version = "0.2", optional = true}
tokio-proto = {version = "0.1.1", optional = true}
tokio-tls = {version = "0.1.3", optional = true, features = ["tokio-proto"]}
tokio-tls = {version = "0.1.3", optional = true}
# Other optional crates
# Conversion
frunk = { version = "0.3.0", optional = true }
frunk_derives = { version = "0.3.0", optional = true }
frunk_core = { version = "0.3.0", optional = true }

View File

@ -1,23 +1,18 @@
#![allow(missing_docs, unused_variables, trivial_casts)]
extern crate openapi_v3;
#[allow(unused_extern_crates)]
extern crate futures;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate swagger;
#[allow(unused_extern_crates)]
extern crate clap;
extern crate tokio_core;
extern crate uuid;
extern crate tokio;
use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData};
#[allow(unused_imports)]
use futures::{Future, future, Stream, stream};
use tokio_core::reactor;
#[allow(unused_imports)]
use openapi_v3::{ApiNoContext, ContextWrapperExt,
use openapi_v3::{Api, ApiNoContext, Client, ContextWrapperExt,
ApiError,
MultigetGetResponse,
MultipleAuthSchemeGetResponse,
@ -38,18 +33,30 @@ fn main() {
.arg(Arg::with_name("operation")
.help("Sets the operation to run")
.possible_values(&[
"MultigetGet",
"MultipleAuthSchemeGet",
"ReadonlyAuthSchemeGet",
"RequiredOctetStreamPut",
"ResponsesWithHeadersGet",
"UuidGet",
"XmlExtraPost",
"XmlOtherPost",
"XmlOtherPut",
"XmlPost",
"XmlPut",
])
"MultigetGet",
"MultipleAuthSchemeGet",
"ReadonlyAuthSchemeGet",
"RequiredOctetStreamPut",
"ResponsesWithHeadersGet",
"UuidGet",
"XmlExtraPost",
"XmlOtherPost",
"XmlOtherPut",
"XmlPost",
"XmlPut",
])
.required(true)
.index(1))
.arg(Arg::with_name("https")
@ -67,86 +74,117 @@ fn main() {
.help("Port to contact"))
.get_matches();
let mut core = reactor::Core::new().unwrap();
let is_https = matches.is_present("https");
let base_url = format!("{}://{}:{}",
if is_https { "https" } else { "http" },
matches.value_of("host").unwrap(),
matches.value_of("port").unwrap());
let client = if matches.is_present("https") {
// Using Simple HTTPS
openapi_v3::Client::try_new_https(core.handle(), &base_url, "examples/ca.pem")
Client::try_new_https(
&base_url,
"examples/ca.pem")
.expect("Failed to create HTTPS client")
} else {
// Using HTTP
openapi_v3::Client::try_new_http(core.handle(), &base_url)
Client::try_new_http(
&base_url)
.expect("Failed to create HTTP client")
};
let context: make_context_ty!(ContextBuilder, EmptyContext, Option<AuthData>, XSpanIdString) =
make_context!(ContextBuilder, EmptyContext, None as Option<AuthData>, XSpanIdString(self::uuid::Uuid::new_v4().to_string()));
make_context!(ContextBuilder, EmptyContext, None as Option<AuthData>, XSpanIdString::default());
let client = client.with_context(context);
match matches.value_of("operation") {
Some("MultigetGet") => {
let result = core.run(client.multiget_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.multiget_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("MultipleAuthSchemeGet") => {
let result = core.run(client.multiple_auth_scheme_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.multiple_auth_scheme_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("ReadonlyAuthSchemeGet") => {
let result = core.run(client.readonly_auth_scheme_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.readonly_auth_scheme_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("RequiredOctetStreamPut") => {
let result = core.run(client.required_octet_stream_put(swagger::ByteArray(Vec::from("BYTE_ARRAY_DATA_HERE"))));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.required_octet_stream_put(
swagger::ByteArray(Vec::from("BYTE_ARRAY_DATA_HERE"))
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("ResponsesWithHeadersGet") => {
let result = core.run(client.responses_with_headers_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.responses_with_headers_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("UuidGet") => {
let result = core.run(client.uuid_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.uuid_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("XmlExtraPost") => {
let result = core.run(client.xml_extra_post(None));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.xml_extra_post(
None
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("XmlOtherPost") => {
let result = core.run(client.xml_other_post(None));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.xml_other_post(
None
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("XmlOtherPut") => {
let result = core.run(client.xml_other_put(None));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.xml_other_put(
None
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("XmlPost") => {
let result = core.run(client.xml_post(None));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.xml_post(
None
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("XmlPut") => {
let result = core.run(client.xml_put(None));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.xml_put(
None
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
_ => {
panic!("Invalid operation provided")
}
}
}

View File

@ -8,9 +8,9 @@ extern crate openapi_v3;
extern crate swagger;
extern crate hyper;
extern crate openssl;
extern crate native_tls;
extern crate tokio_proto;
extern crate tokio;
extern crate tokio_tls;
extern crate native_tls;
extern crate clap;
// Imports required by server library.
@ -22,14 +22,18 @@ extern crate chrono;
extern crate error_chain;
extern crate uuid;
use futures::{Future, Stream};
use hyper::service::MakeService;
use hyper::server::conn::Http;
use openssl::x509::X509_FILETYPE_PEM;
use openssl::ssl::{SslAcceptorBuilder, SslMethod};
use openssl::error::ErrorStack;
use hyper::server::Http;
use tokio_proto::TcpServer;
use tokio::net::TcpListener;
use clap::{App, Arg};
use swagger::auth::AllowAllAuthenticator;
use std::sync::{Arc, Mutex};
use swagger::auth::MakeAllowAllAuthenticator;
use swagger::EmptyContext;
use tokio_tls::TlsAcceptorExt;
mod server_lib;
@ -54,12 +58,15 @@ fn main() {
.help("Whether to use HTTPS or not"))
.get_matches();
let server = server_lib::Server::new();
let service_fn = openapi_v3::server::MakeService::new(server);
let service_fn = MakeAllowAllAuthenticator::new(service_fn, "cosmo");
let service_fn =
openapi_v3::server::context::NewAddContext::<_, EmptyContext>::new(
AllowAllAuthenticator::new(
server_lib::NewService::new(),
"cosmo"
)
openapi_v3::server::context::MakeAddContext::<_, EmptyContext>::new(
service_fn
);
let addr = "127.0.0.1:80".parse().expect("Failed to parse bind address");
@ -67,9 +74,29 @@ fn main() {
let ssl = ssl().expect("Failed to load SSL keys");
let builder: native_tls::TlsAcceptorBuilder = native_tls::backend::openssl::TlsAcceptorBuilderExt::from_openssl(ssl);
let tls_acceptor = builder.build().expect("Failed to build TLS acceptor");
TcpServer::new(tokio_tls::proto::Server::new(Http::new(), tls_acceptor), addr).serve(service_fn);
let service_fn = Arc::new(Mutex::new(service_fn));
let tls_listener = TcpListener::bind(&addr).unwrap().incoming().for_each(move |tcp| {
let addr = tcp.peer_addr().expect("Unable to get remote address");
let service_fn = service_fn.clone();
hyper::rt::spawn(tls_acceptor.accept_async(tcp).map_err(|_| ()).and_then(move |tls| {
let ms = {
let mut service_fn = service_fn.lock().unwrap();
service_fn.make_service(&addr)
};
ms.and_then(move |service| {
Http::new().serve_connection(tls, service)
}).map_err(|_| ())
}));
Ok(())
}).map_err(|_| ());
hyper::rt::run(tls_listener);
} else {
// Using HTTP
TcpServer::new(Http::new(), addr).serve(service_fn);
hyper::rt::run(hyper::server::Server::bind(&addr).serve(service_fn).map_err(|e| panic!("{:?}", e)));
}
}

View File

@ -1,38 +1,124 @@
//! Main library entry point for openapi_v3 implementation.
mod server;
#![allow(unused_imports)]
mod errors {
error_chain!{}
}
pub use self::errors::*;
use std::io;
use std::clone::Clone;
use futures::{self, Future};
use chrono;
use std::collections::HashMap;
use std::marker::PhantomData;
use hyper;
use openapi_v3;
use uuid;
use swagger;
use swagger::{Has, XSpanIdString};
use swagger::auth::Authorization;
pub struct NewService<C>{
marker: PhantomData<C>
use openapi_v3::{Api, ApiError,
MultigetGetResponse,
MultipleAuthSchemeGetResponse,
ReadonlyAuthSchemeGetResponse,
RequiredOctetStreamPutResponse,
ResponsesWithHeadersGetResponse,
UuidGetResponse,
XmlExtraPostResponse,
XmlOtherPostResponse,
XmlOtherPutResponse,
XmlPostResponse,
XmlPutResponse
};
use openapi_v3::models;
#[derive(Copy, Clone)]
pub struct Server<C> {
marker: PhantomData<C>,
}
impl<C> NewService<C>{
impl<C> Server<C> {
pub fn new() -> Self {
NewService{marker:PhantomData}
Server{marker: PhantomData}
}
}
impl<C> hyper::server::NewService for NewService<C> where C: Has<XSpanIdString> + Has<Option<Authorization>> + Clone + 'static {
type Request = (hyper::Request, C);
type Response = hyper::Response;
type Error = hyper::Error;
type Instance = openapi_v3::server::Service<server::Server<C>, C>;
impl<C> Api<C> for Server<C> where C: Has<XSpanIdString>{
/// Instantiate a new server.
fn new_service(&self) -> io::Result<Self::Instance> {
Ok(openapi_v3::server::Service::new(server::Server::new()))
/// Get some stuff.
fn multiget_get(&self, context: &C) -> Box<Future<Item=MultigetGetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("multiget_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn multiple_auth_scheme_get(&self, context: &C) -> Box<Future<Item=MultipleAuthSchemeGetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("multiple_auth_scheme_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn readonly_auth_scheme_get(&self, context: &C) -> Box<Future<Item=ReadonlyAuthSchemeGetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("readonly_auth_scheme_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn required_octet_stream_put(&self, body: swagger::ByteArray, context: &C) -> Box<Future<Item=RequiredOctetStreamPutResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("required_octet_stream_put({:?}) - X-Span-ID: {:?}", body, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn responses_with_headers_get(&self, context: &C) -> Box<Future<Item=ResponsesWithHeadersGetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("responses_with_headers_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn uuid_get(&self, context: &C) -> Box<Future<Item=UuidGetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("uuid_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn xml_extra_post(&self, duplicate_xml_object: Option<models::DuplicateXmlObject>, context: &C) -> Box<Future<Item=XmlExtraPostResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("xml_extra_post({:?}) - X-Span-ID: {:?}", duplicate_xml_object, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn xml_other_post(&self, another_xml_object: Option<models::AnotherXmlObject>, context: &C) -> Box<Future<Item=XmlOtherPostResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("xml_other_post({:?}) - X-Span-ID: {:?}", another_xml_object, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn xml_other_put(&self, string: Option<models::AnotherXmlArray>, context: &C) -> Box<Future<Item=XmlOtherPutResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("xml_other_put({:?}) - X-Span-ID: {:?}", string, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// Post an array
fn xml_post(&self, string: Option<models::XmlArray>, context: &C) -> Box<Future<Item=XmlPostResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("xml_post({:?}) - X-Span-ID: {:?}", string, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn xml_put(&self, xml_object: Option<models::XmlObject>, context: &C) -> Box<Future<Item=XmlPutResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("xml_put({:?}) - X-Span-ID: {:?}", xml_object, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
}

View File

@ -1,18 +1,17 @@
#![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)]
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
// Crates with macros
#[macro_use]
extern crate serde_derive;
#[cfg(any(feature = "client", feature = "server"))]
#[cfg(any(feature = "server"))]
#[macro_use]
extern crate hyper;
extern crate lazy_static;
#[cfg(any(feature = "client", feature = "server"))]
#[macro_use]
extern crate url;
#[macro_use]
extern crate log;
// Crates for conversion support
#[cfg(feature = "conversion")]
@ -26,13 +25,37 @@ extern crate frunk_core;
extern crate mime;
extern crate serde;
extern crate serde_json;
extern crate serde_xml_rs;
extern crate futures;
extern crate chrono;
extern crate swagger;
#[cfg(any(feature = "client", feature = "server"))]
extern crate hyper;
#[cfg(any(feature = "client"))]
extern crate hyper_tls;
#[cfg(any(feature = "client", feature = "server"))]
extern crate openssl;
#[cfg(any(feature = "client", feature = "server"))]
extern crate native_tls;
#[cfg(feature = "server")]
extern crate percent_encoding;
#[cfg(any(feature = "client", feature = "server"))]
extern crate serde_json;
#[cfg(any(feature = "client", feature = "server"))]
extern crate serde_ignored;
#[cfg(any(feature = "client", feature = "server"))]
extern crate tokio;
#[cfg(any(feature = "client", feature = "server"))]
extern crate uuid;
extern crate serde_xml_rs;
#[cfg(any(feature = "client", feature = "server"))]
use hyper::header::HeaderValue;
use futures::Stream;
use std::io::Error;
@ -174,37 +197,37 @@ pub enum XmlPutResponse {
pub trait Api<C> {
/// Get some stuff.
fn multiget_get(&self, context: &C) -> Box<dyn Future<Item=MultigetGetResponse, Error=ApiError>>;
fn multiget_get(&self, context: &C) -> Box<dyn Future<Item=MultigetGetResponse, Error=ApiError> + Send>;
fn multiple_auth_scheme_get(&self, context: &C) -> Box<dyn Future<Item=MultipleAuthSchemeGetResponse, Error=ApiError>>;
fn multiple_auth_scheme_get(&self, context: &C) -> Box<dyn Future<Item=MultipleAuthSchemeGetResponse, Error=ApiError> + Send>;
fn readonly_auth_scheme_get(&self, context: &C) -> Box<dyn Future<Item=ReadonlyAuthSchemeGetResponse, Error=ApiError>>;
fn readonly_auth_scheme_get(&self, context: &C) -> Box<dyn Future<Item=ReadonlyAuthSchemeGetResponse, Error=ApiError> + Send>;
fn required_octet_stream_put(&self, body: swagger::ByteArray, context: &C) -> Box<dyn Future<Item=RequiredOctetStreamPutResponse, Error=ApiError>>;
fn required_octet_stream_put(&self, body: swagger::ByteArray, context: &C) -> Box<dyn Future<Item=RequiredOctetStreamPutResponse, Error=ApiError> + Send>;
fn responses_with_headers_get(&self, context: &C) -> Box<dyn Future<Item=ResponsesWithHeadersGetResponse, Error=ApiError>>;
fn responses_with_headers_get(&self, context: &C) -> Box<dyn Future<Item=ResponsesWithHeadersGetResponse, Error=ApiError> + Send>;
fn uuid_get(&self, context: &C) -> Box<dyn Future<Item=UuidGetResponse, Error=ApiError>>;
fn uuid_get(&self, context: &C) -> Box<dyn Future<Item=UuidGetResponse, Error=ApiError> + Send>;
fn xml_extra_post(&self, duplicate_xml_object: Option<models::DuplicateXmlObject>, context: &C) -> Box<dyn Future<Item=XmlExtraPostResponse, Error=ApiError>>;
fn xml_extra_post(&self, duplicate_xml_object: Option<models::DuplicateXmlObject>, context: &C) -> Box<dyn Future<Item=XmlExtraPostResponse, Error=ApiError> + Send>;
fn xml_other_post(&self, another_xml_object: Option<models::AnotherXmlObject>, context: &C) -> Box<dyn Future<Item=XmlOtherPostResponse, Error=ApiError>>;
fn xml_other_post(&self, another_xml_object: Option<models::AnotherXmlObject>, context: &C) -> Box<dyn Future<Item=XmlOtherPostResponse, Error=ApiError> + Send>;
fn xml_other_put(&self, string: Option<models::AnotherXmlArray>, context: &C) -> Box<dyn Future<Item=XmlOtherPutResponse, Error=ApiError>>;
fn xml_other_put(&self, string: Option<models::AnotherXmlArray>, context: &C) -> Box<dyn Future<Item=XmlOtherPutResponse, Error=ApiError> + Send>;
/// Post an array
fn xml_post(&self, string: Option<models::XmlArray>, context: &C) -> Box<dyn Future<Item=XmlPostResponse, Error=ApiError>>;
fn xml_post(&self, string: Option<models::XmlArray>, context: &C) -> Box<dyn Future<Item=XmlPostResponse, Error=ApiError> + Send>;
fn xml_put(&self, xml_object: Option<models::XmlObject>, context: &C) -> Box<dyn Future<Item=XmlPutResponse, Error=ApiError>>;
fn xml_put(&self, xml_object: Option<models::XmlObject>, context: &C) -> Box<dyn Future<Item=XmlPutResponse, Error=ApiError> + Send>;
}
@ -212,37 +235,37 @@ pub trait Api<C> {
pub trait ApiNoContext {
/// Get some stuff.
fn multiget_get(&self) -> Box<dyn Future<Item=MultigetGetResponse, Error=ApiError>>;
fn multiget_get(&self) -> Box<dyn Future<Item=MultigetGetResponse, Error=ApiError> + Send>;
fn multiple_auth_scheme_get(&self) -> Box<dyn Future<Item=MultipleAuthSchemeGetResponse, Error=ApiError>>;
fn multiple_auth_scheme_get(&self) -> Box<dyn Future<Item=MultipleAuthSchemeGetResponse, Error=ApiError> + Send>;
fn readonly_auth_scheme_get(&self) -> Box<dyn Future<Item=ReadonlyAuthSchemeGetResponse, Error=ApiError>>;
fn readonly_auth_scheme_get(&self) -> Box<dyn Future<Item=ReadonlyAuthSchemeGetResponse, Error=ApiError> + Send>;
fn required_octet_stream_put(&self, body: swagger::ByteArray) -> Box<dyn Future<Item=RequiredOctetStreamPutResponse, Error=ApiError>>;
fn required_octet_stream_put(&self, body: swagger::ByteArray) -> Box<dyn Future<Item=RequiredOctetStreamPutResponse, Error=ApiError> + Send>;
fn responses_with_headers_get(&self) -> Box<dyn Future<Item=ResponsesWithHeadersGetResponse, Error=ApiError>>;
fn responses_with_headers_get(&self) -> Box<dyn Future<Item=ResponsesWithHeadersGetResponse, Error=ApiError> + Send>;
fn uuid_get(&self) -> Box<dyn Future<Item=UuidGetResponse, Error=ApiError>>;
fn uuid_get(&self) -> Box<dyn Future<Item=UuidGetResponse, Error=ApiError> + Send>;
fn xml_extra_post(&self, duplicate_xml_object: Option<models::DuplicateXmlObject>) -> Box<dyn Future<Item=XmlExtraPostResponse, Error=ApiError>>;
fn xml_extra_post(&self, duplicate_xml_object: Option<models::DuplicateXmlObject>) -> Box<dyn Future<Item=XmlExtraPostResponse, Error=ApiError> + Send>;
fn xml_other_post(&self, another_xml_object: Option<models::AnotherXmlObject>) -> Box<dyn Future<Item=XmlOtherPostResponse, Error=ApiError>>;
fn xml_other_post(&self, another_xml_object: Option<models::AnotherXmlObject>) -> Box<dyn Future<Item=XmlOtherPostResponse, Error=ApiError> + Send>;
fn xml_other_put(&self, string: Option<models::AnotherXmlArray>) -> Box<dyn Future<Item=XmlOtherPutResponse, Error=ApiError>>;
fn xml_other_put(&self, string: Option<models::AnotherXmlArray>) -> Box<dyn Future<Item=XmlOtherPutResponse, Error=ApiError> + Send>;
/// Post an array
fn xml_post(&self, string: Option<models::XmlArray>) -> Box<dyn Future<Item=XmlPostResponse, Error=ApiError>>;
fn xml_post(&self, string: Option<models::XmlArray>) -> Box<dyn Future<Item=XmlPostResponse, Error=ApiError> + Send>;
fn xml_put(&self, xml_object: Option<models::XmlObject>) -> Box<dyn Future<Item=XmlPutResponse, Error=ApiError>>;
fn xml_put(&self, xml_object: Option<models::XmlObject>) -> Box<dyn Future<Item=XmlPutResponse, Error=ApiError> + Send>;
}
@ -261,57 +284,57 @@ impl<'a, T: Api<C> + Sized, C> ContextWrapperExt<'a, C> for T {
impl<'a, T: Api<C>, C> ApiNoContext for ContextWrapper<'a, T, C> {
/// Get some stuff.
fn multiget_get(&self) -> Box<dyn Future<Item=MultigetGetResponse, Error=ApiError>> {
fn multiget_get(&self) -> Box<dyn Future<Item=MultigetGetResponse, Error=ApiError> + Send> {
self.api().multiget_get(&self.context())
}
fn multiple_auth_scheme_get(&self) -> Box<dyn Future<Item=MultipleAuthSchemeGetResponse, Error=ApiError>> {
fn multiple_auth_scheme_get(&self) -> Box<dyn Future<Item=MultipleAuthSchemeGetResponse, Error=ApiError> + Send> {
self.api().multiple_auth_scheme_get(&self.context())
}
fn readonly_auth_scheme_get(&self) -> Box<dyn Future<Item=ReadonlyAuthSchemeGetResponse, Error=ApiError>> {
fn readonly_auth_scheme_get(&self) -> Box<dyn Future<Item=ReadonlyAuthSchemeGetResponse, Error=ApiError> + Send> {
self.api().readonly_auth_scheme_get(&self.context())
}
fn required_octet_stream_put(&self, body: swagger::ByteArray) -> Box<dyn Future<Item=RequiredOctetStreamPutResponse, Error=ApiError>> {
fn required_octet_stream_put(&self, body: swagger::ByteArray) -> Box<dyn Future<Item=RequiredOctetStreamPutResponse, Error=ApiError> + Send> {
self.api().required_octet_stream_put(body, &self.context())
}
fn responses_with_headers_get(&self) -> Box<dyn Future<Item=ResponsesWithHeadersGetResponse, Error=ApiError>> {
fn responses_with_headers_get(&self) -> Box<dyn Future<Item=ResponsesWithHeadersGetResponse, Error=ApiError> + Send> {
self.api().responses_with_headers_get(&self.context())
}
fn uuid_get(&self) -> Box<dyn Future<Item=UuidGetResponse, Error=ApiError>> {
fn uuid_get(&self) -> Box<dyn Future<Item=UuidGetResponse, Error=ApiError> + Send> {
self.api().uuid_get(&self.context())
}
fn xml_extra_post(&self, duplicate_xml_object: Option<models::DuplicateXmlObject>) -> Box<dyn Future<Item=XmlExtraPostResponse, Error=ApiError>> {
fn xml_extra_post(&self, duplicate_xml_object: Option<models::DuplicateXmlObject>) -> Box<dyn Future<Item=XmlExtraPostResponse, Error=ApiError> + Send> {
self.api().xml_extra_post(duplicate_xml_object, &self.context())
}
fn xml_other_post(&self, another_xml_object: Option<models::AnotherXmlObject>) -> Box<dyn Future<Item=XmlOtherPostResponse, Error=ApiError>> {
fn xml_other_post(&self, another_xml_object: Option<models::AnotherXmlObject>) -> Box<dyn Future<Item=XmlOtherPostResponse, Error=ApiError> + Send> {
self.api().xml_other_post(another_xml_object, &self.context())
}
fn xml_other_put(&self, string: Option<models::AnotherXmlArray>) -> Box<dyn Future<Item=XmlOtherPutResponse, Error=ApiError>> {
fn xml_other_put(&self, string: Option<models::AnotherXmlArray>) -> Box<dyn Future<Item=XmlOtherPutResponse, Error=ApiError> + Send> {
self.api().xml_other_put(string, &self.context())
}
/// Post an array
fn xml_post(&self, string: Option<models::XmlArray>) -> Box<dyn Future<Item=XmlPostResponse, Error=ApiError>> {
fn xml_post(&self, string: Option<models::XmlArray>) -> Box<dyn Future<Item=XmlPostResponse, Error=ApiError> + Send> {
self.api().xml_post(string, &self.context())
}
fn xml_put(&self, xml_object: Option<models::XmlObject>) -> Box<dyn Future<Item=XmlPutResponse, Error=ApiError>> {
fn xml_put(&self, xml_object: Option<models::XmlObject>) -> Box<dyn Future<Item=XmlPutResponse, Error=ApiError> + Send> {
self.api().xml_put(xml_object, &self.context())
}

View File

@ -1,88 +1,55 @@
/// mime types for requests and responses
pub mod responses {
use hyper::mime::*;
// The macro is called per-operation to beat the recursion limit
lazy_static! {
/// Create Mime objects for the response content types for MultigetGet
pub static ref MULTIGET_GET_JSON_RSP: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the response content types for MultigetGet
pub static MULTIGET_GET_JSON_RSP: &str = "application/json";
lazy_static! {
/// Create Mime objects for the response content types for MultigetGet
pub static ref MULTIGET_GET_XML_RSP: Mime = "application/xml".parse().unwrap();
}
/// Create &str objects for the response content types for MultigetGet
pub static MULTIGET_GET_XML_RSP: &str = "application/xml";
lazy_static! {
/// Create Mime objects for the response content types for MultigetGet
pub static ref MULTIGET_GET_OCTET_RSP: Mime = "application/octet-stream".parse().unwrap();
}
/// Create &str objects for the response content types for MultigetGet
pub static MULTIGET_GET_OCTET_RSP: &str = "application/octet-stream";
lazy_static! {
/// Create Mime objects for the response content types for MultigetGet
pub static ref MULTIGET_GET_STRING_RSP: Mime = "text/plain".parse().unwrap();
}
/// Create &str objects for the response content types for MultigetGet
pub static MULTIGET_GET_STRING_RSP: &str = "text/plain";
lazy_static! {
/// Create Mime objects for the response content types for MultigetGet
pub static ref MULTIGET_GET_DUPLICATE_RESPONSE_LONG_TEXT: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the response content types for MultigetGet
pub static MULTIGET_GET_DUPLICATE_RESPONSE_LONG_TEXT: &str = "application/json";
lazy_static! {
/// Create Mime objects for the response content types for MultigetGet
pub static ref MULTIGET_GET_DUPLICATE_RESPONSE_LONG_TEXT_2: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the response content types for MultigetGet
pub static MULTIGET_GET_DUPLICATE_RESPONSE_LONG_TEXT_2: &str = "application/json";
lazy_static! {
/// Create Mime objects for the response content types for MultigetGet
pub static ref MULTIGET_GET_DUPLICATE_RESPONSE_LONG_TEXT_3: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the response content types for MultigetGet
pub static MULTIGET_GET_DUPLICATE_RESPONSE_LONG_TEXT_3: &str = "application/json";
lazy_static! {
/// Create Mime objects for the response content types for ResponsesWithHeadersGet
pub static ref RESPONSES_WITH_HEADERS_GET_SUCCESS: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the response content types for ResponsesWithHeadersGet
pub static RESPONSES_WITH_HEADERS_GET_SUCCESS: &str = "application/json";
lazy_static! {
/// Create Mime objects for the response content types for UuidGet
pub static ref UUID_GET_DUPLICATE_RESPONSE_LONG_TEXT: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the response content types for UuidGet
pub static UUID_GET_DUPLICATE_RESPONSE_LONG_TEXT: &str = "application/json";
}
pub mod requests {
use hyper::mime::*;
lazy_static! {
/// Create Mime objects for the request content types for RequiredOctetStreamPut
pub static ref REQUIRED_OCTET_STREAM_PUT: Mime = "application/octet-stream".parse().unwrap();
}
/// Create &str objects for the request content types for RequiredOctetStreamPut
pub static REQUIRED_OCTET_STREAM_PUT: &str = "application/octet-stream";
lazy_static! {
/// Create Mime objects for the request content types for XmlExtraPost
pub static ref XML_EXTRA_POST: Mime = "application/xml".parse().unwrap();
}
/// Create &str objects for the request content types for XmlExtraPost
pub static XML_EXTRA_POST: &str = "application/xml";
lazy_static! {
/// Create Mime objects for the request content types for XmlOtherPost
pub static ref XML_OTHER_POST: Mime = "application/xml".parse().unwrap();
}
/// Create &str objects for the request content types for XmlOtherPost
pub static XML_OTHER_POST: &str = "application/xml";
lazy_static! {
/// Create Mime objects for the request content types for XmlOtherPut
pub static ref XML_OTHER_PUT: Mime = "application/xml".parse().unwrap();
}
/// Create &str objects for the request content types for XmlOtherPut
pub static XML_OTHER_PUT: &str = "application/xml";
lazy_static! {
/// Create Mime objects for the request content types for XmlPost
pub static ref XML_POST: Mime = "application/xml".parse().unwrap();
}
/// Create &str objects for the request content types for XmlPost
pub static XML_POST: &str = "application/xml";
lazy_static! {
/// Create Mime objects for the request content types for XmlPut
pub static ref XML_PUT: Mime = "application/xml".parse().unwrap();
}
/// Create &str objects for the request content types for XmlPut
pub static XML_PUT: &str = "application/xml";
}

View File

@ -1,5 +1,4 @@
#![allow(unused_imports, unused_qualifications, unused_extern_crates)]
extern crate chrono;
#![allow(unused_imports, unused_qualifications)]
use serde_xml_rs;
use serde::ser::Serializer;

View File

@ -1,64 +1,86 @@
use futures::Future;
use hyper;
use hyper::header::HeaderName;
use hyper::{Error, Request, Response, StatusCode, service::Service, body::Payload};
use url::form_urlencoded;
use std::default::Default;
use std::io;
use std::marker::PhantomData;
use 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 swagger::auth::{AuthData, Authorization, Bearer, Scopes};
use swagger::context::ContextualPayload;
use swagger::{EmptyContext, Has, Pop, Push, XSpanIdString};
use Api;
pub struct NewAddContext<T, A>
{
pub struct MakeAddContext<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,
impl<T, A, B, C, D> MakeAddContext<T, A>
where
A: Default + Push<XSpanIdString, Result = B>,
B: Push<Option<AuthData>, Result = C>,
C: Push<Option<Authorization>, Result = D>,
{
pub fn new(inner: T) -> NewAddContext<T, A> {
NewAddContext {
pub fn new(inner: T) -> MakeAddContext<T, A> {
MakeAddContext {
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,
// Make a service that adds context.
impl<'a, T, SC, A, B, C, D, E, ME, S, OB, F> hyper::service::MakeService<&'a SC> for
MakeAddContext<T, A>
where
A: Default + Push<XSpanIdString, Result = B>,
B: Push<Option<AuthData>, Result = C>,
C: Push<Option<Authorization>, Result = D>,
D: Send + 'static,
T: hyper::service::MakeService<
&'a SC,
Error = E,
MakeError = ME,
Service = S,
ReqBody = ContextualPayload<hyper::Body, D>,
ResBody = OB,
Future = F
>,
S: Service<
Error = E,
ReqBody = ContextualPayload<hyper::Body, D>,
ResBody = OB> + 'static,
ME: swagger::ErrorBound,
E: swagger::ErrorBound,
F: Future<Item=S, Error=ME> + Send + 'static,
S::Future: Send,
OB: Payload,
{
type Request = Request;
type Response = Response;
type Error = Error;
type Instance = AddContext<T::Instance, A>;
type ReqBody = hyper::Body;
type ResBody = OB;
type Error = E;
type MakeError = ME;
type Service = AddContext<S, A>;
type Future = Box<dyn Future<Item = Self::Service, Error = ME> + Send + 'static>;
fn new_service(&self) -> Result<Self::Instance, io::Error> {
self.inner.new_service().map(|s| AddContext::new(s))
fn make_service(&mut self, ctx: &'a SC) -> Self::Future {
Box::new(self.inner.make_service(ctx).map(|s| AddContext::new(s)))
}
}
/// Middleware to extract authentication data from request
pub struct AddContext<T, A>
{
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>,
where
A: Default + Push<XSpanIdString, Result = B>,
B: Push<Option<AuthData>, Result = C>,
C: Push<Option<Authorization>, Result = D>,
T: Service,
{
pub fn new(inner: T) -> AddContext<T, A> {
AddContext {
@ -68,34 +90,49 @@ impl<T, A, B, C, D> AddContext<T, A>
}
}
impl<T, A, B, C, D> hyper::server::Service for AddContext<T, A>
impl<T, A, B, C, D> Service for AddContext<T, A>
where
A: Default + Push<XSpanIdString, Result=B>,
B: Push<Option<AuthData>, Result=C>,
C: Push<Option<Authorization>, Result=D>,
T: hyper::server::Service<Request = (Request, D), Response = Response, Error = Error>,
D: Send + 'static,
T: Service<ReqBody = ContextualPayload<hyper::Body, D>>,
T::Future: Future<Item=Response<T::ResBody>, Error=T::Error> + Send + 'static
{
type Request = Request;
type Response = Response;
type Error = Error;
type Future = T::Future;
type ReqBody = hyper::Body;
type ResBody = T::ResBody;
type Error = T::Error;
type Future = Box<dyn Future<Item=Response<T::ResBody>, Error=T::Error> + Send + 'static>;
fn call(&self, req: Self::Request) -> Self::Future {
fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future {
let context = A::default().push(XSpanIdString::get_or_generate(&req));
let (head, body) = req.into_parts();
let headers = head.headers.clone();
{
use hyper::header::{Authorization as HyperAuth, Basic, Bearer};
use swagger::auth::Bearer;
use std::ops::Deref;
if let Some(bearer) = req.headers().get::<HyperAuth<Bearer>>().cloned() {
let auth_data = AuthData::Bearer(bearer.deref().clone());
if let Some(bearer) = swagger::auth::from_headers::<Bearer>(&headers) {
let auth_data = AuthData::Bearer(bearer);
let context = context.push(Some(auth_data));
let context = context.push(None::<Authorization>);
return self.inner.call((req, context));
let body = ContextualPayload {
inner: body,
context: context,
};
return Box::new(self.inner.call(hyper::Request::from_parts(head, body)));
}
}
let context = context.push(None::<AuthData>);
let context = context.push(None::<Authorization>);
return self.inner.call((req, context));
let body = ContextualPayload {
inner: body,
context: context,
};
Box::new(self.inner.call(hyper::Request::from_parts(head, body)))
}
}

View File

@ -7,44 +7,46 @@ license = "Unlicense"
[features]
default = ["client", "server"]
client = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url"]
server = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url"]
client = [
"serde_json", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio", "url"
]
server = [
"serde_json", "serde_ignored", "hyper", "native-tls", "openssl", "tokio", "tokio-tls", "regex", "percent-encoding", "url", "lazy_static"
]
conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"]
[dependencies]
# Common
chrono = { version = "0.4", features = ["serde"] }
futures = "0.1"
swagger = "2"
lazy_static = "1.4"
swagger = "3.0"
log = "0.3.0"
mime = "0.2.6"
multipart = "0.13.3"
mime = "0.3"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
# Crates included if required by the API definition
# Common between server and client features
hyper = {version = "0.11", optional = true}
hyper-tls = {version = "0.1.2", optional = true}
hyper = {version = "0.12", optional = true}
hyper-tls = {version = "0.2.1", optional = true}
native-tls = {version = "0.1.4", optional = true}
openssl = {version = "0.9.14", optional = true}
serde_json = {version = "1.0", optional = true}
serde_ignored = {version = "0.0.4", optional = true}
tokio-core = {version = "0.1.6", optional = true}
tokio = {version = "0.1.17", optional = true}
url = {version = "1.5", optional = true}
# Client-specific
# Server-specific
lazy_static = { version = "1.4", optional = true }
percent-encoding = {version = "1.0.0", optional = true}
regex = {version = "0.2", optional = true}
tokio-proto = {version = "0.1.1", optional = true}
tokio-tls = {version = "0.1.3", optional = true, features = ["tokio-proto"]}
tokio-tls = {version = "0.1.3", optional = true}
# Other optional crates
# Conversion
frunk = { version = "0.3.0", optional = true }
frunk_derives = { version = "0.3.0", optional = true }
frunk_core = { version = "0.3.0", optional = true }

View File

@ -1,23 +1,18 @@
#![allow(missing_docs, unused_variables, trivial_casts)]
extern crate ops_v3;
#[allow(unused_extern_crates)]
extern crate futures;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate swagger;
#[allow(unused_extern_crates)]
extern crate clap;
extern crate tokio_core;
extern crate uuid;
extern crate tokio;
use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData};
#[allow(unused_imports)]
use futures::{Future, future, Stream, stream};
use tokio_core::reactor;
#[allow(unused_imports)]
use ops_v3::{ApiNoContext, ContextWrapperExt,
use ops_v3::{Api, ApiNoContext, Client, ContextWrapperExt,
ApiError,
Op10GetResponse,
Op11GetResponse,
@ -64,44 +59,82 @@ fn main() {
.arg(Arg::with_name("operation")
.help("Sets the operation to run")
.possible_values(&[
"Op10Get",
"Op11Get",
"Op12Get",
"Op13Get",
"Op14Get",
"Op15Get",
"Op16Get",
"Op17Get",
"Op18Get",
"Op19Get",
"Op1Get",
"Op20Get",
"Op21Get",
"Op22Get",
"Op23Get",
"Op24Get",
"Op25Get",
"Op26Get",
"Op27Get",
"Op28Get",
"Op29Get",
"Op2Get",
"Op30Get",
"Op31Get",
"Op32Get",
"Op33Get",
"Op34Get",
"Op35Get",
"Op36Get",
"Op37Get",
"Op3Get",
"Op4Get",
"Op5Get",
"Op6Get",
"Op7Get",
"Op8Get",
"Op9Get",
])
"Op10Get",
"Op11Get",
"Op12Get",
"Op13Get",
"Op14Get",
"Op15Get",
"Op16Get",
"Op17Get",
"Op18Get",
"Op19Get",
"Op1Get",
"Op20Get",
"Op21Get",
"Op22Get",
"Op23Get",
"Op24Get",
"Op25Get",
"Op26Get",
"Op27Get",
"Op28Get",
"Op29Get",
"Op2Get",
"Op30Get",
"Op31Get",
"Op32Get",
"Op33Get",
"Op34Get",
"Op35Get",
"Op36Get",
"Op37Get",
"Op3Get",
"Op4Get",
"Op5Get",
"Op6Get",
"Op7Get",
"Op8Get",
"Op9Get",
])
.required(true)
.index(1))
.arg(Arg::with_name("https")
@ -119,216 +152,293 @@ fn main() {
.help("Port to contact"))
.get_matches();
let mut core = reactor::Core::new().unwrap();
let is_https = matches.is_present("https");
let base_url = format!("{}://{}:{}",
if is_https { "https" } else { "http" },
matches.value_of("host").unwrap(),
matches.value_of("port").unwrap());
let client = if matches.is_present("https") {
// Using Simple HTTPS
ops_v3::Client::try_new_https(core.handle(), &base_url, "examples/ca.pem")
Client::try_new_https(
&base_url,
"examples/ca.pem")
.expect("Failed to create HTTPS client")
} else {
// Using HTTP
ops_v3::Client::try_new_http(core.handle(), &base_url)
Client::try_new_http(
&base_url)
.expect("Failed to create HTTP client")
};
let context: make_context_ty!(ContextBuilder, EmptyContext, Option<AuthData>, XSpanIdString) =
make_context!(ContextBuilder, EmptyContext, None as Option<AuthData>, XSpanIdString(self::uuid::Uuid::new_v4().to_string()));
make_context!(ContextBuilder, EmptyContext, None as Option<AuthData>, XSpanIdString::default());
let client = client.with_context(context);
match matches.value_of("operation") {
Some("Op10Get") => {
let result = core.run(client.op10_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op10_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op11Get") => {
let result = core.run(client.op11_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op11_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op12Get") => {
let result = core.run(client.op12_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op12_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op13Get") => {
let result = core.run(client.op13_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op13_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op14Get") => {
let result = core.run(client.op14_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op14_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op15Get") => {
let result = core.run(client.op15_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op15_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op16Get") => {
let result = core.run(client.op16_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op16_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op17Get") => {
let result = core.run(client.op17_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op17_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op18Get") => {
let result = core.run(client.op18_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op18_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op19Get") => {
let result = core.run(client.op19_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op19_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op1Get") => {
let result = core.run(client.op1_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op1_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op20Get") => {
let result = core.run(client.op20_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op20_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op21Get") => {
let result = core.run(client.op21_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op21_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op22Get") => {
let result = core.run(client.op22_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op22_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op23Get") => {
let result = core.run(client.op23_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op23_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op24Get") => {
let result = core.run(client.op24_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op24_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op25Get") => {
let result = core.run(client.op25_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op25_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op26Get") => {
let result = core.run(client.op26_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op26_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op27Get") => {
let result = core.run(client.op27_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op27_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op28Get") => {
let result = core.run(client.op28_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op28_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op29Get") => {
let result = core.run(client.op29_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op29_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op2Get") => {
let result = core.run(client.op2_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op2_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op30Get") => {
let result = core.run(client.op30_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op30_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op31Get") => {
let result = core.run(client.op31_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op31_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op32Get") => {
let result = core.run(client.op32_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op32_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op33Get") => {
let result = core.run(client.op33_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op33_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op34Get") => {
let result = core.run(client.op34_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op34_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op35Get") => {
let result = core.run(client.op35_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op35_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op36Get") => {
let result = core.run(client.op36_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op36_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op37Get") => {
let result = core.run(client.op37_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op37_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op3Get") => {
let result = core.run(client.op3_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op3_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op4Get") => {
let result = core.run(client.op4_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op4_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op5Get") => {
let result = core.run(client.op5_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op5_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op6Get") => {
let result = core.run(client.op6_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op6_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op7Get") => {
let result = core.run(client.op7_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op7_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op8Get") => {
let result = core.run(client.op8_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op8_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("Op9Get") => {
let result = core.run(client.op9_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.op9_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
_ => {
panic!("Invalid operation provided")
}
}
}

View File

@ -8,9 +8,9 @@ extern crate ops_v3;
extern crate swagger;
extern crate hyper;
extern crate openssl;
extern crate native_tls;
extern crate tokio_proto;
extern crate tokio;
extern crate tokio_tls;
extern crate native_tls;
extern crate clap;
// Imports required by server library.
@ -21,14 +21,18 @@ extern crate chrono;
#[macro_use]
extern crate error_chain;
use futures::{Future, Stream};
use hyper::service::MakeService;
use hyper::server::conn::Http;
use openssl::x509::X509_FILETYPE_PEM;
use openssl::ssl::{SslAcceptorBuilder, SslMethod};
use openssl::error::ErrorStack;
use hyper::server::Http;
use tokio_proto::TcpServer;
use tokio::net::TcpListener;
use clap::{App, Arg};
use swagger::auth::AllowAllAuthenticator;
use std::sync::{Arc, Mutex};
use swagger::auth::MakeAllowAllAuthenticator;
use swagger::EmptyContext;
use tokio_tls::TlsAcceptorExt;
mod server_lib;
@ -53,12 +57,15 @@ fn main() {
.help("Whether to use HTTPS or not"))
.get_matches();
let server = server_lib::Server::new();
let service_fn = ops_v3::server::MakeService::new(server);
let service_fn = MakeAllowAllAuthenticator::new(service_fn, "cosmo");
let service_fn =
ops_v3::server::context::NewAddContext::<_, EmptyContext>::new(
AllowAllAuthenticator::new(
server_lib::NewService::new(),
"cosmo"
)
ops_v3::server::context::MakeAddContext::<_, EmptyContext>::new(
service_fn
);
let addr = "127.0.0.1:80".parse().expect("Failed to parse bind address");
@ -66,9 +73,29 @@ fn main() {
let ssl = ssl().expect("Failed to load SSL keys");
let builder: native_tls::TlsAcceptorBuilder = native_tls::backend::openssl::TlsAcceptorBuilderExt::from_openssl(ssl);
let tls_acceptor = builder.build().expect("Failed to build TLS acceptor");
TcpServer::new(tokio_tls::proto::Server::new(Http::new(), tls_acceptor), addr).serve(service_fn);
let service_fn = Arc::new(Mutex::new(service_fn));
let tls_listener = TcpListener::bind(&addr).unwrap().incoming().for_each(move |tcp| {
let addr = tcp.peer_addr().expect("Unable to get remote address");
let service_fn = service_fn.clone();
hyper::rt::spawn(tls_acceptor.accept_async(tcp).map_err(|_| ()).and_then(move |tls| {
let ms = {
let mut service_fn = service_fn.lock().unwrap();
service_fn.make_service(&addr)
};
ms.and_then(move |service| {
Http::new().serve_connection(tls, service)
}).map_err(|_| ())
}));
Ok(())
}).map_err(|_| ());
hyper::rt::run(tls_listener);
} else {
// Using HTTP
TcpServer::new(Http::new(), addr).serve(service_fn);
hyper::rt::run(hyper::server::Server::bind(&addr).serve(service_fn).map_err(|e| panic!("{:?}", e)));
}
}

View File

@ -1,37 +1,332 @@
//! Main library entry point for ops_v3 implementation.
mod server;
#![allow(unused_imports)]
mod errors {
error_chain!{}
}
pub use self::errors::*;
use std::io;
use std::clone::Clone;
use futures::{self, Future};
use chrono;
use std::collections::HashMap;
use std::marker::PhantomData;
use hyper;
use ops_v3;
use swagger;
use swagger::{Has, XSpanIdString};
pub struct NewService<C>{
marker: PhantomData<C>
use ops_v3::{Api, ApiError,
Op10GetResponse,
Op11GetResponse,
Op12GetResponse,
Op13GetResponse,
Op14GetResponse,
Op15GetResponse,
Op16GetResponse,
Op17GetResponse,
Op18GetResponse,
Op19GetResponse,
Op1GetResponse,
Op20GetResponse,
Op21GetResponse,
Op22GetResponse,
Op23GetResponse,
Op24GetResponse,
Op25GetResponse,
Op26GetResponse,
Op27GetResponse,
Op28GetResponse,
Op29GetResponse,
Op2GetResponse,
Op30GetResponse,
Op31GetResponse,
Op32GetResponse,
Op33GetResponse,
Op34GetResponse,
Op35GetResponse,
Op36GetResponse,
Op37GetResponse,
Op3GetResponse,
Op4GetResponse,
Op5GetResponse,
Op6GetResponse,
Op7GetResponse,
Op8GetResponse,
Op9GetResponse
};
use ops_v3::models;
#[derive(Copy, Clone)]
pub struct Server<C> {
marker: PhantomData<C>,
}
impl<C> NewService<C>{
impl<C> Server<C> {
pub fn new() -> Self {
NewService{marker:PhantomData}
Server{marker: PhantomData}
}
}
impl<C> hyper::server::NewService for NewService<C> where C: Has<XSpanIdString> + Clone + 'static {
type Request = (hyper::Request, C);
type Response = hyper::Response;
type Error = hyper::Error;
type Instance = ops_v3::server::Service<server::Server<C>, C>;
impl<C> Api<C> for Server<C> where C: Has<XSpanIdString>{
/// Instantiate a new server.
fn new_service(&self) -> io::Result<Self::Instance> {
Ok(ops_v3::server::Service::new(server::Server::new()))
fn op10_get(&self, context: &C) -> Box<Future<Item=Op10GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op10_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op11_get(&self, context: &C) -> Box<Future<Item=Op11GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op11_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op12_get(&self, context: &C) -> Box<Future<Item=Op12GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op12_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op13_get(&self, context: &C) -> Box<Future<Item=Op13GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op13_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op14_get(&self, context: &C) -> Box<Future<Item=Op14GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op14_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op15_get(&self, context: &C) -> Box<Future<Item=Op15GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op15_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op16_get(&self, context: &C) -> Box<Future<Item=Op16GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op16_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op17_get(&self, context: &C) -> Box<Future<Item=Op17GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op17_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op18_get(&self, context: &C) -> Box<Future<Item=Op18GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op18_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op19_get(&self, context: &C) -> Box<Future<Item=Op19GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op19_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op1_get(&self, context: &C) -> Box<Future<Item=Op1GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op1_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op20_get(&self, context: &C) -> Box<Future<Item=Op20GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op20_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op21_get(&self, context: &C) -> Box<Future<Item=Op21GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op21_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op22_get(&self, context: &C) -> Box<Future<Item=Op22GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op22_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op23_get(&self, context: &C) -> Box<Future<Item=Op23GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op23_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op24_get(&self, context: &C) -> Box<Future<Item=Op24GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op24_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op25_get(&self, context: &C) -> Box<Future<Item=Op25GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op25_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op26_get(&self, context: &C) -> Box<Future<Item=Op26GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op26_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op27_get(&self, context: &C) -> Box<Future<Item=Op27GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op27_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op28_get(&self, context: &C) -> Box<Future<Item=Op28GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op28_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op29_get(&self, context: &C) -> Box<Future<Item=Op29GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op29_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op2_get(&self, context: &C) -> Box<Future<Item=Op2GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op2_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op30_get(&self, context: &C) -> Box<Future<Item=Op30GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op30_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op31_get(&self, context: &C) -> Box<Future<Item=Op31GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op31_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op32_get(&self, context: &C) -> Box<Future<Item=Op32GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op32_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op33_get(&self, context: &C) -> Box<Future<Item=Op33GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op33_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op34_get(&self, context: &C) -> Box<Future<Item=Op34GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op34_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op35_get(&self, context: &C) -> Box<Future<Item=Op35GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op35_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op36_get(&self, context: &C) -> Box<Future<Item=Op36GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op36_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op37_get(&self, context: &C) -> Box<Future<Item=Op37GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op37_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op3_get(&self, context: &C) -> Box<Future<Item=Op3GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op3_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op4_get(&self, context: &C) -> Box<Future<Item=Op4GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op4_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op5_get(&self, context: &C) -> Box<Future<Item=Op5GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op5_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op6_get(&self, context: &C) -> Box<Future<Item=Op6GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op6_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op7_get(&self, context: &C) -> Box<Future<Item=Op7GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op7_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op8_get(&self, context: &C) -> Box<Future<Item=Op8GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op8_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn op9_get(&self, context: &C) -> Box<Future<Item=Op9GetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("op9_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
}

View File

@ -1,18 +1,17 @@
#![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)]
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
// Crates with macros
#[macro_use]
extern crate serde_derive;
#[cfg(any(feature = "client", feature = "server"))]
#[cfg(any(feature = "server"))]
#[macro_use]
extern crate hyper;
extern crate lazy_static;
#[cfg(any(feature = "client", feature = "server"))]
#[macro_use]
extern crate url;
#[macro_use]
extern crate log;
// Crates for conversion support
#[cfg(feature = "conversion")]
@ -26,12 +25,37 @@ extern crate frunk_core;
extern crate mime;
extern crate serde;
extern crate serde_json;
extern crate futures;
extern crate chrono;
extern crate swagger;
#[cfg(any(feature = "client", feature = "server"))]
extern crate hyper;
#[cfg(any(feature = "client"))]
extern crate hyper_tls;
#[cfg(any(feature = "client", feature = "server"))]
extern crate openssl;
#[cfg(any(feature = "client", feature = "server"))]
extern crate native_tls;
#[cfg(feature = "server")]
extern crate percent_encoding;
#[cfg(any(feature = "client", feature = "server"))]
extern crate serde_json;
#[cfg(any(feature = "client", feature = "server"))]
extern crate serde_ignored;
#[cfg(any(feature = "client", feature = "server"))]
extern crate tokio;
#[cfg(any(feature = "client", feature = "server"))]
#[cfg(any(feature = "client", feature = "server"))]
use hyper::header::HeaderValue;
use futures::Stream;
use std::io::Error;
@ -277,115 +301,115 @@ pub enum Op9GetResponse {
pub trait Api<C> {
fn op10_get(&self, context: &C) -> Box<dyn Future<Item=Op10GetResponse, Error=ApiError>>;
fn op10_get(&self, context: &C) -> Box<dyn Future<Item=Op10GetResponse, Error=ApiError> + Send>;
fn op11_get(&self, context: &C) -> Box<dyn Future<Item=Op11GetResponse, Error=ApiError>>;
fn op11_get(&self, context: &C) -> Box<dyn Future<Item=Op11GetResponse, Error=ApiError> + Send>;
fn op12_get(&self, context: &C) -> Box<dyn Future<Item=Op12GetResponse, Error=ApiError>>;
fn op12_get(&self, context: &C) -> Box<dyn Future<Item=Op12GetResponse, Error=ApiError> + Send>;
fn op13_get(&self, context: &C) -> Box<dyn Future<Item=Op13GetResponse, Error=ApiError>>;
fn op13_get(&self, context: &C) -> Box<dyn Future<Item=Op13GetResponse, Error=ApiError> + Send>;
fn op14_get(&self, context: &C) -> Box<dyn Future<Item=Op14GetResponse, Error=ApiError>>;
fn op14_get(&self, context: &C) -> Box<dyn Future<Item=Op14GetResponse, Error=ApiError> + Send>;
fn op15_get(&self, context: &C) -> Box<dyn Future<Item=Op15GetResponse, Error=ApiError>>;
fn op15_get(&self, context: &C) -> Box<dyn Future<Item=Op15GetResponse, Error=ApiError> + Send>;
fn op16_get(&self, context: &C) -> Box<dyn Future<Item=Op16GetResponse, Error=ApiError>>;
fn op16_get(&self, context: &C) -> Box<dyn Future<Item=Op16GetResponse, Error=ApiError> + Send>;
fn op17_get(&self, context: &C) -> Box<dyn Future<Item=Op17GetResponse, Error=ApiError>>;
fn op17_get(&self, context: &C) -> Box<dyn Future<Item=Op17GetResponse, Error=ApiError> + Send>;
fn op18_get(&self, context: &C) -> Box<dyn Future<Item=Op18GetResponse, Error=ApiError>>;
fn op18_get(&self, context: &C) -> Box<dyn Future<Item=Op18GetResponse, Error=ApiError> + Send>;
fn op19_get(&self, context: &C) -> Box<dyn Future<Item=Op19GetResponse, Error=ApiError>>;
fn op19_get(&self, context: &C) -> Box<dyn Future<Item=Op19GetResponse, Error=ApiError> + Send>;
fn op1_get(&self, context: &C) -> Box<dyn Future<Item=Op1GetResponse, Error=ApiError>>;
fn op1_get(&self, context: &C) -> Box<dyn Future<Item=Op1GetResponse, Error=ApiError> + Send>;
fn op20_get(&self, context: &C) -> Box<dyn Future<Item=Op20GetResponse, Error=ApiError>>;
fn op20_get(&self, context: &C) -> Box<dyn Future<Item=Op20GetResponse, Error=ApiError> + Send>;
fn op21_get(&self, context: &C) -> Box<dyn Future<Item=Op21GetResponse, Error=ApiError>>;
fn op21_get(&self, context: &C) -> Box<dyn Future<Item=Op21GetResponse, Error=ApiError> + Send>;
fn op22_get(&self, context: &C) -> Box<dyn Future<Item=Op22GetResponse, Error=ApiError>>;
fn op22_get(&self, context: &C) -> Box<dyn Future<Item=Op22GetResponse, Error=ApiError> + Send>;
fn op23_get(&self, context: &C) -> Box<dyn Future<Item=Op23GetResponse, Error=ApiError>>;
fn op23_get(&self, context: &C) -> Box<dyn Future<Item=Op23GetResponse, Error=ApiError> + Send>;
fn op24_get(&self, context: &C) -> Box<dyn Future<Item=Op24GetResponse, Error=ApiError>>;
fn op24_get(&self, context: &C) -> Box<dyn Future<Item=Op24GetResponse, Error=ApiError> + Send>;
fn op25_get(&self, context: &C) -> Box<dyn Future<Item=Op25GetResponse, Error=ApiError>>;
fn op25_get(&self, context: &C) -> Box<dyn Future<Item=Op25GetResponse, Error=ApiError> + Send>;
fn op26_get(&self, context: &C) -> Box<dyn Future<Item=Op26GetResponse, Error=ApiError>>;
fn op26_get(&self, context: &C) -> Box<dyn Future<Item=Op26GetResponse, Error=ApiError> + Send>;
fn op27_get(&self, context: &C) -> Box<dyn Future<Item=Op27GetResponse, Error=ApiError>>;
fn op27_get(&self, context: &C) -> Box<dyn Future<Item=Op27GetResponse, Error=ApiError> + Send>;
fn op28_get(&self, context: &C) -> Box<dyn Future<Item=Op28GetResponse, Error=ApiError>>;
fn op28_get(&self, context: &C) -> Box<dyn Future<Item=Op28GetResponse, Error=ApiError> + Send>;
fn op29_get(&self, context: &C) -> Box<dyn Future<Item=Op29GetResponse, Error=ApiError>>;
fn op29_get(&self, context: &C) -> Box<dyn Future<Item=Op29GetResponse, Error=ApiError> + Send>;
fn op2_get(&self, context: &C) -> Box<dyn Future<Item=Op2GetResponse, Error=ApiError>>;
fn op2_get(&self, context: &C) -> Box<dyn Future<Item=Op2GetResponse, Error=ApiError> + Send>;
fn op30_get(&self, context: &C) -> Box<dyn Future<Item=Op30GetResponse, Error=ApiError>>;
fn op30_get(&self, context: &C) -> Box<dyn Future<Item=Op30GetResponse, Error=ApiError> + Send>;
fn op31_get(&self, context: &C) -> Box<dyn Future<Item=Op31GetResponse, Error=ApiError>>;
fn op31_get(&self, context: &C) -> Box<dyn Future<Item=Op31GetResponse, Error=ApiError> + Send>;
fn op32_get(&self, context: &C) -> Box<dyn Future<Item=Op32GetResponse, Error=ApiError>>;
fn op32_get(&self, context: &C) -> Box<dyn Future<Item=Op32GetResponse, Error=ApiError> + Send>;
fn op33_get(&self, context: &C) -> Box<dyn Future<Item=Op33GetResponse, Error=ApiError>>;
fn op33_get(&self, context: &C) -> Box<dyn Future<Item=Op33GetResponse, Error=ApiError> + Send>;
fn op34_get(&self, context: &C) -> Box<dyn Future<Item=Op34GetResponse, Error=ApiError>>;
fn op34_get(&self, context: &C) -> Box<dyn Future<Item=Op34GetResponse, Error=ApiError> + Send>;
fn op35_get(&self, context: &C) -> Box<dyn Future<Item=Op35GetResponse, Error=ApiError>>;
fn op35_get(&self, context: &C) -> Box<dyn Future<Item=Op35GetResponse, Error=ApiError> + Send>;
fn op36_get(&self, context: &C) -> Box<dyn Future<Item=Op36GetResponse, Error=ApiError>>;
fn op36_get(&self, context: &C) -> Box<dyn Future<Item=Op36GetResponse, Error=ApiError> + Send>;
fn op37_get(&self, context: &C) -> Box<dyn Future<Item=Op37GetResponse, Error=ApiError>>;
fn op37_get(&self, context: &C) -> Box<dyn Future<Item=Op37GetResponse, Error=ApiError> + Send>;
fn op3_get(&self, context: &C) -> Box<dyn Future<Item=Op3GetResponse, Error=ApiError>>;
fn op3_get(&self, context: &C) -> Box<dyn Future<Item=Op3GetResponse, Error=ApiError> + Send>;
fn op4_get(&self, context: &C) -> Box<dyn Future<Item=Op4GetResponse, Error=ApiError>>;
fn op4_get(&self, context: &C) -> Box<dyn Future<Item=Op4GetResponse, Error=ApiError> + Send>;
fn op5_get(&self, context: &C) -> Box<dyn Future<Item=Op5GetResponse, Error=ApiError>>;
fn op5_get(&self, context: &C) -> Box<dyn Future<Item=Op5GetResponse, Error=ApiError> + Send>;
fn op6_get(&self, context: &C) -> Box<dyn Future<Item=Op6GetResponse, Error=ApiError>>;
fn op6_get(&self, context: &C) -> Box<dyn Future<Item=Op6GetResponse, Error=ApiError> + Send>;
fn op7_get(&self, context: &C) -> Box<dyn Future<Item=Op7GetResponse, Error=ApiError>>;
fn op7_get(&self, context: &C) -> Box<dyn Future<Item=Op7GetResponse, Error=ApiError> + Send>;
fn op8_get(&self, context: &C) -> Box<dyn Future<Item=Op8GetResponse, Error=ApiError>>;
fn op8_get(&self, context: &C) -> Box<dyn Future<Item=Op8GetResponse, Error=ApiError> + Send>;
fn op9_get(&self, context: &C) -> Box<dyn Future<Item=Op9GetResponse, Error=ApiError>>;
fn op9_get(&self, context: &C) -> Box<dyn Future<Item=Op9GetResponse, Error=ApiError> + Send>;
}
@ -393,115 +417,115 @@ pub trait Api<C> {
pub trait ApiNoContext {
fn op10_get(&self) -> Box<dyn Future<Item=Op10GetResponse, Error=ApiError>>;
fn op10_get(&self) -> Box<dyn Future<Item=Op10GetResponse, Error=ApiError> + Send>;
fn op11_get(&self) -> Box<dyn Future<Item=Op11GetResponse, Error=ApiError>>;
fn op11_get(&self) -> Box<dyn Future<Item=Op11GetResponse, Error=ApiError> + Send>;
fn op12_get(&self) -> Box<dyn Future<Item=Op12GetResponse, Error=ApiError>>;
fn op12_get(&self) -> Box<dyn Future<Item=Op12GetResponse, Error=ApiError> + Send>;
fn op13_get(&self) -> Box<dyn Future<Item=Op13GetResponse, Error=ApiError>>;
fn op13_get(&self) -> Box<dyn Future<Item=Op13GetResponse, Error=ApiError> + Send>;
fn op14_get(&self) -> Box<dyn Future<Item=Op14GetResponse, Error=ApiError>>;
fn op14_get(&self) -> Box<dyn Future<Item=Op14GetResponse, Error=ApiError> + Send>;
fn op15_get(&self) -> Box<dyn Future<Item=Op15GetResponse, Error=ApiError>>;
fn op15_get(&self) -> Box<dyn Future<Item=Op15GetResponse, Error=ApiError> + Send>;
fn op16_get(&self) -> Box<dyn Future<Item=Op16GetResponse, Error=ApiError>>;
fn op16_get(&self) -> Box<dyn Future<Item=Op16GetResponse, Error=ApiError> + Send>;
fn op17_get(&self) -> Box<dyn Future<Item=Op17GetResponse, Error=ApiError>>;
fn op17_get(&self) -> Box<dyn Future<Item=Op17GetResponse, Error=ApiError> + Send>;
fn op18_get(&self) -> Box<dyn Future<Item=Op18GetResponse, Error=ApiError>>;
fn op18_get(&self) -> Box<dyn Future<Item=Op18GetResponse, Error=ApiError> + Send>;
fn op19_get(&self) -> Box<dyn Future<Item=Op19GetResponse, Error=ApiError>>;
fn op19_get(&self) -> Box<dyn Future<Item=Op19GetResponse, Error=ApiError> + Send>;
fn op1_get(&self) -> Box<dyn Future<Item=Op1GetResponse, Error=ApiError>>;
fn op1_get(&self) -> Box<dyn Future<Item=Op1GetResponse, Error=ApiError> + Send>;
fn op20_get(&self) -> Box<dyn Future<Item=Op20GetResponse, Error=ApiError>>;
fn op20_get(&self) -> Box<dyn Future<Item=Op20GetResponse, Error=ApiError> + Send>;
fn op21_get(&self) -> Box<dyn Future<Item=Op21GetResponse, Error=ApiError>>;
fn op21_get(&self) -> Box<dyn Future<Item=Op21GetResponse, Error=ApiError> + Send>;
fn op22_get(&self) -> Box<dyn Future<Item=Op22GetResponse, Error=ApiError>>;
fn op22_get(&self) -> Box<dyn Future<Item=Op22GetResponse, Error=ApiError> + Send>;
fn op23_get(&self) -> Box<dyn Future<Item=Op23GetResponse, Error=ApiError>>;
fn op23_get(&self) -> Box<dyn Future<Item=Op23GetResponse, Error=ApiError> + Send>;
fn op24_get(&self) -> Box<dyn Future<Item=Op24GetResponse, Error=ApiError>>;
fn op24_get(&self) -> Box<dyn Future<Item=Op24GetResponse, Error=ApiError> + Send>;
fn op25_get(&self) -> Box<dyn Future<Item=Op25GetResponse, Error=ApiError>>;
fn op25_get(&self) -> Box<dyn Future<Item=Op25GetResponse, Error=ApiError> + Send>;
fn op26_get(&self) -> Box<dyn Future<Item=Op26GetResponse, Error=ApiError>>;
fn op26_get(&self) -> Box<dyn Future<Item=Op26GetResponse, Error=ApiError> + Send>;
fn op27_get(&self) -> Box<dyn Future<Item=Op27GetResponse, Error=ApiError>>;
fn op27_get(&self) -> Box<dyn Future<Item=Op27GetResponse, Error=ApiError> + Send>;
fn op28_get(&self) -> Box<dyn Future<Item=Op28GetResponse, Error=ApiError>>;
fn op28_get(&self) -> Box<dyn Future<Item=Op28GetResponse, Error=ApiError> + Send>;
fn op29_get(&self) -> Box<dyn Future<Item=Op29GetResponse, Error=ApiError>>;
fn op29_get(&self) -> Box<dyn Future<Item=Op29GetResponse, Error=ApiError> + Send>;
fn op2_get(&self) -> Box<dyn Future<Item=Op2GetResponse, Error=ApiError>>;
fn op2_get(&self) -> Box<dyn Future<Item=Op2GetResponse, Error=ApiError> + Send>;
fn op30_get(&self) -> Box<dyn Future<Item=Op30GetResponse, Error=ApiError>>;
fn op30_get(&self) -> Box<dyn Future<Item=Op30GetResponse, Error=ApiError> + Send>;
fn op31_get(&self) -> Box<dyn Future<Item=Op31GetResponse, Error=ApiError>>;
fn op31_get(&self) -> Box<dyn Future<Item=Op31GetResponse, Error=ApiError> + Send>;
fn op32_get(&self) -> Box<dyn Future<Item=Op32GetResponse, Error=ApiError>>;
fn op32_get(&self) -> Box<dyn Future<Item=Op32GetResponse, Error=ApiError> + Send>;
fn op33_get(&self) -> Box<dyn Future<Item=Op33GetResponse, Error=ApiError>>;
fn op33_get(&self) -> Box<dyn Future<Item=Op33GetResponse, Error=ApiError> + Send>;
fn op34_get(&self) -> Box<dyn Future<Item=Op34GetResponse, Error=ApiError>>;
fn op34_get(&self) -> Box<dyn Future<Item=Op34GetResponse, Error=ApiError> + Send>;
fn op35_get(&self) -> Box<dyn Future<Item=Op35GetResponse, Error=ApiError>>;
fn op35_get(&self) -> Box<dyn Future<Item=Op35GetResponse, Error=ApiError> + Send>;
fn op36_get(&self) -> Box<dyn Future<Item=Op36GetResponse, Error=ApiError>>;
fn op36_get(&self) -> Box<dyn Future<Item=Op36GetResponse, Error=ApiError> + Send>;
fn op37_get(&self) -> Box<dyn Future<Item=Op37GetResponse, Error=ApiError>>;
fn op37_get(&self) -> Box<dyn Future<Item=Op37GetResponse, Error=ApiError> + Send>;
fn op3_get(&self) -> Box<dyn Future<Item=Op3GetResponse, Error=ApiError>>;
fn op3_get(&self) -> Box<dyn Future<Item=Op3GetResponse, Error=ApiError> + Send>;
fn op4_get(&self) -> Box<dyn Future<Item=Op4GetResponse, Error=ApiError>>;
fn op4_get(&self) -> Box<dyn Future<Item=Op4GetResponse, Error=ApiError> + Send>;
fn op5_get(&self) -> Box<dyn Future<Item=Op5GetResponse, Error=ApiError>>;
fn op5_get(&self) -> Box<dyn Future<Item=Op5GetResponse, Error=ApiError> + Send>;
fn op6_get(&self) -> Box<dyn Future<Item=Op6GetResponse, Error=ApiError>>;
fn op6_get(&self) -> Box<dyn Future<Item=Op6GetResponse, Error=ApiError> + Send>;
fn op7_get(&self) -> Box<dyn Future<Item=Op7GetResponse, Error=ApiError>>;
fn op7_get(&self) -> Box<dyn Future<Item=Op7GetResponse, Error=ApiError> + Send>;
fn op8_get(&self) -> Box<dyn Future<Item=Op8GetResponse, Error=ApiError>>;
fn op8_get(&self) -> Box<dyn Future<Item=Op8GetResponse, Error=ApiError> + Send>;
fn op9_get(&self) -> Box<dyn Future<Item=Op9GetResponse, Error=ApiError>>;
fn op9_get(&self) -> Box<dyn Future<Item=Op9GetResponse, Error=ApiError> + Send>;
}
@ -520,187 +544,187 @@ impl<'a, T: Api<C> + Sized, C> ContextWrapperExt<'a, C> for T {
impl<'a, T: Api<C>, C> ApiNoContext for ContextWrapper<'a, T, C> {
fn op10_get(&self) -> Box<dyn Future<Item=Op10GetResponse, Error=ApiError>> {
fn op10_get(&self) -> Box<dyn Future<Item=Op10GetResponse, Error=ApiError> + Send> {
self.api().op10_get(&self.context())
}
fn op11_get(&self) -> Box<dyn Future<Item=Op11GetResponse, Error=ApiError>> {
fn op11_get(&self) -> Box<dyn Future<Item=Op11GetResponse, Error=ApiError> + Send> {
self.api().op11_get(&self.context())
}
fn op12_get(&self) -> Box<dyn Future<Item=Op12GetResponse, Error=ApiError>> {
fn op12_get(&self) -> Box<dyn Future<Item=Op12GetResponse, Error=ApiError> + Send> {
self.api().op12_get(&self.context())
}
fn op13_get(&self) -> Box<dyn Future<Item=Op13GetResponse, Error=ApiError>> {
fn op13_get(&self) -> Box<dyn Future<Item=Op13GetResponse, Error=ApiError> + Send> {
self.api().op13_get(&self.context())
}
fn op14_get(&self) -> Box<dyn Future<Item=Op14GetResponse, Error=ApiError>> {
fn op14_get(&self) -> Box<dyn Future<Item=Op14GetResponse, Error=ApiError> + Send> {
self.api().op14_get(&self.context())
}
fn op15_get(&self) -> Box<dyn Future<Item=Op15GetResponse, Error=ApiError>> {
fn op15_get(&self) -> Box<dyn Future<Item=Op15GetResponse, Error=ApiError> + Send> {
self.api().op15_get(&self.context())
}
fn op16_get(&self) -> Box<dyn Future<Item=Op16GetResponse, Error=ApiError>> {
fn op16_get(&self) -> Box<dyn Future<Item=Op16GetResponse, Error=ApiError> + Send> {
self.api().op16_get(&self.context())
}
fn op17_get(&self) -> Box<dyn Future<Item=Op17GetResponse, Error=ApiError>> {
fn op17_get(&self) -> Box<dyn Future<Item=Op17GetResponse, Error=ApiError> + Send> {
self.api().op17_get(&self.context())
}
fn op18_get(&self) -> Box<dyn Future<Item=Op18GetResponse, Error=ApiError>> {
fn op18_get(&self) -> Box<dyn Future<Item=Op18GetResponse, Error=ApiError> + Send> {
self.api().op18_get(&self.context())
}
fn op19_get(&self) -> Box<dyn Future<Item=Op19GetResponse, Error=ApiError>> {
fn op19_get(&self) -> Box<dyn Future<Item=Op19GetResponse, Error=ApiError> + Send> {
self.api().op19_get(&self.context())
}
fn op1_get(&self) -> Box<dyn Future<Item=Op1GetResponse, Error=ApiError>> {
fn op1_get(&self) -> Box<dyn Future<Item=Op1GetResponse, Error=ApiError> + Send> {
self.api().op1_get(&self.context())
}
fn op20_get(&self) -> Box<dyn Future<Item=Op20GetResponse, Error=ApiError>> {
fn op20_get(&self) -> Box<dyn Future<Item=Op20GetResponse, Error=ApiError> + Send> {
self.api().op20_get(&self.context())
}
fn op21_get(&self) -> Box<dyn Future<Item=Op21GetResponse, Error=ApiError>> {
fn op21_get(&self) -> Box<dyn Future<Item=Op21GetResponse, Error=ApiError> + Send> {
self.api().op21_get(&self.context())
}
fn op22_get(&self) -> Box<dyn Future<Item=Op22GetResponse, Error=ApiError>> {
fn op22_get(&self) -> Box<dyn Future<Item=Op22GetResponse, Error=ApiError> + Send> {
self.api().op22_get(&self.context())
}
fn op23_get(&self) -> Box<dyn Future<Item=Op23GetResponse, Error=ApiError>> {
fn op23_get(&self) -> Box<dyn Future<Item=Op23GetResponse, Error=ApiError> + Send> {
self.api().op23_get(&self.context())
}
fn op24_get(&self) -> Box<dyn Future<Item=Op24GetResponse, Error=ApiError>> {
fn op24_get(&self) -> Box<dyn Future<Item=Op24GetResponse, Error=ApiError> + Send> {
self.api().op24_get(&self.context())
}
fn op25_get(&self) -> Box<dyn Future<Item=Op25GetResponse, Error=ApiError>> {
fn op25_get(&self) -> Box<dyn Future<Item=Op25GetResponse, Error=ApiError> + Send> {
self.api().op25_get(&self.context())
}
fn op26_get(&self) -> Box<dyn Future<Item=Op26GetResponse, Error=ApiError>> {
fn op26_get(&self) -> Box<dyn Future<Item=Op26GetResponse, Error=ApiError> + Send> {
self.api().op26_get(&self.context())
}
fn op27_get(&self) -> Box<dyn Future<Item=Op27GetResponse, Error=ApiError>> {
fn op27_get(&self) -> Box<dyn Future<Item=Op27GetResponse, Error=ApiError> + Send> {
self.api().op27_get(&self.context())
}
fn op28_get(&self) -> Box<dyn Future<Item=Op28GetResponse, Error=ApiError>> {
fn op28_get(&self) -> Box<dyn Future<Item=Op28GetResponse, Error=ApiError> + Send> {
self.api().op28_get(&self.context())
}
fn op29_get(&self) -> Box<dyn Future<Item=Op29GetResponse, Error=ApiError>> {
fn op29_get(&self) -> Box<dyn Future<Item=Op29GetResponse, Error=ApiError> + Send> {
self.api().op29_get(&self.context())
}
fn op2_get(&self) -> Box<dyn Future<Item=Op2GetResponse, Error=ApiError>> {
fn op2_get(&self) -> Box<dyn Future<Item=Op2GetResponse, Error=ApiError> + Send> {
self.api().op2_get(&self.context())
}
fn op30_get(&self) -> Box<dyn Future<Item=Op30GetResponse, Error=ApiError>> {
fn op30_get(&self) -> Box<dyn Future<Item=Op30GetResponse, Error=ApiError> + Send> {
self.api().op30_get(&self.context())
}
fn op31_get(&self) -> Box<dyn Future<Item=Op31GetResponse, Error=ApiError>> {
fn op31_get(&self) -> Box<dyn Future<Item=Op31GetResponse, Error=ApiError> + Send> {
self.api().op31_get(&self.context())
}
fn op32_get(&self) -> Box<dyn Future<Item=Op32GetResponse, Error=ApiError>> {
fn op32_get(&self) -> Box<dyn Future<Item=Op32GetResponse, Error=ApiError> + Send> {
self.api().op32_get(&self.context())
}
fn op33_get(&self) -> Box<dyn Future<Item=Op33GetResponse, Error=ApiError>> {
fn op33_get(&self) -> Box<dyn Future<Item=Op33GetResponse, Error=ApiError> + Send> {
self.api().op33_get(&self.context())
}
fn op34_get(&self) -> Box<dyn Future<Item=Op34GetResponse, Error=ApiError>> {
fn op34_get(&self) -> Box<dyn Future<Item=Op34GetResponse, Error=ApiError> + Send> {
self.api().op34_get(&self.context())
}
fn op35_get(&self) -> Box<dyn Future<Item=Op35GetResponse, Error=ApiError>> {
fn op35_get(&self) -> Box<dyn Future<Item=Op35GetResponse, Error=ApiError> + Send> {
self.api().op35_get(&self.context())
}
fn op36_get(&self) -> Box<dyn Future<Item=Op36GetResponse, Error=ApiError>> {
fn op36_get(&self) -> Box<dyn Future<Item=Op36GetResponse, Error=ApiError> + Send> {
self.api().op36_get(&self.context())
}
fn op37_get(&self) -> Box<dyn Future<Item=Op37GetResponse, Error=ApiError>> {
fn op37_get(&self) -> Box<dyn Future<Item=Op37GetResponse, Error=ApiError> + Send> {
self.api().op37_get(&self.context())
}
fn op3_get(&self) -> Box<dyn Future<Item=Op3GetResponse, Error=ApiError>> {
fn op3_get(&self) -> Box<dyn Future<Item=Op3GetResponse, Error=ApiError> + Send> {
self.api().op3_get(&self.context())
}
fn op4_get(&self) -> Box<dyn Future<Item=Op4GetResponse, Error=ApiError>> {
fn op4_get(&self) -> Box<dyn Future<Item=Op4GetResponse, Error=ApiError> + Send> {
self.api().op4_get(&self.context())
}
fn op5_get(&self) -> Box<dyn Future<Item=Op5GetResponse, Error=ApiError>> {
fn op5_get(&self) -> Box<dyn Future<Item=Op5GetResponse, Error=ApiError> + Send> {
self.api().op5_get(&self.context())
}
fn op6_get(&self) -> Box<dyn Future<Item=Op6GetResponse, Error=ApiError>> {
fn op6_get(&self) -> Box<dyn Future<Item=Op6GetResponse, Error=ApiError> + Send> {
self.api().op6_get(&self.context())
}
fn op7_get(&self) -> Box<dyn Future<Item=Op7GetResponse, Error=ApiError>> {
fn op7_get(&self) -> Box<dyn Future<Item=Op7GetResponse, Error=ApiError> + Send> {
self.api().op7_get(&self.context())
}
fn op8_get(&self) -> Box<dyn Future<Item=Op8GetResponse, Error=ApiError>> {
fn op8_get(&self) -> Box<dyn Future<Item=Op8GetResponse, Error=ApiError> + Send> {
self.api().op8_get(&self.context())
}
fn op9_get(&self) -> Box<dyn Future<Item=Op9GetResponse, Error=ApiError>> {
fn op9_get(&self) -> Box<dyn Future<Item=Op9GetResponse, Error=ApiError> + Send> {
self.api().op9_get(&self.context())
}

View File

@ -1,13 +1,10 @@
/// mime types for requests and responses
pub mod responses {
use hyper::mime::*;
// The macro is called per-operation to beat the recursion limit
}
pub mod requests {
use hyper::mime::*;
}

View File

@ -1,5 +1,4 @@
#![allow(unused_imports, unused_qualifications, unused_extern_crates)]
extern crate chrono;
#![allow(unused_imports, unused_qualifications)]
use serde::ser::Serializer;

View File

@ -1,64 +1,86 @@
use futures::Future;
use hyper;
use hyper::header::HeaderName;
use hyper::{Error, Request, Response, StatusCode, service::Service, body::Payload};
use url::form_urlencoded;
use std::default::Default;
use std::io;
use std::marker::PhantomData;
use 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 swagger::auth::{AuthData, Authorization, Bearer, Scopes};
use swagger::context::ContextualPayload;
use swagger::{EmptyContext, Has, Pop, Push, XSpanIdString};
use Api;
pub struct NewAddContext<T, A>
{
pub struct MakeAddContext<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,
impl<T, A, B, C, D> MakeAddContext<T, A>
where
A: Default + Push<XSpanIdString, Result = B>,
B: Push<Option<AuthData>, Result = C>,
C: Push<Option<Authorization>, Result = D>,
{
pub fn new(inner: T) -> NewAddContext<T, A> {
NewAddContext {
pub fn new(inner: T) -> MakeAddContext<T, A> {
MakeAddContext {
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,
// Make a service that adds context.
impl<'a, T, SC, A, B, C, D, E, ME, S, OB, F> hyper::service::MakeService<&'a SC> for
MakeAddContext<T, A>
where
A: Default + Push<XSpanIdString, Result = B>,
B: Push<Option<AuthData>, Result = C>,
C: Push<Option<Authorization>, Result = D>,
D: Send + 'static,
T: hyper::service::MakeService<
&'a SC,
Error = E,
MakeError = ME,
Service = S,
ReqBody = ContextualPayload<hyper::Body, D>,
ResBody = OB,
Future = F
>,
S: Service<
Error = E,
ReqBody = ContextualPayload<hyper::Body, D>,
ResBody = OB> + 'static,
ME: swagger::ErrorBound,
E: swagger::ErrorBound,
F: Future<Item=S, Error=ME> + Send + 'static,
S::Future: Send,
OB: Payload,
{
type Request = Request;
type Response = Response;
type Error = Error;
type Instance = AddContext<T::Instance, A>;
type ReqBody = hyper::Body;
type ResBody = OB;
type Error = E;
type MakeError = ME;
type Service = AddContext<S, A>;
type Future = Box<dyn Future<Item = Self::Service, Error = ME> + Send + 'static>;
fn new_service(&self) -> Result<Self::Instance, io::Error> {
self.inner.new_service().map(|s| AddContext::new(s))
fn make_service(&mut self, ctx: &'a SC) -> Self::Future {
Box::new(self.inner.make_service(ctx).map(|s| AddContext::new(s)))
}
}
/// Middleware to extract authentication data from request
pub struct AddContext<T, A>
{
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>,
where
A: Default + Push<XSpanIdString, Result = B>,
B: Push<Option<AuthData>, Result = C>,
C: Push<Option<Authorization>, Result = D>,
T: Service,
{
pub fn new(inner: T) -> AddContext<T, A> {
AddContext {
@ -68,24 +90,33 @@ impl<T, A, B, C, D> AddContext<T, A>
}
}
impl<T, A, B, C, D> hyper::server::Service for AddContext<T, A>
impl<T, A, B, C, D> Service for AddContext<T, A>
where
A: Default + Push<XSpanIdString, Result=B>,
B: Push<Option<AuthData>, Result=C>,
C: Push<Option<Authorization>, Result=D>,
T: hyper::server::Service<Request = (Request, D), Response = Response, Error = Error>,
D: Send + 'static,
T: Service<ReqBody = ContextualPayload<hyper::Body, D>>,
T::Future: Future<Item=Response<T::ResBody>, Error=T::Error> + Send + 'static
{
type Request = Request;
type Response = Response;
type Error = Error;
type Future = T::Future;
type ReqBody = hyper::Body;
type ResBody = T::ResBody;
type Error = T::Error;
type Future = Box<dyn Future<Item=Response<T::ResBody>, Error=T::Error> + Send + 'static>;
fn call(&self, req: Self::Request) -> Self::Future {
fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future {
let context = A::default().push(XSpanIdString::get_or_generate(&req));
let (head, body) = req.into_parts();
let headers = head.headers.clone();
let context = context.push(None::<AuthData>);
let context = context.push(None::<Authorization>);
return self.inner.call((req, context));
let body = ContextualPayload {
inner: body,
context: context,
};
Box::new(self.inner.call(hyper::Request::from_parts(head, body)))
}
}

View File

@ -7,48 +7,56 @@ license = "Unlicense"
[features]
default = ["client", "server"]
client = ["serde_urlencoded", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url"]
server = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url"]
client = [
"multipart", "multipart/client", "swagger/multipart",
"serde_urlencoded",
"serde_json", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio", "url"
]
server = [
"multipart", "multipart/server",
"serde_json", "serde_ignored", "hyper", "native-tls", "openssl", "tokio", "tokio-tls", "regex", "percent-encoding", "url", "lazy_static"
]
conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"]
[dependencies]
# Common
chrono = { version = "0.4", features = ["serde"] }
futures = "0.1"
swagger = "2"
lazy_static = "1.4"
swagger = "3.0"
log = "0.3.0"
mime = "0.2.6"
multipart = "0.13.3"
mime = "0.3"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
# Crates included if required by the API definition
uuid = {version = "0.5", features = ["serde", "v4"]}
# TODO: this should be updated to point at the official crate once
# https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream
serde-xml-rs = {git = "git://github.com/Metaswitch/serde-xml-rs.git" , branch = "master"}
mime_0_2 = { package = "mime", version = "0.2.6" }
multipart = { version = "0.16", default-features = false, optional = true }
uuid = {version = "0.7", features = ["serde", "v4"]}
# Common between server and client features
hyper = {version = "0.11", optional = true}
hyper-tls = {version = "0.1.2", optional = true}
hyper = {version = "0.12", optional = true}
hyper-tls = {version = "0.2.1", optional = true}
native-tls = {version = "0.1.4", optional = true}
openssl = {version = "0.9.14", optional = true}
serde_json = {version = "1.0", optional = true}
serde_ignored = {version = "0.0.4", optional = true}
tokio-core = {version = "0.1.6", optional = true}
tokio = {version = "0.1.17", optional = true}
url = {version = "1.5", optional = true}
# Client-specific
serde_urlencoded = {version = "0.5.1", optional = true}
# Server-specific
lazy_static = { version = "1.4", optional = true }
percent-encoding = {version = "1.0.0", optional = true}
regex = {version = "0.2", optional = true}
tokio-proto = {version = "0.1.1", optional = true}
tokio-tls = {version = "0.1.3", optional = true, features = ["tokio-proto"]}
tokio-tls = {version = "0.1.3", optional = true}
# Other optional crates
# Conversion
frunk = { version = "0.3.0", optional = true }
frunk_derives = { version = "0.3.0", optional = true }
frunk_core = { version = "0.3.0", optional = true }

View File

@ -1,23 +1,18 @@
#![allow(missing_docs, unused_variables, trivial_casts)]
extern crate petstore_with_fake_endpoints_models_for_testing;
#[allow(unused_extern_crates)]
extern crate futures;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate swagger;
#[allow(unused_extern_crates)]
extern crate clap;
extern crate tokio_core;
extern crate uuid;
extern crate tokio;
use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData};
#[allow(unused_imports)]
use futures::{Future, future, Stream, stream};
use tokio_core::reactor;
#[allow(unused_imports)]
use petstore_with_fake_endpoints_models_for_testing::{ApiNoContext, ContextWrapperExt,
use petstore_with_fake_endpoints_models_for_testing::{Api, ApiNoContext, Client, ContextWrapperExt,
ApiError,
TestSpecialTagsResponse,
FakeOuterBooleanSerializeResponse,
@ -59,29 +54,52 @@ fn main() {
.arg(Arg::with_name("operation")
.help("Sets the operation to run")
.possible_values(&[
"FakeOuterBooleanSerialize",
"FakeOuterCompositeSerialize",
"FakeOuterNumberSerialize",
"FakeOuterStringSerialize",
"TestEndpointParameters",
"TestEnumParameters",
"TestJsonFormData",
"DeletePet",
"FindPetsByStatus",
"FindPetsByTags",
"GetPetById",
"UpdatePetWithForm",
"UploadFile",
"DeleteOrder",
"GetInventory",
"GetOrderById",
"CreateUsersWithArrayInput",
"CreateUsersWithListInput",
"DeleteUser",
"GetUserByName",
"LoginUser",
"LogoutUser",
])
"FakeOuterBooleanSerialize",
"FakeOuterCompositeSerialize",
"FakeOuterNumberSerialize",
"FakeOuterStringSerialize",
"TestEndpointParameters",
"TestEnumParameters",
"TestJsonFormData",
"DeletePet",
"FindPetsByStatus",
"FindPetsByTags",
"GetPetById",
"UpdatePetWithForm",
"UploadFile",
"DeleteOrder",
"GetInventory",
"GetOrderById",
"CreateUsersWithArrayInput",
"CreateUsersWithListInput",
"DeleteUser",
"GetUserByName",
"LoginUser",
"LogoutUser",
])
.required(true)
.index(1))
.arg(Arg::with_name("https")
@ -99,201 +117,336 @@ fn main() {
.help("Port to contact"))
.get_matches();
let mut core = reactor::Core::new().unwrap();
let is_https = matches.is_present("https");
let base_url = format!("{}://{}:{}",
if is_https { "https" } else { "http" },
matches.value_of("host").unwrap(),
matches.value_of("port").unwrap());
let client = if matches.is_present("https") {
// Using Simple HTTPS
petstore_with_fake_endpoints_models_for_testing::Client::try_new_https(core.handle(), &base_url, "examples/ca.pem")
Client::try_new_https(
&base_url,
"examples/ca.pem")
.expect("Failed to create HTTPS client")
} else {
// Using HTTP
petstore_with_fake_endpoints_models_for_testing::Client::try_new_http(core.handle(), &base_url)
Client::try_new_http(
&base_url)
.expect("Failed to create HTTP client")
};
let context: make_context_ty!(ContextBuilder, EmptyContext, Option<AuthData>, XSpanIdString) =
make_context!(ContextBuilder, EmptyContext, None as Option<AuthData>, XSpanIdString(self::uuid::Uuid::new_v4().to_string()));
make_context!(ContextBuilder, EmptyContext, None as Option<AuthData>, XSpanIdString::default());
let client = client.with_context(context);
match matches.value_of("operation") {
// Disabled because there's no example.
// Some("TestSpecialTags") => {
// let result = core.run(client.test_special_tags(???));
// println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
// },
/* Disabled because there's no example.
Some("TestSpecialTags") => {
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.test_special_tags(
???
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
*/
Some("FakeOuterBooleanSerialize") => {
let result = core.run(client.fake_outer_boolean_serialize(None));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.fake_outer_boolean_serialize(
None
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("FakeOuterCompositeSerialize") => {
let result = core.run(client.fake_outer_composite_serialize(None));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.fake_outer_composite_serialize(
None
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("FakeOuterNumberSerialize") => {
let result = core.run(client.fake_outer_number_serialize(None));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.fake_outer_number_serialize(
None
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("FakeOuterStringSerialize") => {
let result = core.run(client.fake_outer_string_serialize(None));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.fake_outer_string_serialize(
None
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
// Disabled because there's no example.
// Some("TestBodyWithQueryParams") => {
// let result = core.run(client.test_body_with_query_params("query_example".to_string(), ???));
// println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
// },
/* Disabled because there's no example.
Some("TestBodyWithQueryParams") => {
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.test_body_with_query_params(
"query_example".to_string(),
???
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
*/
// Disabled because there's no example.
// Some("TestClientModel") => {
// let result = core.run(client.test_client_model(???));
// println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
// },
/* Disabled because there's no example.
Some("TestClientModel") => {
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.test_client_model(
???
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
*/
Some("TestEndpointParameters") => {
let result = core.run(client.test_endpoint_parameters(8.14, 1.2, "pattern_without_delimiter_example".to_string(), swagger::ByteArray(Vec::from("BYTE_ARRAY_DATA_HERE")), Some(56), Some(56), Some(789), Some(3.4), Some("string_example".to_string()), Some(swagger::ByteArray(Vec::from("BINARY_DATA_HERE"))), None, None, Some("password_example".to_string()), Some("callback_example".to_string())));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.test_endpoint_parameters(
8.14,
1.2,
"pattern_without_delimiter_example".to_string(),
swagger::ByteArray(Vec::from("BYTE_ARRAY_DATA_HERE")),
Some(56),
Some(56),
Some(789),
Some(3.4),
Some("string_example".to_string()),
Some(swagger::ByteArray(Vec::from("BINARY_DATA_HERE"))),
None,
None,
Some("password_example".to_string()),
Some("callback_example".to_string())
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("TestEnumParameters") => {
let result = core.run(client.test_enum_parameters(Some(&Vec::new()), Some("enum_header_string_example".to_string()), Some(&Vec::new()), Some("enum_query_string_example".to_string()), Some(56), Some(1.2), Some("enum_form_string_example".to_string())));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.test_enum_parameters(
Some(&Vec::new()),
Some("enum_header_string_example".to_string()),
Some(&Vec::new()),
Some("enum_query_string_example".to_string()),
Some(56),
Some(1.2),
Some("enum_form_string_example".to_string())
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
// Disabled because there's no example.
// Some("TestInlineAdditionalProperties") => {
// let result = core.run(client.test_inline_additional_properties(???));
// println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
// },
/* Disabled because there's no example.
Some("TestInlineAdditionalProperties") => {
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.test_inline_additional_properties(
???
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
*/
Some("TestJsonFormData") => {
let result = core.run(client.test_json_form_data("param_example".to_string(), "param2_example".to_string()));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.test_json_form_data(
"param_example".to_string(),
"param2_example".to_string()
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
// Disabled because there's no example.
// Some("TestClassname") => {
// let result = core.run(client.test_classname(???));
// println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
// },
/* Disabled because there's no example.
Some("TestClassname") => {
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.test_classname(
???
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
*/
// Disabled because there's no example.
// Some("AddPet") => {
// let result = core.run(client.add_pet(???));
// println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
// },
/* Disabled because there's no example.
Some("AddPet") => {
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.add_pet(
???
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
*/
Some("DeletePet") => {
let result = core.run(client.delete_pet(789, Some("api_key_example".to_string())));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.delete_pet(
789,
Some("api_key_example".to_string())
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("FindPetsByStatus") => {
let result = core.run(client.find_pets_by_status(&Vec::new()));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.find_pets_by_status(
&Vec::new()
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("FindPetsByTags") => {
let result = core.run(client.find_pets_by_tags(&Vec::new()));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.find_pets_by_tags(
&Vec::new()
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("GetPetById") => {
let result = core.run(client.get_pet_by_id(789));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.get_pet_by_id(
789
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
// Disabled because there's no example.
// Some("UpdatePet") => {
// let result = core.run(client.update_pet(???));
// println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
// },
/* Disabled because there's no example.
Some("UpdatePet") => {
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.update_pet(
???
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
*/
Some("UpdatePetWithForm") => {
let result = core.run(client.update_pet_with_form(789, Some("name_example".to_string()), Some("status_example".to_string())));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.update_pet_with_form(
789,
Some("name_example".to_string()),
Some("status_example".to_string())
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("UploadFile") => {
let result = core.run(client.upload_file(789, Some("additional_metadata_example".to_string()), Some(swagger::ByteArray(Vec::from("BINARY_DATA_HERE")))));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.upload_file(
789,
Some("additional_metadata_example".to_string()),
Some(swagger::ByteArray(Vec::from("BINARY_DATA_HERE")))
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("DeleteOrder") => {
let result = core.run(client.delete_order("order_id_example".to_string()));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.delete_order(
"order_id_example".to_string()
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("GetInventory") => {
let result = core.run(client.get_inventory());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.get_inventory(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("GetOrderById") => {
let result = core.run(client.get_order_by_id(789));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.get_order_by_id(
789
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
// Disabled because there's no example.
// Some("PlaceOrder") => {
// let result = core.run(client.place_order(???));
// println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
// },
/* Disabled because there's no example.
Some("PlaceOrder") => {
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.place_order(
???
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
*/
// Disabled because there's no example.
// Some("CreateUser") => {
// let result = core.run(client.create_user(???));
// println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
// },
/* Disabled because there's no example.
Some("CreateUser") => {
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.create_user(
???
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
*/
Some("CreateUsersWithArrayInput") => {
let result = core.run(client.create_users_with_array_input(&Vec::new()));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.create_users_with_array_input(
&Vec::new()
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("CreateUsersWithListInput") => {
let result = core.run(client.create_users_with_list_input(&Vec::new()));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.create_users_with_list_input(
&Vec::new()
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("DeleteUser") => {
let result = core.run(client.delete_user("username_example".to_string()));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.delete_user(
"username_example".to_string()
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("GetUserByName") => {
let result = core.run(client.get_user_by_name("username_example".to_string()));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.get_user_by_name(
"username_example".to_string()
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("LoginUser") => {
let result = core.run(client.login_user("username_example".to_string(), "password_example".to_string()));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.login_user(
"username_example".to_string(),
"password_example".to_string()
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("LogoutUser") => {
let result = core.run(client.logout_user());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.logout_user(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
// Disabled because there's no example.
// Some("UpdateUser") => {
// let result = core.run(client.update_user("username_example".to_string(), ???));
// println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
// },
/* Disabled because there's no example.
Some("UpdateUser") => {
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.update_user(
"username_example".to_string(),
???
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
*/
_ => {
panic!("Invalid operation provided")
}
}
}

View File

@ -8,9 +8,9 @@ extern crate petstore_with_fake_endpoints_models_for_testing;
extern crate swagger;
extern crate hyper;
extern crate openssl;
extern crate native_tls;
extern crate tokio_proto;
extern crate tokio;
extern crate tokio_tls;
extern crate native_tls;
extern crate clap;
// Imports required by server library.
@ -22,14 +22,18 @@ extern crate chrono;
extern crate error_chain;
extern crate uuid;
use futures::{Future, Stream};
use hyper::service::MakeService;
use hyper::server::conn::Http;
use openssl::x509::X509_FILETYPE_PEM;
use openssl::ssl::{SslAcceptorBuilder, SslMethod};
use openssl::error::ErrorStack;
use hyper::server::Http;
use tokio_proto::TcpServer;
use tokio::net::TcpListener;
use clap::{App, Arg};
use swagger::auth::AllowAllAuthenticator;
use std::sync::{Arc, Mutex};
use swagger::auth::MakeAllowAllAuthenticator;
use swagger::EmptyContext;
use tokio_tls::TlsAcceptorExt;
mod server_lib;
@ -54,12 +58,15 @@ fn main() {
.help("Whether to use HTTPS or not"))
.get_matches();
let server = server_lib::Server::new();
let service_fn = petstore_with_fake_endpoints_models_for_testing::server::MakeService::new(server);
let service_fn = MakeAllowAllAuthenticator::new(service_fn, "cosmo");
let service_fn =
petstore_with_fake_endpoints_models_for_testing::server::context::NewAddContext::<_, EmptyContext>::new(
AllowAllAuthenticator::new(
server_lib::NewService::new(),
"cosmo"
)
petstore_with_fake_endpoints_models_for_testing::server::context::MakeAddContext::<_, EmptyContext>::new(
service_fn
);
let addr = "127.0.0.1:80".parse().expect("Failed to parse bind address");
@ -67,9 +74,29 @@ fn main() {
let ssl = ssl().expect("Failed to load SSL keys");
let builder: native_tls::TlsAcceptorBuilder = native_tls::backend::openssl::TlsAcceptorBuilderExt::from_openssl(ssl);
let tls_acceptor = builder.build().expect("Failed to build TLS acceptor");
TcpServer::new(tokio_tls::proto::Server::new(Http::new(), tls_acceptor), addr).serve(service_fn);
let service_fn = Arc::new(Mutex::new(service_fn));
let tls_listener = TcpListener::bind(&addr).unwrap().incoming().for_each(move |tcp| {
let addr = tcp.peer_addr().expect("Unable to get remote address");
let service_fn = service_fn.clone();
hyper::rt::spawn(tls_acceptor.accept_async(tcp).map_err(|_| ()).and_then(move |tls| {
let ms = {
let mut service_fn = service_fn.lock().unwrap();
service_fn.make_service(&addr)
};
ms.and_then(move |service| {
Http::new().serve_connection(tls, service)
}).map_err(|_| ())
}));
Ok(())
}).map_err(|_| ());
hyper::rt::run(tls_listener);
} else {
// Using HTTP
TcpServer::new(Http::new(), addr).serve(service_fn);
hyper::rt::run(hyper::server::Server::bind(&addr).serve(service_fn).map_err(|e| panic!("{:?}", e)));
}
}

View File

@ -1,38 +1,292 @@
//! Main library entry point for petstore_with_fake_endpoints_models_for_testing implementation.
mod server;
#![allow(unused_imports)]
mod errors {
error_chain!{}
}
pub use self::errors::*;
use std::io;
use std::clone::Clone;
use futures::{self, Future};
use chrono;
use std::collections::HashMap;
use std::marker::PhantomData;
use hyper;
use petstore_with_fake_endpoints_models_for_testing;
use uuid;
use swagger;
use swagger::{Has, XSpanIdString};
use swagger::auth::Authorization;
pub struct NewService<C>{
marker: PhantomData<C>
use petstore_with_fake_endpoints_models_for_testing::{Api, ApiError,
TestSpecialTagsResponse,
FakeOuterBooleanSerializeResponse,
FakeOuterCompositeSerializeResponse,
FakeOuterNumberSerializeResponse,
FakeOuterStringSerializeResponse,
TestBodyWithQueryParamsResponse,
TestClientModelResponse,
TestEndpointParametersResponse,
TestEnumParametersResponse,
TestInlineAdditionalPropertiesResponse,
TestJsonFormDataResponse,
TestClassnameResponse,
AddPetResponse,
DeletePetResponse,
FindPetsByStatusResponse,
FindPetsByTagsResponse,
GetPetByIdResponse,
UpdatePetResponse,
UpdatePetWithFormResponse,
UploadFileResponse,
DeleteOrderResponse,
GetInventoryResponse,
GetOrderByIdResponse,
PlaceOrderResponse,
CreateUserResponse,
CreateUsersWithArrayInputResponse,
CreateUsersWithListInputResponse,
DeleteUserResponse,
GetUserByNameResponse,
LoginUserResponse,
LogoutUserResponse,
UpdateUserResponse
};
use petstore_with_fake_endpoints_models_for_testing::models;
#[derive(Copy, Clone)]
pub struct Server<C> {
marker: PhantomData<C>,
}
impl<C> NewService<C>{
impl<C> Server<C> {
pub fn new() -> Self {
NewService{marker:PhantomData}
Server{marker: PhantomData}
}
}
impl<C> hyper::server::NewService for NewService<C> where C: Has<XSpanIdString> + Has<Option<Authorization>> + Clone + 'static {
type Request = (hyper::Request, C);
type Response = hyper::Response;
type Error = hyper::Error;
type Instance = petstore_with_fake_endpoints_models_for_testing::server::Service<server::Server<C>, C>;
impl<C> Api<C> for Server<C> where C: Has<XSpanIdString>{
/// Instantiate a new server.
fn new_service(&self) -> io::Result<Self::Instance> {
Ok(petstore_with_fake_endpoints_models_for_testing::server::Service::new(server::Server::new()))
/// To test special tags
fn test_special_tags(&self, body: models::Client, context: &C) -> Box<Future<Item=TestSpecialTagsResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("test_special_tags({:?}) - X-Span-ID: {:?}", body, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn fake_outer_boolean_serialize(&self, body: Option<models::OuterBoolean>, context: &C) -> Box<Future<Item=FakeOuterBooleanSerializeResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("fake_outer_boolean_serialize({:?}) - X-Span-ID: {:?}", body, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn fake_outer_composite_serialize(&self, body: Option<models::OuterComposite>, context: &C) -> Box<Future<Item=FakeOuterCompositeSerializeResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("fake_outer_composite_serialize({:?}) - X-Span-ID: {:?}", body, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn fake_outer_number_serialize(&self, body: Option<models::OuterNumber>, context: &C) -> Box<Future<Item=FakeOuterNumberSerializeResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("fake_outer_number_serialize({:?}) - X-Span-ID: {:?}", body, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn fake_outer_string_serialize(&self, body: Option<models::OuterString>, context: &C) -> Box<Future<Item=FakeOuterStringSerializeResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("fake_outer_string_serialize({:?}) - X-Span-ID: {:?}", body, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn test_body_with_query_params(&self, query: String, body: models::User, context: &C) -> Box<Future<Item=TestBodyWithQueryParamsResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("test_body_with_query_params(\"{}\", {:?}) - X-Span-ID: {:?}", query, body, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// To test \"client\" model
fn test_client_model(&self, body: models::Client, context: &C) -> Box<Future<Item=TestClientModelResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("test_client_model({:?}) - X-Span-ID: {:?}", body, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트
fn test_endpoint_parameters(&self, number: f64, double: f64, pattern_without_delimiter: String, byte: swagger::ByteArray, integer: Option<i32>, int32: Option<i32>, int64: Option<i64>, float: Option<f32>, string: Option<String>, binary: Option<swagger::ByteArray>, date: Option<chrono::DateTime<chrono::Utc>>, date_time: Option<chrono::DateTime<chrono::Utc>>, password: Option<String>, callback: Option<String>, context: &C) -> Box<Future<Item=TestEndpointParametersResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("test_endpoint_parameters({}, {}, \"{}\", {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}) - X-Span-ID: {:?}", number, double, pattern_without_delimiter, byte, integer, int32, int64, float, string, binary, date, date_time, password, callback, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// To test enum parameters
fn test_enum_parameters(&self, enum_header_string_array: Option<&Vec<String>>, enum_header_string: Option<String>, enum_query_string_array: Option<&Vec<String>>, enum_query_string: Option<String>, enum_query_integer: Option<i32>, enum_query_double: Option<f64>, enum_form_string: Option<String>, context: &C) -> Box<Future<Item=TestEnumParametersResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("test_enum_parameters({:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}) - X-Span-ID: {:?}", enum_header_string_array, enum_header_string, enum_query_string_array, enum_query_string, enum_query_integer, enum_query_double, enum_form_string, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// test inline additionalProperties
fn test_inline_additional_properties(&self, param: HashMap<String, String>, context: &C) -> Box<Future<Item=TestInlineAdditionalPropertiesResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("test_inline_additional_properties({:?}) - X-Span-ID: {:?}", param, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// test json serialization of form data
fn test_json_form_data(&self, param: String, param2: String, context: &C) -> Box<Future<Item=TestJsonFormDataResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("test_json_form_data(\"{}\", \"{}\") - X-Span-ID: {:?}", param, param2, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// To test class name in snake case
fn test_classname(&self, body: models::Client, context: &C) -> Box<Future<Item=TestClassnameResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("test_classname({:?}) - X-Span-ID: {:?}", body, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// Add a new pet to the store
fn add_pet(&self, body: models::Pet, context: &C) -> Box<Future<Item=AddPetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("add_pet({:?}) - X-Span-ID: {:?}", body, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// Deletes a pet
fn delete_pet(&self, pet_id: i64, api_key: Option<String>, context: &C) -> Box<Future<Item=DeletePetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("delete_pet({}, {:?}) - X-Span-ID: {:?}", pet_id, api_key, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// Finds Pets by status
fn find_pets_by_status(&self, status: &Vec<String>, context: &C) -> Box<Future<Item=FindPetsByStatusResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("find_pets_by_status({:?}) - X-Span-ID: {:?}", status, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// Finds Pets by tags
fn find_pets_by_tags(&self, tags: &Vec<String>, context: &C) -> Box<Future<Item=FindPetsByTagsResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("find_pets_by_tags({:?}) - X-Span-ID: {:?}", tags, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// Find pet by ID
fn get_pet_by_id(&self, pet_id: i64, context: &C) -> Box<Future<Item=GetPetByIdResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("get_pet_by_id({}) - X-Span-ID: {:?}", pet_id, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// Update an existing pet
fn update_pet(&self, body: models::Pet, context: &C) -> Box<Future<Item=UpdatePetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("update_pet({:?}) - X-Span-ID: {:?}", body, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// Updates a pet in the store with form data
fn update_pet_with_form(&self, pet_id: i64, name: Option<String>, status: Option<String>, context: &C) -> Box<Future<Item=UpdatePetWithFormResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("update_pet_with_form({}, {:?}, {:?}) - X-Span-ID: {:?}", pet_id, name, status, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// uploads an image
fn upload_file(&self, pet_id: i64, additional_metadata: Option<String>, file: Option<swagger::ByteArray>, context: &C) -> Box<Future<Item=UploadFileResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("upload_file({}, {:?}, {:?}) - X-Span-ID: {:?}", pet_id, additional_metadata, file, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// Delete purchase order by ID
fn delete_order(&self, order_id: String, context: &C) -> Box<Future<Item=DeleteOrderResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("delete_order(\"{}\") - X-Span-ID: {:?}", order_id, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// Returns pet inventories by status
fn get_inventory(&self, context: &C) -> Box<Future<Item=GetInventoryResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("get_inventory() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// Find purchase order by ID
fn get_order_by_id(&self, order_id: i64, context: &C) -> Box<Future<Item=GetOrderByIdResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("get_order_by_id({}) - X-Span-ID: {:?}", order_id, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// Place an order for a pet
fn place_order(&self, body: models::Order, context: &C) -> Box<Future<Item=PlaceOrderResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("place_order({:?}) - X-Span-ID: {:?}", body, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// Create user
fn create_user(&self, body: models::User, context: &C) -> Box<Future<Item=CreateUserResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("create_user({:?}) - X-Span-ID: {:?}", body, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// Creates list of users with given input array
fn create_users_with_array_input(&self, body: &Vec<models::User>, context: &C) -> Box<Future<Item=CreateUsersWithArrayInputResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("create_users_with_array_input({:?}) - X-Span-ID: {:?}", body, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// Creates list of users with given input array
fn create_users_with_list_input(&self, body: &Vec<models::User>, context: &C) -> Box<Future<Item=CreateUsersWithListInputResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("create_users_with_list_input({:?}) - X-Span-ID: {:?}", body, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// Delete user
fn delete_user(&self, username: String, context: &C) -> Box<Future<Item=DeleteUserResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("delete_user(\"{}\") - X-Span-ID: {:?}", username, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// Get user by user name
fn get_user_by_name(&self, username: String, context: &C) -> Box<Future<Item=GetUserByNameResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("get_user_by_name(\"{}\") - X-Span-ID: {:?}", username, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// Logs user into the system
fn login_user(&self, username: String, password: String, context: &C) -> Box<Future<Item=LoginUserResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("login_user(\"{}\", \"{}\") - X-Span-ID: {:?}", username, password, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// Logs out current logged in user session
fn logout_user(&self, context: &C) -> Box<Future<Item=LogoutUserResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("logout_user() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// Updated user
fn update_user(&self, username: String, body: models::User, context: &C) -> Box<Future<Item=UpdateUserResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("update_user(\"{}\", {:?}) - X-Span-ID: {:?}", username, body, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
}

View File

@ -1,18 +1,17 @@
#![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)]
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
// Crates with macros
#[macro_use]
extern crate serde_derive;
#[cfg(any(feature = "client", feature = "server"))]
#[cfg(any(feature = "server"))]
#[macro_use]
extern crate hyper;
extern crate lazy_static;
#[cfg(any(feature = "client", feature = "server"))]
#[macro_use]
extern crate url;
#[macro_use]
extern crate log;
// Crates for conversion support
#[cfg(feature = "conversion")]
@ -26,13 +25,40 @@ extern crate frunk_core;
extern crate mime;
extern crate serde;
extern crate serde_json;
extern crate serde_xml_rs;
extern crate futures;
extern crate chrono;
extern crate swagger;
#[cfg(any(feature = "client", feature = "server"))]
extern crate hyper;
#[cfg(any(feature = "client"))]
extern crate hyper_tls;
#[cfg(any(feature = "client", feature = "server"))]
extern crate openssl;
#[cfg(any(feature = "client", feature = "server"))]
extern crate native_tls;
#[cfg(feature = "server")]
extern crate percent_encoding;
#[cfg(any(feature = "client", feature = "server"))]
extern crate serde_json;
#[cfg(any(feature = "client", feature = "server"))]
extern crate serde_ignored;
#[cfg(any(feature = "client", feature = "server"))]
extern crate tokio;
#[cfg(any(feature = "client", feature = "server"))]
extern crate uuid;
extern crate serde_xml_rs;
#[cfg(any(feature = "client", feature = "server"))]
extern crate multipart;
extern crate mime_0_2;
#[cfg(any(feature = "client", feature = "server"))]
extern crate serde_urlencoded;
use hyper::header::HeaderValue;
use futures::Stream;
use std::io::Error;
@ -319,100 +345,100 @@ pub enum UpdateUserResponse {
pub trait Api<C> {
/// To test special tags
fn test_special_tags(&self, body: models::Client, context: &C) -> Box<dyn Future<Item=TestSpecialTagsResponse, Error=ApiError>>;
fn test_special_tags(&self, body: models::Client, context: &C) -> Box<dyn Future<Item=TestSpecialTagsResponse, Error=ApiError> + Send>;
fn fake_outer_boolean_serialize(&self, body: Option<models::OuterBoolean>, context: &C) -> Box<dyn Future<Item=FakeOuterBooleanSerializeResponse, Error=ApiError>>;
fn fake_outer_boolean_serialize(&self, body: Option<models::OuterBoolean>, context: &C) -> Box<dyn Future<Item=FakeOuterBooleanSerializeResponse, Error=ApiError> + Send>;
fn fake_outer_composite_serialize(&self, body: Option<models::OuterComposite>, context: &C) -> Box<dyn Future<Item=FakeOuterCompositeSerializeResponse, Error=ApiError>>;
fn fake_outer_composite_serialize(&self, body: Option<models::OuterComposite>, context: &C) -> Box<dyn Future<Item=FakeOuterCompositeSerializeResponse, Error=ApiError> + Send>;
fn fake_outer_number_serialize(&self, body: Option<models::OuterNumber>, context: &C) -> Box<dyn Future<Item=FakeOuterNumberSerializeResponse, Error=ApiError>>;
fn fake_outer_number_serialize(&self, body: Option<models::OuterNumber>, context: &C) -> Box<dyn Future<Item=FakeOuterNumberSerializeResponse, Error=ApiError> + Send>;
fn fake_outer_string_serialize(&self, body: Option<models::OuterString>, context: &C) -> Box<dyn Future<Item=FakeOuterStringSerializeResponse, Error=ApiError>>;
fn fake_outer_string_serialize(&self, body: Option<models::OuterString>, context: &C) -> Box<dyn Future<Item=FakeOuterStringSerializeResponse, Error=ApiError> + Send>;
fn test_body_with_query_params(&self, query: String, body: models::User, context: &C) -> Box<dyn Future<Item=TestBodyWithQueryParamsResponse, Error=ApiError>>;
fn test_body_with_query_params(&self, query: String, body: models::User, context: &C) -> Box<dyn Future<Item=TestBodyWithQueryParamsResponse, Error=ApiError> + Send>;
/// To test \"client\" model
fn test_client_model(&self, body: models::Client, context: &C) -> Box<dyn Future<Item=TestClientModelResponse, Error=ApiError>>;
fn test_client_model(&self, body: models::Client, context: &C) -> Box<dyn Future<Item=TestClientModelResponse, Error=ApiError> + Send>;
/// Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트
fn test_endpoint_parameters(&self, number: f64, double: f64, pattern_without_delimiter: String, byte: swagger::ByteArray, integer: Option<i32>, int32: Option<i32>, int64: Option<i64>, float: Option<f32>, string: Option<String>, binary: Option<swagger::ByteArray>, date: Option<chrono::DateTime<chrono::Utc>>, date_time: Option<chrono::DateTime<chrono::Utc>>, password: Option<String>, callback: Option<String>, context: &C) -> Box<dyn Future<Item=TestEndpointParametersResponse, Error=ApiError>>;
fn test_endpoint_parameters(&self, number: f64, double: f64, pattern_without_delimiter: String, byte: swagger::ByteArray, integer: Option<i32>, int32: Option<i32>, int64: Option<i64>, float: Option<f32>, string: Option<String>, binary: Option<swagger::ByteArray>, date: Option<chrono::DateTime<chrono::Utc>>, date_time: Option<chrono::DateTime<chrono::Utc>>, password: Option<String>, callback: Option<String>, context: &C) -> Box<dyn Future<Item=TestEndpointParametersResponse, Error=ApiError> + Send>;
/// To test enum parameters
fn test_enum_parameters(&self, enum_header_string_array: Option<&Vec<String>>, enum_header_string: Option<String>, enum_query_string_array: Option<&Vec<String>>, enum_query_string: Option<String>, enum_query_integer: Option<i32>, enum_query_double: Option<f64>, enum_form_string: Option<String>, context: &C) -> Box<dyn Future<Item=TestEnumParametersResponse, Error=ApiError>>;
fn test_enum_parameters(&self, enum_header_string_array: Option<&Vec<String>>, enum_header_string: Option<String>, enum_query_string_array: Option<&Vec<String>>, enum_query_string: Option<String>, enum_query_integer: Option<i32>, enum_query_double: Option<f64>, enum_form_string: Option<String>, context: &C) -> Box<dyn Future<Item=TestEnumParametersResponse, Error=ApiError> + Send>;
/// test inline additionalProperties
fn test_inline_additional_properties(&self, param: HashMap<String, String>, context: &C) -> Box<dyn Future<Item=TestInlineAdditionalPropertiesResponse, Error=ApiError>>;
fn test_inline_additional_properties(&self, param: HashMap<String, String>, context: &C) -> Box<dyn Future<Item=TestInlineAdditionalPropertiesResponse, Error=ApiError> + Send>;
/// test json serialization of form data
fn test_json_form_data(&self, param: String, param2: String, context: &C) -> Box<dyn Future<Item=TestJsonFormDataResponse, Error=ApiError>>;
fn test_json_form_data(&self, param: String, param2: String, context: &C) -> Box<dyn Future<Item=TestJsonFormDataResponse, Error=ApiError> + Send>;
/// To test class name in snake case
fn test_classname(&self, body: models::Client, context: &C) -> Box<dyn Future<Item=TestClassnameResponse, Error=ApiError>>;
fn test_classname(&self, body: models::Client, context: &C) -> Box<dyn Future<Item=TestClassnameResponse, Error=ApiError> + Send>;
/// Add a new pet to the store
fn add_pet(&self, body: models::Pet, context: &C) -> Box<dyn Future<Item=AddPetResponse, Error=ApiError>>;
fn add_pet(&self, body: models::Pet, context: &C) -> Box<dyn Future<Item=AddPetResponse, Error=ApiError> + Send>;
/// Deletes a pet
fn delete_pet(&self, pet_id: i64, api_key: Option<String>, context: &C) -> Box<dyn Future<Item=DeletePetResponse, Error=ApiError>>;
fn delete_pet(&self, pet_id: i64, api_key: Option<String>, context: &C) -> Box<dyn Future<Item=DeletePetResponse, Error=ApiError> + Send>;
/// Finds Pets by status
fn find_pets_by_status(&self, status: &Vec<String>, context: &C) -> Box<dyn Future<Item=FindPetsByStatusResponse, Error=ApiError>>;
fn find_pets_by_status(&self, status: &Vec<String>, context: &C) -> Box<dyn Future<Item=FindPetsByStatusResponse, Error=ApiError> + Send>;
/// Finds Pets by tags
fn find_pets_by_tags(&self, tags: &Vec<String>, context: &C) -> Box<dyn Future<Item=FindPetsByTagsResponse, Error=ApiError>>;
fn find_pets_by_tags(&self, tags: &Vec<String>, context: &C) -> Box<dyn Future<Item=FindPetsByTagsResponse, Error=ApiError> + Send>;
/// Find pet by ID
fn get_pet_by_id(&self, pet_id: i64, context: &C) -> Box<dyn Future<Item=GetPetByIdResponse, Error=ApiError>>;
fn get_pet_by_id(&self, pet_id: i64, context: &C) -> Box<dyn Future<Item=GetPetByIdResponse, Error=ApiError> + Send>;
/// Update an existing pet
fn update_pet(&self, body: models::Pet, context: &C) -> Box<dyn Future<Item=UpdatePetResponse, Error=ApiError>>;
fn update_pet(&self, body: models::Pet, context: &C) -> Box<dyn Future<Item=UpdatePetResponse, Error=ApiError> + Send>;
/// Updates a pet in the store with form data
fn update_pet_with_form(&self, pet_id: i64, name: Option<String>, status: Option<String>, context: &C) -> Box<dyn Future<Item=UpdatePetWithFormResponse, Error=ApiError>>;
fn update_pet_with_form(&self, pet_id: i64, name: Option<String>, status: Option<String>, context: &C) -> Box<dyn Future<Item=UpdatePetWithFormResponse, Error=ApiError> + Send>;
/// uploads an image
fn upload_file(&self, pet_id: i64, additional_metadata: Option<String>, file: Option<swagger::ByteArray>, context: &C) -> Box<dyn Future<Item=UploadFileResponse, Error=ApiError>>;
fn upload_file(&self, pet_id: i64, additional_metadata: Option<String>, file: Option<swagger::ByteArray>, context: &C) -> Box<dyn Future<Item=UploadFileResponse, Error=ApiError> + Send>;
/// Delete purchase order by ID
fn delete_order(&self, order_id: String, context: &C) -> Box<dyn Future<Item=DeleteOrderResponse, Error=ApiError>>;
fn delete_order(&self, order_id: String, context: &C) -> Box<dyn Future<Item=DeleteOrderResponse, Error=ApiError> + Send>;
/// Returns pet inventories by status
fn get_inventory(&self, context: &C) -> Box<dyn Future<Item=GetInventoryResponse, Error=ApiError>>;
fn get_inventory(&self, context: &C) -> Box<dyn Future<Item=GetInventoryResponse, Error=ApiError> + Send>;
/// Find purchase order by ID
fn get_order_by_id(&self, order_id: i64, context: &C) -> Box<dyn Future<Item=GetOrderByIdResponse, Error=ApiError>>;
fn get_order_by_id(&self, order_id: i64, context: &C) -> Box<dyn Future<Item=GetOrderByIdResponse, Error=ApiError> + Send>;
/// Place an order for a pet
fn place_order(&self, body: models::Order, context: &C) -> Box<dyn Future<Item=PlaceOrderResponse, Error=ApiError>>;
fn place_order(&self, body: models::Order, context: &C) -> Box<dyn Future<Item=PlaceOrderResponse, Error=ApiError> + Send>;
/// Create user
fn create_user(&self, body: models::User, context: &C) -> Box<dyn Future<Item=CreateUserResponse, Error=ApiError>>;
fn create_user(&self, body: models::User, context: &C) -> Box<dyn Future<Item=CreateUserResponse, Error=ApiError> + Send>;
/// Creates list of users with given input array
fn create_users_with_array_input(&self, body: &Vec<models::User>, context: &C) -> Box<dyn Future<Item=CreateUsersWithArrayInputResponse, Error=ApiError>>;
fn create_users_with_array_input(&self, body: &Vec<models::User>, context: &C) -> Box<dyn Future<Item=CreateUsersWithArrayInputResponse, Error=ApiError> + Send>;
/// Creates list of users with given input array
fn create_users_with_list_input(&self, body: &Vec<models::User>, context: &C) -> Box<dyn Future<Item=CreateUsersWithListInputResponse, Error=ApiError>>;
fn create_users_with_list_input(&self, body: &Vec<models::User>, context: &C) -> Box<dyn Future<Item=CreateUsersWithListInputResponse, Error=ApiError> + Send>;
/// Delete user
fn delete_user(&self, username: String, context: &C) -> Box<dyn Future<Item=DeleteUserResponse, Error=ApiError>>;
fn delete_user(&self, username: String, context: &C) -> Box<dyn Future<Item=DeleteUserResponse, Error=ApiError> + Send>;
/// Get user by user name
fn get_user_by_name(&self, username: String, context: &C) -> Box<dyn Future<Item=GetUserByNameResponse, Error=ApiError>>;
fn get_user_by_name(&self, username: String, context: &C) -> Box<dyn Future<Item=GetUserByNameResponse, Error=ApiError> + Send>;
/// Logs user into the system
fn login_user(&self, username: String, password: String, context: &C) -> Box<dyn Future<Item=LoginUserResponse, Error=ApiError>>;
fn login_user(&self, username: String, password: String, context: &C) -> Box<dyn Future<Item=LoginUserResponse, Error=ApiError> + Send>;
/// Logs out current logged in user session
fn logout_user(&self, context: &C) -> Box<dyn Future<Item=LogoutUserResponse, Error=ApiError>>;
fn logout_user(&self, context: &C) -> Box<dyn Future<Item=LogoutUserResponse, Error=ApiError> + Send>;
/// Updated user
fn update_user(&self, username: String, body: models::User, context: &C) -> Box<dyn Future<Item=UpdateUserResponse, Error=ApiError>>;
fn update_user(&self, username: String, body: models::User, context: &C) -> Box<dyn Future<Item=UpdateUserResponse, Error=ApiError> + Send>;
}
@ -420,100 +446,100 @@ pub trait Api<C> {
pub trait ApiNoContext {
/// To test special tags
fn test_special_tags(&self, body: models::Client) -> Box<dyn Future<Item=TestSpecialTagsResponse, Error=ApiError>>;
fn test_special_tags(&self, body: models::Client) -> Box<dyn Future<Item=TestSpecialTagsResponse, Error=ApiError> + Send>;
fn fake_outer_boolean_serialize(&self, body: Option<models::OuterBoolean>) -> Box<dyn Future<Item=FakeOuterBooleanSerializeResponse, Error=ApiError>>;
fn fake_outer_boolean_serialize(&self, body: Option<models::OuterBoolean>) -> Box<dyn Future<Item=FakeOuterBooleanSerializeResponse, Error=ApiError> + Send>;
fn fake_outer_composite_serialize(&self, body: Option<models::OuterComposite>) -> Box<dyn Future<Item=FakeOuterCompositeSerializeResponse, Error=ApiError>>;
fn fake_outer_composite_serialize(&self, body: Option<models::OuterComposite>) -> Box<dyn Future<Item=FakeOuterCompositeSerializeResponse, Error=ApiError> + Send>;
fn fake_outer_number_serialize(&self, body: Option<models::OuterNumber>) -> Box<dyn Future<Item=FakeOuterNumberSerializeResponse, Error=ApiError>>;
fn fake_outer_number_serialize(&self, body: Option<models::OuterNumber>) -> Box<dyn Future<Item=FakeOuterNumberSerializeResponse, Error=ApiError> + Send>;
fn fake_outer_string_serialize(&self, body: Option<models::OuterString>) -> Box<dyn Future<Item=FakeOuterStringSerializeResponse, Error=ApiError>>;
fn fake_outer_string_serialize(&self, body: Option<models::OuterString>) -> Box<dyn Future<Item=FakeOuterStringSerializeResponse, Error=ApiError> + Send>;
fn test_body_with_query_params(&self, query: String, body: models::User) -> Box<dyn Future<Item=TestBodyWithQueryParamsResponse, Error=ApiError>>;
fn test_body_with_query_params(&self, query: String, body: models::User) -> Box<dyn Future<Item=TestBodyWithQueryParamsResponse, Error=ApiError> + Send>;
/// To test \"client\" model
fn test_client_model(&self, body: models::Client) -> Box<dyn Future<Item=TestClientModelResponse, Error=ApiError>>;
fn test_client_model(&self, body: models::Client) -> Box<dyn Future<Item=TestClientModelResponse, Error=ApiError> + Send>;
/// Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트
fn test_endpoint_parameters(&self, number: f64, double: f64, pattern_without_delimiter: String, byte: swagger::ByteArray, integer: Option<i32>, int32: Option<i32>, int64: Option<i64>, float: Option<f32>, string: Option<String>, binary: Option<swagger::ByteArray>, date: Option<chrono::DateTime<chrono::Utc>>, date_time: Option<chrono::DateTime<chrono::Utc>>, password: Option<String>, callback: Option<String>) -> Box<dyn Future<Item=TestEndpointParametersResponse, Error=ApiError>>;
fn test_endpoint_parameters(&self, number: f64, double: f64, pattern_without_delimiter: String, byte: swagger::ByteArray, integer: Option<i32>, int32: Option<i32>, int64: Option<i64>, float: Option<f32>, string: Option<String>, binary: Option<swagger::ByteArray>, date: Option<chrono::DateTime<chrono::Utc>>, date_time: Option<chrono::DateTime<chrono::Utc>>, password: Option<String>, callback: Option<String>) -> Box<dyn Future<Item=TestEndpointParametersResponse, Error=ApiError> + Send>;
/// To test enum parameters
fn test_enum_parameters(&self, enum_header_string_array: Option<&Vec<String>>, enum_header_string: Option<String>, enum_query_string_array: Option<&Vec<String>>, enum_query_string: Option<String>, enum_query_integer: Option<i32>, enum_query_double: Option<f64>, enum_form_string: Option<String>) -> Box<dyn Future<Item=TestEnumParametersResponse, Error=ApiError>>;
fn test_enum_parameters(&self, enum_header_string_array: Option<&Vec<String>>, enum_header_string: Option<String>, enum_query_string_array: Option<&Vec<String>>, enum_query_string: Option<String>, enum_query_integer: Option<i32>, enum_query_double: Option<f64>, enum_form_string: Option<String>) -> Box<dyn Future<Item=TestEnumParametersResponse, Error=ApiError> + Send>;
/// test inline additionalProperties
fn test_inline_additional_properties(&self, param: HashMap<String, String>) -> Box<dyn Future<Item=TestInlineAdditionalPropertiesResponse, Error=ApiError>>;
fn test_inline_additional_properties(&self, param: HashMap<String, String>) -> Box<dyn Future<Item=TestInlineAdditionalPropertiesResponse, Error=ApiError> + Send>;
/// test json serialization of form data
fn test_json_form_data(&self, param: String, param2: String) -> Box<dyn Future<Item=TestJsonFormDataResponse, Error=ApiError>>;
fn test_json_form_data(&self, param: String, param2: String) -> Box<dyn Future<Item=TestJsonFormDataResponse, Error=ApiError> + Send>;
/// To test class name in snake case
fn test_classname(&self, body: models::Client) -> Box<dyn Future<Item=TestClassnameResponse, Error=ApiError>>;
fn test_classname(&self, body: models::Client) -> Box<dyn Future<Item=TestClassnameResponse, Error=ApiError> + Send>;
/// Add a new pet to the store
fn add_pet(&self, body: models::Pet) -> Box<dyn Future<Item=AddPetResponse, Error=ApiError>>;
fn add_pet(&self, body: models::Pet) -> Box<dyn Future<Item=AddPetResponse, Error=ApiError> + Send>;
/// Deletes a pet
fn delete_pet(&self, pet_id: i64, api_key: Option<String>) -> Box<dyn Future<Item=DeletePetResponse, Error=ApiError>>;
fn delete_pet(&self, pet_id: i64, api_key: Option<String>) -> Box<dyn Future<Item=DeletePetResponse, Error=ApiError> + Send>;
/// Finds Pets by status
fn find_pets_by_status(&self, status: &Vec<String>) -> Box<dyn Future<Item=FindPetsByStatusResponse, Error=ApiError>>;
fn find_pets_by_status(&self, status: &Vec<String>) -> Box<dyn Future<Item=FindPetsByStatusResponse, Error=ApiError> + Send>;
/// Finds Pets by tags
fn find_pets_by_tags(&self, tags: &Vec<String>) -> Box<dyn Future<Item=FindPetsByTagsResponse, Error=ApiError>>;
fn find_pets_by_tags(&self, tags: &Vec<String>) -> Box<dyn Future<Item=FindPetsByTagsResponse, Error=ApiError> + Send>;
/// Find pet by ID
fn get_pet_by_id(&self, pet_id: i64) -> Box<dyn Future<Item=GetPetByIdResponse, Error=ApiError>>;
fn get_pet_by_id(&self, pet_id: i64) -> Box<dyn Future<Item=GetPetByIdResponse, Error=ApiError> + Send>;
/// Update an existing pet
fn update_pet(&self, body: models::Pet) -> Box<dyn Future<Item=UpdatePetResponse, Error=ApiError>>;
fn update_pet(&self, body: models::Pet) -> Box<dyn Future<Item=UpdatePetResponse, Error=ApiError> + Send>;
/// Updates a pet in the store with form data
fn update_pet_with_form(&self, pet_id: i64, name: Option<String>, status: Option<String>) -> Box<dyn Future<Item=UpdatePetWithFormResponse, Error=ApiError>>;
fn update_pet_with_form(&self, pet_id: i64, name: Option<String>, status: Option<String>) -> Box<dyn Future<Item=UpdatePetWithFormResponse, Error=ApiError> + Send>;
/// uploads an image
fn upload_file(&self, pet_id: i64, additional_metadata: Option<String>, file: Option<swagger::ByteArray>) -> Box<dyn Future<Item=UploadFileResponse, Error=ApiError>>;
fn upload_file(&self, pet_id: i64, additional_metadata: Option<String>, file: Option<swagger::ByteArray>) -> Box<dyn Future<Item=UploadFileResponse, Error=ApiError> + Send>;
/// Delete purchase order by ID
fn delete_order(&self, order_id: String) -> Box<dyn Future<Item=DeleteOrderResponse, Error=ApiError>>;
fn delete_order(&self, order_id: String) -> Box<dyn Future<Item=DeleteOrderResponse, Error=ApiError> + Send>;
/// Returns pet inventories by status
fn get_inventory(&self) -> Box<dyn Future<Item=GetInventoryResponse, Error=ApiError>>;
fn get_inventory(&self) -> Box<dyn Future<Item=GetInventoryResponse, Error=ApiError> + Send>;
/// Find purchase order by ID
fn get_order_by_id(&self, order_id: i64) -> Box<dyn Future<Item=GetOrderByIdResponse, Error=ApiError>>;
fn get_order_by_id(&self, order_id: i64) -> Box<dyn Future<Item=GetOrderByIdResponse, Error=ApiError> + Send>;
/// Place an order for a pet
fn place_order(&self, body: models::Order) -> Box<dyn Future<Item=PlaceOrderResponse, Error=ApiError>>;
fn place_order(&self, body: models::Order) -> Box<dyn Future<Item=PlaceOrderResponse, Error=ApiError> + Send>;
/// Create user
fn create_user(&self, body: models::User) -> Box<dyn Future<Item=CreateUserResponse, Error=ApiError>>;
fn create_user(&self, body: models::User) -> Box<dyn Future<Item=CreateUserResponse, Error=ApiError> + Send>;
/// Creates list of users with given input array
fn create_users_with_array_input(&self, body: &Vec<models::User>) -> Box<dyn Future<Item=CreateUsersWithArrayInputResponse, Error=ApiError>>;
fn create_users_with_array_input(&self, body: &Vec<models::User>) -> Box<dyn Future<Item=CreateUsersWithArrayInputResponse, Error=ApiError> + Send>;
/// Creates list of users with given input array
fn create_users_with_list_input(&self, body: &Vec<models::User>) -> Box<dyn Future<Item=CreateUsersWithListInputResponse, Error=ApiError>>;
fn create_users_with_list_input(&self, body: &Vec<models::User>) -> Box<dyn Future<Item=CreateUsersWithListInputResponse, Error=ApiError> + Send>;
/// Delete user
fn delete_user(&self, username: String) -> Box<dyn Future<Item=DeleteUserResponse, Error=ApiError>>;
fn delete_user(&self, username: String) -> Box<dyn Future<Item=DeleteUserResponse, Error=ApiError> + Send>;
/// Get user by user name
fn get_user_by_name(&self, username: String) -> Box<dyn Future<Item=GetUserByNameResponse, Error=ApiError>>;
fn get_user_by_name(&self, username: String) -> Box<dyn Future<Item=GetUserByNameResponse, Error=ApiError> + Send>;
/// Logs user into the system
fn login_user(&self, username: String, password: String) -> Box<dyn Future<Item=LoginUserResponse, Error=ApiError>>;
fn login_user(&self, username: String, password: String) -> Box<dyn Future<Item=LoginUserResponse, Error=ApiError> + Send>;
/// Logs out current logged in user session
fn logout_user(&self) -> Box<dyn Future<Item=LogoutUserResponse, Error=ApiError>>;
fn logout_user(&self) -> Box<dyn Future<Item=LogoutUserResponse, Error=ApiError> + Send>;
/// Updated user
fn update_user(&self, username: String, body: models::User) -> Box<dyn Future<Item=UpdateUserResponse, Error=ApiError>>;
fn update_user(&self, username: String, body: models::User) -> Box<dyn Future<Item=UpdateUserResponse, Error=ApiError> + Send>;
}
@ -532,162 +558,162 @@ impl<'a, T: Api<C> + Sized, C> ContextWrapperExt<'a, C> for T {
impl<'a, T: Api<C>, C> ApiNoContext for ContextWrapper<'a, T, C> {
/// To test special tags
fn test_special_tags(&self, body: models::Client) -> Box<dyn Future<Item=TestSpecialTagsResponse, Error=ApiError>> {
fn test_special_tags(&self, body: models::Client) -> Box<dyn Future<Item=TestSpecialTagsResponse, Error=ApiError> + Send> {
self.api().test_special_tags(body, &self.context())
}
fn fake_outer_boolean_serialize(&self, body: Option<models::OuterBoolean>) -> Box<dyn Future<Item=FakeOuterBooleanSerializeResponse, Error=ApiError>> {
fn fake_outer_boolean_serialize(&self, body: Option<models::OuterBoolean>) -> Box<dyn Future<Item=FakeOuterBooleanSerializeResponse, Error=ApiError> + Send> {
self.api().fake_outer_boolean_serialize(body, &self.context())
}
fn fake_outer_composite_serialize(&self, body: Option<models::OuterComposite>) -> Box<dyn Future<Item=FakeOuterCompositeSerializeResponse, Error=ApiError>> {
fn fake_outer_composite_serialize(&self, body: Option<models::OuterComposite>) -> Box<dyn Future<Item=FakeOuterCompositeSerializeResponse, Error=ApiError> + Send> {
self.api().fake_outer_composite_serialize(body, &self.context())
}
fn fake_outer_number_serialize(&self, body: Option<models::OuterNumber>) -> Box<dyn Future<Item=FakeOuterNumberSerializeResponse, Error=ApiError>> {
fn fake_outer_number_serialize(&self, body: Option<models::OuterNumber>) -> Box<dyn Future<Item=FakeOuterNumberSerializeResponse, Error=ApiError> + Send> {
self.api().fake_outer_number_serialize(body, &self.context())
}
fn fake_outer_string_serialize(&self, body: Option<models::OuterString>) -> Box<dyn Future<Item=FakeOuterStringSerializeResponse, Error=ApiError>> {
fn fake_outer_string_serialize(&self, body: Option<models::OuterString>) -> Box<dyn Future<Item=FakeOuterStringSerializeResponse, Error=ApiError> + Send> {
self.api().fake_outer_string_serialize(body, &self.context())
}
fn test_body_with_query_params(&self, query: String, body: models::User) -> Box<dyn Future<Item=TestBodyWithQueryParamsResponse, Error=ApiError>> {
fn test_body_with_query_params(&self, query: String, body: models::User) -> Box<dyn Future<Item=TestBodyWithQueryParamsResponse, Error=ApiError> + Send> {
self.api().test_body_with_query_params(query, body, &self.context())
}
/// To test \"client\" model
fn test_client_model(&self, body: models::Client) -> Box<dyn Future<Item=TestClientModelResponse, Error=ApiError>> {
fn test_client_model(&self, body: models::Client) -> Box<dyn Future<Item=TestClientModelResponse, Error=ApiError> + Send> {
self.api().test_client_model(body, &self.context())
}
/// Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트
fn test_endpoint_parameters(&self, number: f64, double: f64, pattern_without_delimiter: String, byte: swagger::ByteArray, integer: Option<i32>, int32: Option<i32>, int64: Option<i64>, float: Option<f32>, string: Option<String>, binary: Option<swagger::ByteArray>, date: Option<chrono::DateTime<chrono::Utc>>, date_time: Option<chrono::DateTime<chrono::Utc>>, password: Option<String>, callback: Option<String>) -> Box<dyn Future<Item=TestEndpointParametersResponse, Error=ApiError>> {
fn test_endpoint_parameters(&self, number: f64, double: f64, pattern_without_delimiter: String, byte: swagger::ByteArray, integer: Option<i32>, int32: Option<i32>, int64: Option<i64>, float: Option<f32>, string: Option<String>, binary: Option<swagger::ByteArray>, date: Option<chrono::DateTime<chrono::Utc>>, date_time: Option<chrono::DateTime<chrono::Utc>>, password: Option<String>, callback: Option<String>) -> Box<dyn Future<Item=TestEndpointParametersResponse, Error=ApiError> + Send> {
self.api().test_endpoint_parameters(number, double, pattern_without_delimiter, byte, integer, int32, int64, float, string, binary, date, date_time, password, callback, &self.context())
}
/// To test enum parameters
fn test_enum_parameters(&self, enum_header_string_array: Option<&Vec<String>>, enum_header_string: Option<String>, enum_query_string_array: Option<&Vec<String>>, enum_query_string: Option<String>, enum_query_integer: Option<i32>, enum_query_double: Option<f64>, enum_form_string: Option<String>) -> Box<dyn Future<Item=TestEnumParametersResponse, Error=ApiError>> {
fn test_enum_parameters(&self, enum_header_string_array: Option<&Vec<String>>, enum_header_string: Option<String>, enum_query_string_array: Option<&Vec<String>>, enum_query_string: Option<String>, enum_query_integer: Option<i32>, enum_query_double: Option<f64>, enum_form_string: Option<String>) -> Box<dyn Future<Item=TestEnumParametersResponse, Error=ApiError> + Send> {
self.api().test_enum_parameters(enum_header_string_array, enum_header_string, enum_query_string_array, enum_query_string, enum_query_integer, enum_query_double, enum_form_string, &self.context())
}
/// test inline additionalProperties
fn test_inline_additional_properties(&self, param: HashMap<String, String>) -> Box<dyn Future<Item=TestInlineAdditionalPropertiesResponse, Error=ApiError>> {
fn test_inline_additional_properties(&self, param: HashMap<String, String>) -> Box<dyn Future<Item=TestInlineAdditionalPropertiesResponse, Error=ApiError> + Send> {
self.api().test_inline_additional_properties(param, &self.context())
}
/// test json serialization of form data
fn test_json_form_data(&self, param: String, param2: String) -> Box<dyn Future<Item=TestJsonFormDataResponse, Error=ApiError>> {
fn test_json_form_data(&self, param: String, param2: String) -> Box<dyn Future<Item=TestJsonFormDataResponse, Error=ApiError> + Send> {
self.api().test_json_form_data(param, param2, &self.context())
}
/// To test class name in snake case
fn test_classname(&self, body: models::Client) -> Box<dyn Future<Item=TestClassnameResponse, Error=ApiError>> {
fn test_classname(&self, body: models::Client) -> Box<dyn Future<Item=TestClassnameResponse, Error=ApiError> + Send> {
self.api().test_classname(body, &self.context())
}
/// Add a new pet to the store
fn add_pet(&self, body: models::Pet) -> Box<dyn Future<Item=AddPetResponse, Error=ApiError>> {
fn add_pet(&self, body: models::Pet) -> Box<dyn Future<Item=AddPetResponse, Error=ApiError> + Send> {
self.api().add_pet(body, &self.context())
}
/// Deletes a pet
fn delete_pet(&self, pet_id: i64, api_key: Option<String>) -> Box<dyn Future<Item=DeletePetResponse, Error=ApiError>> {
fn delete_pet(&self, pet_id: i64, api_key: Option<String>) -> Box<dyn Future<Item=DeletePetResponse, Error=ApiError> + Send> {
self.api().delete_pet(pet_id, api_key, &self.context())
}
/// Finds Pets by status
fn find_pets_by_status(&self, status: &Vec<String>) -> Box<dyn Future<Item=FindPetsByStatusResponse, Error=ApiError>> {
fn find_pets_by_status(&self, status: &Vec<String>) -> Box<dyn Future<Item=FindPetsByStatusResponse, Error=ApiError> + Send> {
self.api().find_pets_by_status(status, &self.context())
}
/// Finds Pets by tags
fn find_pets_by_tags(&self, tags: &Vec<String>) -> Box<dyn Future<Item=FindPetsByTagsResponse, Error=ApiError>> {
fn find_pets_by_tags(&self, tags: &Vec<String>) -> Box<dyn Future<Item=FindPetsByTagsResponse, Error=ApiError> + Send> {
self.api().find_pets_by_tags(tags, &self.context())
}
/// Find pet by ID
fn get_pet_by_id(&self, pet_id: i64) -> Box<dyn Future<Item=GetPetByIdResponse, Error=ApiError>> {
fn get_pet_by_id(&self, pet_id: i64) -> Box<dyn Future<Item=GetPetByIdResponse, Error=ApiError> + Send> {
self.api().get_pet_by_id(pet_id, &self.context())
}
/// Update an existing pet
fn update_pet(&self, body: models::Pet) -> Box<dyn Future<Item=UpdatePetResponse, Error=ApiError>> {
fn update_pet(&self, body: models::Pet) -> Box<dyn Future<Item=UpdatePetResponse, Error=ApiError> + Send> {
self.api().update_pet(body, &self.context())
}
/// Updates a pet in the store with form data
fn update_pet_with_form(&self, pet_id: i64, name: Option<String>, status: Option<String>) -> Box<dyn Future<Item=UpdatePetWithFormResponse, Error=ApiError>> {
fn update_pet_with_form(&self, pet_id: i64, name: Option<String>, status: Option<String>) -> Box<dyn Future<Item=UpdatePetWithFormResponse, Error=ApiError> + Send> {
self.api().update_pet_with_form(pet_id, name, status, &self.context())
}
/// uploads an image
fn upload_file(&self, pet_id: i64, additional_metadata: Option<String>, file: Option<swagger::ByteArray>) -> Box<dyn Future<Item=UploadFileResponse, Error=ApiError>> {
fn upload_file(&self, pet_id: i64, additional_metadata: Option<String>, file: Option<swagger::ByteArray>) -> Box<dyn Future<Item=UploadFileResponse, Error=ApiError> + Send> {
self.api().upload_file(pet_id, additional_metadata, file, &self.context())
}
/// Delete purchase order by ID
fn delete_order(&self, order_id: String) -> Box<dyn Future<Item=DeleteOrderResponse, Error=ApiError>> {
fn delete_order(&self, order_id: String) -> Box<dyn Future<Item=DeleteOrderResponse, Error=ApiError> + Send> {
self.api().delete_order(order_id, &self.context())
}
/// Returns pet inventories by status
fn get_inventory(&self) -> Box<dyn Future<Item=GetInventoryResponse, Error=ApiError>> {
fn get_inventory(&self) -> Box<dyn Future<Item=GetInventoryResponse, Error=ApiError> + Send> {
self.api().get_inventory(&self.context())
}
/// Find purchase order by ID
fn get_order_by_id(&self, order_id: i64) -> Box<dyn Future<Item=GetOrderByIdResponse, Error=ApiError>> {
fn get_order_by_id(&self, order_id: i64) -> Box<dyn Future<Item=GetOrderByIdResponse, Error=ApiError> + Send> {
self.api().get_order_by_id(order_id, &self.context())
}
/// Place an order for a pet
fn place_order(&self, body: models::Order) -> Box<dyn Future<Item=PlaceOrderResponse, Error=ApiError>> {
fn place_order(&self, body: models::Order) -> Box<dyn Future<Item=PlaceOrderResponse, Error=ApiError> + Send> {
self.api().place_order(body, &self.context())
}
/// Create user
fn create_user(&self, body: models::User) -> Box<dyn Future<Item=CreateUserResponse, Error=ApiError>> {
fn create_user(&self, body: models::User) -> Box<dyn Future<Item=CreateUserResponse, Error=ApiError> + Send> {
self.api().create_user(body, &self.context())
}
/// Creates list of users with given input array
fn create_users_with_array_input(&self, body: &Vec<models::User>) -> Box<dyn Future<Item=CreateUsersWithArrayInputResponse, Error=ApiError>> {
fn create_users_with_array_input(&self, body: &Vec<models::User>) -> Box<dyn Future<Item=CreateUsersWithArrayInputResponse, Error=ApiError> + Send> {
self.api().create_users_with_array_input(body, &self.context())
}
/// Creates list of users with given input array
fn create_users_with_list_input(&self, body: &Vec<models::User>) -> Box<dyn Future<Item=CreateUsersWithListInputResponse, Error=ApiError>> {
fn create_users_with_list_input(&self, body: &Vec<models::User>) -> Box<dyn Future<Item=CreateUsersWithListInputResponse, Error=ApiError> + Send> {
self.api().create_users_with_list_input(body, &self.context())
}
/// Delete user
fn delete_user(&self, username: String) -> Box<dyn Future<Item=DeleteUserResponse, Error=ApiError>> {
fn delete_user(&self, username: String) -> Box<dyn Future<Item=DeleteUserResponse, Error=ApiError> + Send> {
self.api().delete_user(username, &self.context())
}
/// Get user by user name
fn get_user_by_name(&self, username: String) -> Box<dyn Future<Item=GetUserByNameResponse, Error=ApiError>> {
fn get_user_by_name(&self, username: String) -> Box<dyn Future<Item=GetUserByNameResponse, Error=ApiError> + Send> {
self.api().get_user_by_name(username, &self.context())
}
/// Logs user into the system
fn login_user(&self, username: String, password: String) -> Box<dyn Future<Item=LoginUserResponse, Error=ApiError>> {
fn login_user(&self, username: String, password: String) -> Box<dyn Future<Item=LoginUserResponse, Error=ApiError> + Send> {
self.api().login_user(username, password, &self.context())
}
/// Logs out current logged in user session
fn logout_user(&self) -> Box<dyn Future<Item=LogoutUserResponse, Error=ApiError>> {
fn logout_user(&self) -> Box<dyn Future<Item=LogoutUserResponse, Error=ApiError> + Send> {
self.api().logout_user(&self.context())
}
/// Updated user
fn update_user(&self, username: String, body: models::User) -> Box<dyn Future<Item=UpdateUserResponse, Error=ApiError>> {
fn update_user(&self, username: String, body: models::User) -> Box<dyn Future<Item=UpdateUserResponse, Error=ApiError> + Send> {
self.api().update_user(username, body, &self.context())
}

View File

@ -1,198 +1,118 @@
/// mime types for requests and responses
pub mod responses {
use hyper::mime::*;
// The macro is called per-operation to beat the recursion limit
lazy_static! {
/// Create Mime objects for the response content types for TestSpecialTags
pub static ref TEST_SPECIAL_TAGS_SUCCESSFUL_OPERATION: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the response content types for TestSpecialTags
pub static TEST_SPECIAL_TAGS_SUCCESSFUL_OPERATION: &str = "application/json";
lazy_static! {
/// Create Mime objects for the response content types for FakeOuterBooleanSerialize
pub static ref FAKE_OUTER_BOOLEAN_SERIALIZE_OUTPUT_BOOLEAN: Mime = "*/*".parse().unwrap();
}
/// Create &str objects for the response content types for FakeOuterBooleanSerialize
pub static FAKE_OUTER_BOOLEAN_SERIALIZE_OUTPUT_BOOLEAN: &str = "*/*";
lazy_static! {
/// Create Mime objects for the response content types for FakeOuterCompositeSerialize
pub static ref FAKE_OUTER_COMPOSITE_SERIALIZE_OUTPUT_COMPOSITE: Mime = "*/*".parse().unwrap();
}
/// Create &str objects for the response content types for FakeOuterCompositeSerialize
pub static FAKE_OUTER_COMPOSITE_SERIALIZE_OUTPUT_COMPOSITE: &str = "*/*";
lazy_static! {
/// Create Mime objects for the response content types for FakeOuterNumberSerialize
pub static ref FAKE_OUTER_NUMBER_SERIALIZE_OUTPUT_NUMBER: Mime = "*/*".parse().unwrap();
}
/// Create &str objects for the response content types for FakeOuterNumberSerialize
pub static FAKE_OUTER_NUMBER_SERIALIZE_OUTPUT_NUMBER: &str = "*/*";
lazy_static! {
/// Create Mime objects for the response content types for FakeOuterStringSerialize
pub static ref FAKE_OUTER_STRING_SERIALIZE_OUTPUT_STRING: Mime = "*/*".parse().unwrap();
}
/// Create &str objects for the response content types for FakeOuterStringSerialize
pub static FAKE_OUTER_STRING_SERIALIZE_OUTPUT_STRING: &str = "*/*";
lazy_static! {
/// Create Mime objects for the response content types for TestClientModel
pub static ref TEST_CLIENT_MODEL_SUCCESSFUL_OPERATION: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the response content types for TestClientModel
pub static TEST_CLIENT_MODEL_SUCCESSFUL_OPERATION: &str = "application/json";
lazy_static! {
/// Create Mime objects for the response content types for TestClassname
pub static ref TEST_CLASSNAME_SUCCESSFUL_OPERATION: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the response content types for TestClassname
pub static TEST_CLASSNAME_SUCCESSFUL_OPERATION: &str = "application/json";
lazy_static! {
/// Create Mime objects for the response content types for FindPetsByStatus
pub static ref FIND_PETS_BY_STATUS_SUCCESSFUL_OPERATION: Mime = "application/xml".parse().unwrap();
}
/// Create &str objects for the response content types for FindPetsByStatus
pub static FIND_PETS_BY_STATUS_SUCCESSFUL_OPERATION: &str = "application/xml";
lazy_static! {
/// Create Mime objects for the response content types for FindPetsByTags
pub static ref FIND_PETS_BY_TAGS_SUCCESSFUL_OPERATION: Mime = "application/xml".parse().unwrap();
}
/// Create &str objects for the response content types for FindPetsByTags
pub static FIND_PETS_BY_TAGS_SUCCESSFUL_OPERATION: &str = "application/xml";
lazy_static! {
/// Create Mime objects for the response content types for GetPetById
pub static ref GET_PET_BY_ID_SUCCESSFUL_OPERATION: Mime = "application/xml".parse().unwrap();
}
/// Create &str objects for the response content types for GetPetById
pub static GET_PET_BY_ID_SUCCESSFUL_OPERATION: &str = "application/xml";
lazy_static! {
/// Create Mime objects for the response content types for UploadFile
pub static ref UPLOAD_FILE_SUCCESSFUL_OPERATION: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the response content types for UploadFile
pub static UPLOAD_FILE_SUCCESSFUL_OPERATION: &str = "application/json";
lazy_static! {
/// Create Mime objects for the response content types for GetInventory
pub static ref GET_INVENTORY_SUCCESSFUL_OPERATION: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the response content types for GetInventory
pub static GET_INVENTORY_SUCCESSFUL_OPERATION: &str = "application/json";
lazy_static! {
/// Create Mime objects for the response content types for GetOrderById
pub static ref GET_ORDER_BY_ID_SUCCESSFUL_OPERATION: Mime = "application/xml".parse().unwrap();
}
/// Create &str objects for the response content types for GetOrderById
pub static GET_ORDER_BY_ID_SUCCESSFUL_OPERATION: &str = "application/xml";
lazy_static! {
/// Create Mime objects for the response content types for PlaceOrder
pub static ref PLACE_ORDER_SUCCESSFUL_OPERATION: Mime = "application/xml".parse().unwrap();
}
/// Create &str objects for the response content types for PlaceOrder
pub static PLACE_ORDER_SUCCESSFUL_OPERATION: &str = "application/xml";
lazy_static! {
/// Create Mime objects for the response content types for GetUserByName
pub static ref GET_USER_BY_NAME_SUCCESSFUL_OPERATION: Mime = "application/xml".parse().unwrap();
}
/// Create &str objects for the response content types for GetUserByName
pub static GET_USER_BY_NAME_SUCCESSFUL_OPERATION: &str = "application/xml";
lazy_static! {
/// Create Mime objects for the response content types for LoginUser
pub static ref LOGIN_USER_SUCCESSFUL_OPERATION: Mime = "application/xml".parse().unwrap();
}
/// Create &str objects for the response content types for LoginUser
pub static LOGIN_USER_SUCCESSFUL_OPERATION: &str = "application/xml";
}
pub mod requests {
use hyper::mime::*;
lazy_static! {
/// Create Mime objects for the request content types for TestSpecialTags
pub static ref TEST_SPECIAL_TAGS: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the request content types for TestSpecialTags
pub static TEST_SPECIAL_TAGS: &str = "application/json";
lazy_static! {
/// Create Mime objects for the request content types for FakeOuterBooleanSerialize
pub static ref FAKE_OUTER_BOOLEAN_SERIALIZE: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the request content types for FakeOuterBooleanSerialize
pub static FAKE_OUTER_BOOLEAN_SERIALIZE: &str = "application/json";
lazy_static! {
/// Create Mime objects for the request content types for FakeOuterCompositeSerialize
pub static ref FAKE_OUTER_COMPOSITE_SERIALIZE: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the request content types for FakeOuterCompositeSerialize
pub static FAKE_OUTER_COMPOSITE_SERIALIZE: &str = "application/json";
lazy_static! {
/// Create Mime objects for the request content types for FakeOuterNumberSerialize
pub static ref FAKE_OUTER_NUMBER_SERIALIZE: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the request content types for FakeOuterNumberSerialize
pub static FAKE_OUTER_NUMBER_SERIALIZE: &str = "application/json";
lazy_static! {
/// Create Mime objects for the request content types for FakeOuterStringSerialize
pub static ref FAKE_OUTER_STRING_SERIALIZE: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the request content types for FakeOuterStringSerialize
pub static FAKE_OUTER_STRING_SERIALIZE: &str = "application/json";
lazy_static! {
/// Create Mime objects for the request content types for TestBodyWithQueryParams
pub static ref TEST_BODY_WITH_QUERY_PARAMS: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the request content types for TestBodyWithQueryParams
pub static TEST_BODY_WITH_QUERY_PARAMS: &str = "application/json";
lazy_static! {
/// Create Mime objects for the request content types for TestClientModel
pub static ref TEST_CLIENT_MODEL: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the request content types for TestClientModel
pub static TEST_CLIENT_MODEL: &str = "application/json";
lazy_static! {
/// Create Mime objects for the request content types for TestEndpointParameters
pub static ref TEST_ENDPOINT_PARAMETERS: Mime = "application/x-www-form-urlencoded".parse().unwrap();
}
/// Create &str objects for the request content types for TestEndpointParameters
pub static TEST_ENDPOINT_PARAMETERS: &str = "application/x-www-form-urlencoded";
lazy_static! {
/// Create Mime objects for the request content types for TestEnumParameters
pub static ref TEST_ENUM_PARAMETERS: Mime = "application/x-www-form-urlencoded".parse().unwrap();
}
/// Create &str objects for the request content types for TestEnumParameters
pub static TEST_ENUM_PARAMETERS: &str = "application/x-www-form-urlencoded";
lazy_static! {
/// Create Mime objects for the request content types for TestInlineAdditionalProperties
pub static ref TEST_INLINE_ADDITIONAL_PROPERTIES: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the request content types for TestInlineAdditionalProperties
pub static TEST_INLINE_ADDITIONAL_PROPERTIES: &str = "application/json";
lazy_static! {
/// Create Mime objects for the request content types for TestJsonFormData
pub static ref TEST_JSON_FORM_DATA: Mime = "application/x-www-form-urlencoded".parse().unwrap();
}
/// Create &str objects for the request content types for TestJsonFormData
pub static TEST_JSON_FORM_DATA: &str = "application/x-www-form-urlencoded";
lazy_static! {
/// Create Mime objects for the request content types for TestClassname
pub static ref TEST_CLASSNAME: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the request content types for TestClassname
pub static TEST_CLASSNAME: &str = "application/json";
lazy_static! {
/// Create Mime objects for the request content types for AddPet
pub static ref ADD_PET: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the request content types for AddPet
pub static ADD_PET: &str = "application/json";
lazy_static! {
/// Create Mime objects for the request content types for UpdatePet
pub static ref UPDATE_PET: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the request content types for UpdatePet
pub static UPDATE_PET: &str = "application/json";
lazy_static! {
/// Create Mime objects for the request content types for UpdatePetWithForm
pub static ref UPDATE_PET_WITH_FORM: Mime = "application/x-www-form-urlencoded".parse().unwrap();
}
/// Create &str objects for the request content types for UpdatePetWithForm
pub static UPDATE_PET_WITH_FORM: &str = "application/x-www-form-urlencoded";
lazy_static! {
/// Create Mime objects for the request content types for UploadFile
pub static ref UPLOAD_FILE: Mime = "multipart/form-data".parse().unwrap();
}
/// Create &str objects for the request content types for PlaceOrder
pub static PLACE_ORDER: &str = "application/json";
lazy_static! {
/// Create Mime objects for the request content types for PlaceOrder
pub static ref PLACE_ORDER: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the request content types for CreateUser
pub static CREATE_USER: &str = "application/json";
lazy_static! {
/// Create Mime objects for the request content types for CreateUser
pub static ref CREATE_USER: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the request content types for CreateUsersWithArrayInput
pub static CREATE_USERS_WITH_ARRAY_INPUT: &str = "application/json";
lazy_static! {
/// Create Mime objects for the request content types for CreateUsersWithArrayInput
pub static ref CREATE_USERS_WITH_ARRAY_INPUT: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the request content types for CreateUsersWithListInput
pub static CREATE_USERS_WITH_LIST_INPUT: &str = "application/json";
lazy_static! {
/// Create Mime objects for the request content types for CreateUsersWithListInput
pub static ref CREATE_USERS_WITH_LIST_INPUT: Mime = "application/json".parse().unwrap();
}
lazy_static! {
/// Create Mime objects for the request content types for UpdateUser
pub static ref UPDATE_USER: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the request content types for UpdateUser
pub static UPDATE_USER: &str = "application/json";
}

View File

@ -1,5 +1,4 @@
#![allow(unused_imports, unused_qualifications, unused_extern_crates)]
extern crate chrono;
#![allow(unused_imports, unused_qualifications)]
use serde_xml_rs;
use serde::ser::Serializer;

View File

@ -1,64 +1,86 @@
use futures::Future;
use hyper;
use hyper::header::HeaderName;
use hyper::{Error, Request, Response, StatusCode, service::Service, body::Payload};
use url::form_urlencoded;
use std::default::Default;
use std::io;
use std::marker::PhantomData;
use 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 swagger::auth::{AuthData, Authorization, Bearer, Scopes};
use swagger::context::ContextualPayload;
use swagger::{EmptyContext, Has, Pop, Push, XSpanIdString};
use Api;
pub struct NewAddContext<T, A>
{
pub struct MakeAddContext<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,
impl<T, A, B, C, D> MakeAddContext<T, A>
where
A: Default + Push<XSpanIdString, Result = B>,
B: Push<Option<AuthData>, Result = C>,
C: Push<Option<Authorization>, Result = D>,
{
pub fn new(inner: T) -> NewAddContext<T, A> {
NewAddContext {
pub fn new(inner: T) -> MakeAddContext<T, A> {
MakeAddContext {
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,
// Make a service that adds context.
impl<'a, T, SC, A, B, C, D, E, ME, S, OB, F> hyper::service::MakeService<&'a SC> for
MakeAddContext<T, A>
where
A: Default + Push<XSpanIdString, Result = B>,
B: Push<Option<AuthData>, Result = C>,
C: Push<Option<Authorization>, Result = D>,
D: Send + 'static,
T: hyper::service::MakeService<
&'a SC,
Error = E,
MakeError = ME,
Service = S,
ReqBody = ContextualPayload<hyper::Body, D>,
ResBody = OB,
Future = F
>,
S: Service<
Error = E,
ReqBody = ContextualPayload<hyper::Body, D>,
ResBody = OB> + 'static,
ME: swagger::ErrorBound,
E: swagger::ErrorBound,
F: Future<Item=S, Error=ME> + Send + 'static,
S::Future: Send,
OB: Payload,
{
type Request = Request;
type Response = Response;
type Error = Error;
type Instance = AddContext<T::Instance, A>;
type ReqBody = hyper::Body;
type ResBody = OB;
type Error = E;
type MakeError = ME;
type Service = AddContext<S, A>;
type Future = Box<dyn Future<Item = Self::Service, Error = ME> + Send + 'static>;
fn new_service(&self) -> Result<Self::Instance, io::Error> {
self.inner.new_service().map(|s| AddContext::new(s))
fn make_service(&mut self, ctx: &'a SC) -> Self::Future {
Box::new(self.inner.make_service(ctx).map(|s| AddContext::new(s)))
}
}
/// Middleware to extract authentication data from request
pub struct AddContext<T, A>
{
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>,
where
A: Default + Push<XSpanIdString, Result = B>,
B: Push<Option<AuthData>, Result = C>,
C: Push<Option<Authorization>, Result = D>,
T: Service,
{
pub fn new(inner: T) -> AddContext<T, A> {
AddContext {
@ -68,32 +90,43 @@ impl<T, A, B, C, D> AddContext<T, A>
}
}
impl<T, A, B, C, D> hyper::server::Service for AddContext<T, A>
impl<T, A, B, C, D> Service for AddContext<T, A>
where
A: Default + Push<XSpanIdString, Result=B>,
B: Push<Option<AuthData>, Result=C>,
C: Push<Option<Authorization>, Result=D>,
T: hyper::server::Service<Request = (Request, D), Response = Response, Error = Error>,
D: Send + 'static,
T: Service<ReqBody = ContextualPayload<hyper::Body, D>>,
T::Future: Future<Item=Response<T::ResBody>, Error=T::Error> + Send + 'static
{
type Request = Request;
type Response = Response;
type Error = Error;
type Future = T::Future;
type ReqBody = hyper::Body;
type ResBody = T::ResBody;
type Error = T::Error;
type Future = Box<dyn Future<Item=Response<T::ResBody>, Error=T::Error> + Send + 'static>;
fn call(&self, req: Self::Request) -> Self::Future {
fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future {
let context = A::default().push(XSpanIdString::get_or_generate(&req));
let (head, body) = req.into_parts();
let headers = head.headers.clone();
{
header! { (ApiKey1, "api_key") => [String] }
if let Some(header) = req.headers().get::<ApiKey1>().cloned() {
let auth_data = AuthData::ApiKey(header.0);
use swagger::auth::api_key_from_header;
if let Some(header) = api_key_from_header(&headers, "api_key") {
let auth_data = AuthData::ApiKey(header);
let context = context.push(Some(auth_data));
let context = context.push(None::<Authorization>);
return self.inner.call((req, context));
let body = ContextualPayload {
inner: body,
context: context,
};
return Box::new(self.inner.call(hyper::Request::from_parts(head, body)));
}
}
{
let key = form_urlencoded::parse(req.query().unwrap_or_default().as_bytes())
let key = form_urlencoded::parse(head.uri.query().unwrap_or_default().as_bytes())
.filter(|e| e.0 == "api_key_query")
.map(|e| e.1.clone().into_owned())
.nth(0);
@ -101,32 +134,54 @@ impl<T, A, B, C, D> hyper::server::Service for AddContext<T, A>
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));
let body = ContextualPayload {
inner: body,
context: context,
};
return Box::new(self.inner.call(hyper::Request::from_parts(head, body)));
}
}
{
use hyper::header::{Authorization as HyperAuth, Basic, Bearer};
use swagger::auth::Basic;
use std::ops::Deref;
if let Some(basic) = req.headers().get::<HyperAuth<Basic>>().cloned() {
let auth_data = AuthData::Basic(basic.deref().clone());
if let Some(basic) = swagger::auth::from_headers::<Basic>(&headers) {
let auth_data = AuthData::Basic(basic);
let context = context.push(Some(auth_data));
let context = context.push(None::<Authorization>);
return self.inner.call((req, context));
let body = ContextualPayload {
inner: body,
context: context,
};
return Box::new(self.inner.call(hyper::Request::from_parts(head, body)));
}
}
{
use hyper::header::{Authorization as HyperAuth, Basic, Bearer};
use swagger::auth::Bearer;
use std::ops::Deref;
if let Some(bearer) = req.headers().get::<HyperAuth<Bearer>>().cloned() {
let auth_data = AuthData::Bearer(bearer.deref().clone());
if let Some(bearer) = swagger::auth::from_headers::<Bearer>(&headers) {
let auth_data = AuthData::Bearer(bearer);
let context = context.push(Some(auth_data));
let context = context.push(None::<Authorization>);
return self.inner.call((req, context));
let body = ContextualPayload {
inner: body,
context: context,
};
return Box::new(self.inner.call(hyper::Request::from_parts(head, body)));
}
}
let context = context.push(None::<AuthData>);
let context = context.push(None::<Authorization>);
return self.inner.call((req, context));
let body = ContextualPayload {
inner: body,
context: context,
};
Box::new(self.inner.call(hyper::Request::from_parts(head, body)))
}
}

View File

@ -7,44 +7,46 @@ license = "Unlicense"
[features]
default = ["client", "server"]
client = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url"]
server = ["serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url"]
client = [
"serde_json", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio", "url"
]
server = [
"serde_json", "serde_ignored", "hyper", "native-tls", "openssl", "tokio", "tokio-tls", "regex", "percent-encoding", "url", "lazy_static"
]
conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"]
[dependencies]
# Common
chrono = { version = "0.4", features = ["serde"] }
futures = "0.1"
swagger = "2"
lazy_static = "1.4"
swagger = "3.0"
log = "0.3.0"
mime = "0.2.6"
multipart = "0.13.3"
mime = "0.3"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
# Crates included if required by the API definition
# Common between server and client features
hyper = {version = "0.11", optional = true}
hyper-tls = {version = "0.1.2", optional = true}
hyper = {version = "0.12", optional = true}
hyper-tls = {version = "0.2.1", optional = true}
native-tls = {version = "0.1.4", optional = true}
openssl = {version = "0.9.14", optional = true}
serde_json = {version = "1.0", optional = true}
serde_ignored = {version = "0.0.4", optional = true}
tokio-core = {version = "0.1.6", optional = true}
tokio = {version = "0.1.17", optional = true}
url = {version = "1.5", optional = true}
# Client-specific
# Server-specific
lazy_static = { version = "1.4", optional = true }
percent-encoding = {version = "1.0.0", optional = true}
regex = {version = "0.2", optional = true}
tokio-proto = {version = "0.1.1", optional = true}
tokio-tls = {version = "0.1.3", optional = true, features = ["tokio-proto"]}
tokio-tls = {version = "0.1.3", optional = true}
# Other optional crates
# Conversion
frunk = { version = "0.3.0", optional = true }
frunk_derives = { version = "0.3.0", optional = true }
frunk_core = { version = "0.3.0", optional = true }

View File

@ -1,23 +1,18 @@
#![allow(missing_docs, unused_variables, trivial_casts)]
extern crate rust_server_test;
#[allow(unused_extern_crates)]
extern crate futures;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate swagger;
#[allow(unused_extern_crates)]
extern crate clap;
extern crate tokio_core;
extern crate uuid;
extern crate tokio;
use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData};
#[allow(unused_imports)]
use futures::{Future, future, Stream, stream};
use tokio_core::reactor;
#[allow(unused_imports)]
use rust_server_test::{ApiNoContext, ContextWrapperExt,
use rust_server_test::{Api, ApiNoContext, Client, ContextWrapperExt,
ApiError,
DummyGetResponse,
DummyPutResponse,
@ -32,11 +27,16 @@ fn main() {
.arg(Arg::with_name("operation")
.help("Sets the operation to run")
.possible_values(&[
"DummyGet",
"FileResponseGet",
"HtmlPost",
"RawJsonGet",
])
"DummyGet",
"FileResponseGet",
"HtmlPost",
"RawJsonGet",
])
.required(true)
.index(1))
.arg(Arg::with_name("https")
@ -54,57 +54,73 @@ fn main() {
.help("Port to contact"))
.get_matches();
let mut core = reactor::Core::new().unwrap();
let is_https = matches.is_present("https");
let base_url = format!("{}://{}:{}",
if is_https { "https" } else { "http" },
matches.value_of("host").unwrap(),
matches.value_of("port").unwrap());
let client = if matches.is_present("https") {
// Using Simple HTTPS
rust_server_test::Client::try_new_https(core.handle(), &base_url, "examples/ca.pem")
Client::try_new_https(
&base_url,
"examples/ca.pem")
.expect("Failed to create HTTPS client")
} else {
// Using HTTP
rust_server_test::Client::try_new_http(core.handle(), &base_url)
Client::try_new_http(
&base_url)
.expect("Failed to create HTTP client")
};
let context: make_context_ty!(ContextBuilder, EmptyContext, Option<AuthData>, XSpanIdString) =
make_context!(ContextBuilder, EmptyContext, None as Option<AuthData>, XSpanIdString(self::uuid::Uuid::new_v4().to_string()));
make_context!(ContextBuilder, EmptyContext, None as Option<AuthData>, XSpanIdString::default());
let client = client.with_context(context);
match matches.value_of("operation") {
Some("DummyGet") => {
let result = core.run(client.dummy_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.dummy_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
// Disabled because there's no example.
// Some("DummyPut") => {
// let result = core.run(client.dummy_put(???));
// println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
// },
/* Disabled because there's no example.
Some("DummyPut") => {
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.dummy_put(
???
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
*/
Some("FileResponseGet") => {
let result = core.run(client.file_response_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.file_response_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("HtmlPost") => {
let result = core.run(client.html_post("body_example".to_string()));
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.html_post(
"body_example".to_string()
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
Some("RawJsonGet") => {
let result = core.run(client.raw_json_get());
let mut rt = tokio::runtime::Runtime::new().unwrap();
let result = rt.block_on(client.raw_json_get(
));
println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &dyn Has<XSpanIdString>).get().clone());
},
},
_ => {
panic!("Invalid operation provided")
}
}
}

View File

@ -8,9 +8,9 @@ extern crate rust_server_test;
extern crate swagger;
extern crate hyper;
extern crate openssl;
extern crate native_tls;
extern crate tokio_proto;
extern crate tokio;
extern crate tokio_tls;
extern crate native_tls;
extern crate clap;
// Imports required by server library.
@ -21,14 +21,18 @@ extern crate chrono;
#[macro_use]
extern crate error_chain;
use futures::{Future, Stream};
use hyper::service::MakeService;
use hyper::server::conn::Http;
use openssl::x509::X509_FILETYPE_PEM;
use openssl::ssl::{SslAcceptorBuilder, SslMethod};
use openssl::error::ErrorStack;
use hyper::server::Http;
use tokio_proto::TcpServer;
use tokio::net::TcpListener;
use clap::{App, Arg};
use swagger::auth::AllowAllAuthenticator;
use std::sync::{Arc, Mutex};
use swagger::auth::MakeAllowAllAuthenticator;
use swagger::EmptyContext;
use tokio_tls::TlsAcceptorExt;
mod server_lib;
@ -53,12 +57,15 @@ fn main() {
.help("Whether to use HTTPS or not"))
.get_matches();
let server = server_lib::Server::new();
let service_fn = rust_server_test::server::MakeService::new(server);
let service_fn = MakeAllowAllAuthenticator::new(service_fn, "cosmo");
let service_fn =
rust_server_test::server::context::NewAddContext::<_, EmptyContext>::new(
AllowAllAuthenticator::new(
server_lib::NewService::new(),
"cosmo"
)
rust_server_test::server::context::MakeAddContext::<_, EmptyContext>::new(
service_fn
);
let addr = "127.0.0.1:80".parse().expect("Failed to parse bind address");
@ -66,9 +73,29 @@ fn main() {
let ssl = ssl().expect("Failed to load SSL keys");
let builder: native_tls::TlsAcceptorBuilder = native_tls::backend::openssl::TlsAcceptorBuilderExt::from_openssl(ssl);
let tls_acceptor = builder.build().expect("Failed to build TLS acceptor");
TcpServer::new(tokio_tls::proto::Server::new(Http::new(), tls_acceptor), addr).serve(service_fn);
let service_fn = Arc::new(Mutex::new(service_fn));
let tls_listener = TcpListener::bind(&addr).unwrap().incoming().for_each(move |tcp| {
let addr = tcp.peer_addr().expect("Unable to get remote address");
let service_fn = service_fn.clone();
hyper::rt::spawn(tls_acceptor.accept_async(tcp).map_err(|_| ()).and_then(move |tls| {
let ms = {
let mut service_fn = service_fn.lock().unwrap();
service_fn.make_service(&addr)
};
ms.and_then(move |service| {
Http::new().serve_connection(tls, service)
}).map_err(|_| ())
}));
Ok(())
}).map_err(|_| ());
hyper::rt::run(tls_listener);
} else {
// Using HTTP
TcpServer::new(Http::new(), addr).serve(service_fn);
hyper::rt::run(hyper::server::Server::bind(&addr).serve(service_fn).map_err(|e| panic!("{:?}", e)));
}
}

View File

@ -1,37 +1,76 @@
//! Main library entry point for rust_server_test implementation.
mod server;
#![allow(unused_imports)]
mod errors {
error_chain!{}
}
pub use self::errors::*;
use std::io;
use std::clone::Clone;
use futures::{self, Future};
use chrono;
use std::collections::HashMap;
use std::marker::PhantomData;
use hyper;
use rust_server_test;
use swagger;
use swagger::{Has, XSpanIdString};
pub struct NewService<C>{
marker: PhantomData<C>
use rust_server_test::{Api, ApiError,
DummyGetResponse,
DummyPutResponse,
FileResponseGetResponse,
HtmlPostResponse,
RawJsonGetResponse
};
use rust_server_test::models;
#[derive(Copy, Clone)]
pub struct Server<C> {
marker: PhantomData<C>,
}
impl<C> NewService<C>{
impl<C> Server<C> {
pub fn new() -> Self {
NewService{marker:PhantomData}
Server{marker: PhantomData}
}
}
impl<C> hyper::server::NewService for NewService<C> where C: Has<XSpanIdString> + Clone + 'static {
type Request = (hyper::Request, C);
type Response = hyper::Response;
type Error = hyper::Error;
type Instance = rust_server_test::server::Service<server::Server<C>, C>;
impl<C> Api<C> for Server<C> where C: Has<XSpanIdString>{
/// Instantiate a new server.
fn new_service(&self) -> io::Result<Self::Instance> {
Ok(rust_server_test::server::Service::new(server::Server::new()))
/// A dummy endpoint to make the spec valid.
fn dummy_get(&self, context: &C) -> Box<Future<Item=DummyGetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("dummy_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
fn dummy_put(&self, nested_response: models::InlineObject, context: &C) -> Box<Future<Item=DummyPutResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("dummy_put({:?}) - X-Span-ID: {:?}", nested_response, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// Get a file
fn file_response_get(&self, context: &C) -> Box<Future<Item=FileResponseGetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("file_response_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// Test HTML handling
fn html_post(&self, body: String, context: &C) -> Box<Future<Item=HtmlPostResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("html_post(\"{}\") - X-Span-ID: {:?}", body, context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
/// Get an arbitrary JSON blob.
fn raw_json_get(&self, context: &C) -> Box<Future<Item=RawJsonGetResponse, Error=ApiError> + Send> {
let context = context.clone();
println!("raw_json_get() - X-Span-ID: {:?}", context.get().0.clone());
Box::new(futures::failed("Generic failure".into()))
}
}

View File

@ -1,21 +1,18 @@
#![allow(unused_extern_crates)]
extern crate tokio_core;
extern crate native_tls;
extern crate hyper_tls;
extern crate openssl;
extern crate mime;
extern crate chrono;
extern crate url;
use hyper;
use hyper::header::{Headers, ContentType};
use hyper::Uri;
use self::url::percent_encoding::{utf8_percent_encode, PATH_SEGMENT_ENCODE_SET, QUERY_ENCODE_SET};
use hyper::client::HttpConnector;
use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE};
use hyper::{Body, Uri, Response};
use hyper_tls::HttpsConnector;
use url::form_urlencoded;
use url::percent_encoding::{utf8_percent_encode, PATH_SEGMENT_ENCODE_SET, QUERY_ENCODE_SET};
use futures;
use futures::{Future, Stream};
use futures::{future, stream};
use self::tokio_core::reactor::Handle;
use serde_json;
use std::borrow::Cow;
#[allow(unused_imports)]
use std::collections::{HashMap, BTreeMap};
use std::io::{Read, Error, ErrorKind};
use std::error;
use std::fmt;
@ -24,15 +21,10 @@ use std::sync::Arc;
use std::str;
use std::str::FromStr;
use std::string::ToString;
use mimetypes;
use serde_json;
#[allow(unused_imports)]
use std::collections::{HashMap, BTreeMap};
#[allow(unused_imports)]
use swagger;
use swagger::{ApiError, XSpanIdString, Has, AuthData};
use swagger::client::Service;
use swagger::{ApiError, XSpanId, XSpanIdString, Has, AuthData};
use {Api,
DummyGetResponse,
@ -41,6 +33,8 @@ use {Api,
HtmlPostResponse,
RawJsonGetResponse
};
use mimetypes;
use models;
define_encode_set! {
@ -56,7 +50,7 @@ fn into_base_path(input: &str, correct_scheme: Option<&'static str>) -> Result<S
// First convert to Uri, since a base path is a subset of Uri.
let uri = Uri::from_str(input)?;
let scheme = uri.scheme().ok_or(ClientInitError::InvalidScheme)?;
let scheme = uri.scheme_part().ok_or(ClientInitError::InvalidScheme)?;
// Check the scheme if necessary
if let Some(correct_scheme) = correct_scheme {
@ -66,104 +60,36 @@ fn into_base_path(input: &str, correct_scheme: Option<&'static str>) -> Result<S
}
let host = uri.host().ok_or_else(|| ClientInitError::MissingHost)?;
let port = uri.port().map(|x| format!(":{}", x)).unwrap_or_default();
let port = uri.port_part().map(|x| format!(":{}", x)).unwrap_or_default();
Ok(format!("{}://{}{}", scheme, host, port))
}
/// A client that implements the API by making HTTP calls out to a server.
pub struct Client<F> where
F: Future<Item=hyper::Response, Error=hyper::Error> + 'static {
client_service: Arc<Box<dyn hyper::client::Service<Request=hyper::Request<hyper::Body>, Response=hyper::Response, Error=hyper::Error, Future=F>>>,
pub struct Client<F>
{
client_service: Arc<Box<dyn Service<ReqBody=Body, Future=F> + Send + Sync>>,
base_path: String,
}
impl<F> fmt::Debug for Client<F> where
F: Future<Item=hyper::Response, Error=hyper::Error> + 'static {
impl<F> fmt::Debug for Client<F>
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Client {{ base_path: {} }}", self.base_path)
}
}
impl<F> Clone for Client<F> where
F: Future<Item=hyper::Response, Error=hyper::Error> + 'static {
impl<F> Clone for Client<F>
{
fn clone(&self) -> Self {
Client {
client_service: self.client_service.clone(),
base_path: self.base_path.clone()
base_path: self.base_path.clone(),
}
}
}
impl Client<hyper::client::FutureResponse> {
/// Create an HTTP client.
///
/// # Arguments
/// * `handle` - tokio reactor handle to use for execution
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
pub fn try_new_http(handle: Handle, base_path: &str) -> Result<Client<hyper::client::FutureResponse>, ClientInitError> {
let http_connector = swagger::http_connector();
Self::try_new_with_connector::<hyper::client::HttpConnector>(
handle,
base_path,
Some("http"),
http_connector,
)
}
/// Create a client with a TLS connection to the server.
///
/// # Arguments
/// * `handle` - tokio reactor handle to use for execution
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
/// * `ca_certificate` - Path to CA certificate used to authenticate the server
pub fn try_new_https<CA>(
handle: Handle,
base_path: &str,
ca_certificate: CA,
) -> Result<Client<hyper::client::FutureResponse>, ClientInitError>
where
CA: AsRef<Path>,
{
let https_connector = swagger::https_connector(ca_certificate);
Self::try_new_with_connector::<hyper_tls::HttpsConnector<hyper::client::HttpConnector>>(
handle,
base_path,
Some("https"),
https_connector,
)
}
/// Create a client with a mutually authenticated TLS connection to the server.
///
/// # Arguments
/// * `handle` - tokio reactor handle to use for execution
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
/// * `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
pub fn try_new_https_mutual<CA, K, C>(
handle: Handle,
base_path: &str,
ca_certificate: CA,
client_key: K,
client_certificate: C,
) -> Result<Client<hyper::client::FutureResponse>, ClientInitError>
where
CA: AsRef<Path>,
K: AsRef<Path>,
C: AsRef<Path>,
{
let https_connector =
swagger::https_mutual_connector(ca_certificate, client_key, client_certificate);
Self::try_new_with_connector::<hyper_tls::HttpsConnector<hyper::client::HttpConnector>>(
handle,
base_path,
Some("https"),
https_connector,
)
}
impl Client<hyper::client::ResponseFuture>
{
/// Create a client with a custom implementation of hyper::client::Connect.
///
/// Intended for use with custom implementations of connect for e.g. protocol logging
@ -176,23 +102,21 @@ impl Client<hyper::client::FutureResponse> {
///
/// # Arguments
///
/// * `handle` - tokio reactor handle to use for execution
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
/// * `protocol` - Which protocol to use when constructing the request url, e.g. `Some("http")`
/// * `connector_fn` - Function which returns an implementation of `hyper::client::Connect`
pub fn try_new_with_connector<C>(
handle: Handle,
base_path: &str,
protocol: Option<&'static str>,
connector_fn: Box<dyn Fn(&Handle) -> C + Send + Sync>,
) -> Result<Client<hyper::client::FutureResponse>, ClientInitError>
where
C: hyper::client::Connect + hyper::client::Service,
connector_fn: Box<dyn Fn() -> C + Send + Sync>,
) -> Result<Self, ClientInitError> where
C: hyper::client::connect::Connect + 'static,
C::Transport: 'static,
C::Future: 'static,
{
let connector = connector_fn(&handle);
let client_service = Box::new(hyper::Client::configure().connector(connector).build(
&handle,
));
let connector = connector_fn();
let client_service = Box::new(hyper::client::Client::builder().build(connector));
Ok(Client {
client_service: Arc::new(client_service),
@ -200,40 +124,67 @@ impl Client<hyper::client::FutureResponse> {
})
}
/// Constructor for creating a `Client` by passing in a pre-made `hyper` client.
/// Create an HTTP client.
///
/// One should avoid relying on this function if possible, since it adds a dependency on the underlying transport
/// implementation, which it would be better to abstract away. Therefore, using this function may lead to a loss of
/// code generality, which may make it harder to move the application to a serverless environment, for example.
/// # Arguments
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
pub fn try_new_http(
base_path: &str,
) -> Result<Self, ClientInitError> {
let http_connector = swagger::http_connector();
Self::try_new_with_connector(base_path, Some("http"), http_connector)
}
/// Create a client with a TLS connection to the server.
///
/// The reason for this function's existence is to support legacy test code, which did mocking at the hyper layer.
/// This is not a recommended way to write new tests. If other reasons are found for using this function, they
/// should be mentioned here.
#[deprecated(note="Use try_new_with_client_service instead")]
pub fn try_new_with_hyper_client(
hyper_client: Arc<Box<dyn hyper::client::Service<Request=hyper::Request<hyper::Body>, Response=hyper::Response, Error=hyper::Error, Future=hyper::client::FutureResponse>>>,
handle: Handle,
base_path: &str
) -> Result<Client<hyper::client::FutureResponse>, ClientInitError>
/// # Arguments
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
/// * `ca_certificate` - Path to CA certificate used to authenticate the server
pub fn try_new_https<CA>(
base_path: &str,
ca_certificate: CA,
) -> Result<Self, ClientInitError>
where
CA: AsRef<Path>,
{
Ok(Client {
client_service: hyper_client,
base_path: into_base_path(base_path, None)?,
})
let https_connector = swagger::https_connector(ca_certificate);
Self::try_new_with_connector(base_path, Some("https"), https_connector)
}
/// Create a client with a mutually authenticated TLS connection to the server.
///
/// # Arguments
/// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com"
/// * `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
pub fn try_new_https_mutual<CA, K, D>(
base_path: &str,
ca_certificate: CA,
client_key: K,
client_certificate: D,
) -> Result<Self, ClientInitError>
where
CA: AsRef<Path>,
K: AsRef<Path>,
D: AsRef<Path>,
{
let https_connector =
swagger::https_mutual_connector(ca_certificate, client_key, client_certificate);
Self::try_new_with_connector(base_path, Some("https"), https_connector)
}
}
impl<F> Client<F> where
F: Future<Item=hyper::Response, Error=hyper::Error> + 'static
impl<F> Client<F>
{
/// Constructor for creating a `Client` by passing in a pre-made `hyper` client Service.
/// Constructor for creating a `Client` by passing in a pre-made `swagger::client::Service`
///
/// This allows adding custom wrappers around the underlying transport, for example for logging.
pub fn try_new_with_client_service(client_service: Arc<Box<dyn hyper::client::Service<Request=hyper::Request<hyper::Body>, Response=hyper::Response, Error=hyper::Error, Future=F>>>,
handle: Handle,
base_path: &str)
-> Result<Client<F>, ClientInitError>
{
pub fn try_new_with_client_service(
client_service: Arc<Box<dyn Service<ReqBody=Body, Future=F> + Send + Sync>>,
base_path: &str,
) -> Result<Self, ClientInitError> {
Ok(Client {
client_service: client_service,
base_path: into_base_path(base_path, None)?,
@ -241,19 +192,19 @@ impl<F> Client<F> where
}
}
impl<F, C> Api<C> for Client<F> where
F: Future<Item=hyper::Response, Error=hyper::Error> + 'static,
C: Has<XSpanIdString> {
impl<C, F> Api<C> for Client<F> where
C: Has<XSpanIdString> ,
F: Future<Item=Response<Body>, Error=hyper::Error> + Send + 'static
{
fn dummy_get(&self, context: &C) -> Box<dyn Future<Item=DummyGetResponse, Error=ApiError>> {
fn dummy_get(&self, context: &C) -> Box<dyn Future<Item=DummyGetResponse, Error=ApiError> + Send> {
let mut uri = format!(
"{}/dummy",
self.base_path
);
let mut query_string = self::url::form_urlencoded::Serializer::new("".to_owned());
// Query parameters
let mut query_string = url::form_urlencoded::Serializer::new("".to_owned());
let query_string_str = query_string.finish();
if !query_string_str.is_empty() {
uri += "?";
@ -262,29 +213,40 @@ impl<F, C> Api<C> for Client<F> where
let uri = match Uri::from_str(&uri) {
Ok(uri) => uri,
Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to build URI: {}", err))))),
Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))),
};
let mut request = hyper::Request::new(hyper::Method::Get, uri);
let mut request = match hyper::Request::builder()
.method("GET")
.uri(uri)
.body(Body::empty()) {
Ok(req) => req,
Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e))))
};
request.headers_mut().set(XSpanId((context as &dyn Has<XSpanIdString>).get().0.clone()));
Box::new(self.client_service.call(request)
let header = HeaderValue::from_str((context as &dyn Has<XSpanIdString>).get().0.clone().to_string().as_str());
request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header {
Ok(h) => h,
Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e))))
});
Box::new(self.client_service.request(request)
.map_err(|e| ApiError(format!("No response received: {}", e)))
.and_then(|mut response| {
match response.status().as_u16() {
200 => {
let body = response.body();
let body = response.into_body();
Box::new(
future::ok(
DummyGetResponse::Success
)
) as Box<dyn Future<Item=_, Error=_>>
) as Box<dyn Future<Item=_, Error=_> + Send>
},
code => {
let headers = response.headers().clone();
Box::new(response.body()
Box::new(response.into_body()
.take(100)
.concat2()
.then(move |body|
@ -299,22 +261,21 @@ impl<F, C> Api<C> for Client<F> where
Err(e) => Cow::from(format!("<Failed to read body: {}>", e)),
})))
)
) as Box<dyn Future<Item=_, Error=_>>
) as Box<dyn Future<Item=_, Error=_> + Send>
}
}
}))
}
fn dummy_put(&self, param_nested_response: models::InlineObject, context: &C) -> Box<dyn Future<Item=DummyPutResponse, Error=ApiError>> {
fn dummy_put(&self, param_nested_response: models::InlineObject, context: &C) -> Box<dyn Future<Item=DummyPutResponse, Error=ApiError> + Send> {
let mut uri = format!(
"{}/dummy",
self.base_path
);
let mut query_string = self::url::form_urlencoded::Serializer::new("".to_owned());
// Query parameters
let mut query_string = url::form_urlencoded::Serializer::new("".to_owned());
let query_string_str = query_string.finish();
if !query_string_str.is_empty() {
uri += "?";
@ -323,33 +284,48 @@ impl<F, C> Api<C> for Client<F> where
let uri = match Uri::from_str(&uri) {
Ok(uri) => uri,
Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to build URI: {}", err))))),
Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))),
};
let mut request = hyper::Request::new(hyper::Method::Put, uri);
let mut request = match hyper::Request::builder()
.method("PUT")
.uri(uri)
.body(Body::empty()) {
Ok(req) => req,
Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e))))
};
let body = serde_json::to_string(&param_nested_response).expect("impossible to fail to serialize");
request.set_body(body);
*request.body_mut() = Body::from(body);
request.headers_mut().set(ContentType(mimetypes::requests::DUMMY_PUT.clone()));
let header = &mimetypes::requests::DUMMY_PUT;
request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) {
Ok(h) => h,
Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e))))
});
request.headers_mut().set(XSpanId((context as &dyn Has<XSpanIdString>).get().0.clone()));
Box::new(self.client_service.call(request)
let header = HeaderValue::from_str((context as &dyn Has<XSpanIdString>).get().0.clone().to_string().as_str());
request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header {
Ok(h) => h,
Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e))))
});
Box::new(self.client_service.request(request)
.map_err(|e| ApiError(format!("No response received: {}", e)))
.and_then(|mut response| {
match response.status().as_u16() {
200 => {
let body = response.body();
let body = response.into_body();
Box::new(
future::ok(
DummyPutResponse::Success
)
) as Box<dyn Future<Item=_, Error=_>>
) as Box<dyn Future<Item=_, Error=_> + Send>
},
code => {
let headers = response.headers().clone();
Box::new(response.body()
Box::new(response.into_body()
.take(100)
.concat2()
.then(move |body|
@ -364,22 +340,21 @@ impl<F, C> Api<C> for Client<F> where
Err(e) => Cow::from(format!("<Failed to read body: {}>", e)),
})))
)
) as Box<dyn Future<Item=_, Error=_>>
) as Box<dyn Future<Item=_, Error=_> + Send>
}
}
}))
}
fn file_response_get(&self, context: &C) -> Box<dyn Future<Item=FileResponseGetResponse, Error=ApiError>> {
fn file_response_get(&self, context: &C) -> Box<dyn Future<Item=FileResponseGetResponse, Error=ApiError> + Send> {
let mut uri = format!(
"{}/file_response",
self.base_path
);
let mut query_string = self::url::form_urlencoded::Serializer::new("".to_owned());
// Query parameters
let mut query_string = url::form_urlencoded::Serializer::new("".to_owned());
let query_string_str = query_string.finish();
if !query_string_str.is_empty() {
uri += "?";
@ -388,19 +363,31 @@ impl<F, C> Api<C> for Client<F> where
let uri = match Uri::from_str(&uri) {
Ok(uri) => uri,
Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to build URI: {}", err))))),
Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))),
};
let mut request = hyper::Request::new(hyper::Method::Get, uri);
let mut request = match hyper::Request::builder()
.method("GET")
.uri(uri)
.body(Body::empty()) {
Ok(req) => req,
Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e))))
};
request.headers_mut().set(XSpanId((context as &dyn Has<XSpanIdString>).get().0.clone()));
Box::new(self.client_service.call(request)
let header = HeaderValue::from_str((context as &dyn Has<XSpanIdString>).get().0.clone().to_string().as_str());
request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header {
Ok(h) => h,
Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e))))
});
Box::new(self.client_service.request(request)
.map_err(|e| ApiError(format!("No response received: {}", e)))
.and_then(|mut response| {
match response.status().as_u16() {
200 => {
let body = response.body();
let body = response.into_body();
Box::new(
body
.concat2()
@ -414,13 +401,14 @@ impl<F, C> Api<C> for Client<F> where
)
)
.map(move |body| {
FileResponseGetResponse::Success(body)
FileResponseGetResponse::Success
(body)
})
) as Box<dyn Future<Item=_, Error=_>>
) as Box<dyn Future<Item=_, Error=_> + Send>
},
code => {
let headers = response.headers().clone();
Box::new(response.body()
Box::new(response.into_body()
.take(100)
.concat2()
.then(move |body|
@ -435,22 +423,21 @@ impl<F, C> Api<C> for Client<F> where
Err(e) => Cow::from(format!("<Failed to read body: {}>", e)),
})))
)
) as Box<dyn Future<Item=_, Error=_>>
) as Box<dyn Future<Item=_, Error=_> + Send>
}
}
}))
}
fn html_post(&self, param_body: String, context: &C) -> Box<dyn Future<Item=HtmlPostResponse, Error=ApiError>> {
fn html_post(&self, param_body: String, context: &C) -> Box<dyn Future<Item=HtmlPostResponse, Error=ApiError> + Send> {
let mut uri = format!(
"{}/html",
self.base_path
);
let mut query_string = self::url::form_urlencoded::Serializer::new("".to_owned());
// Query parameters
let mut query_string = url::form_urlencoded::Serializer::new("".to_owned());
let query_string_str = query_string.finish();
if !query_string_str.is_empty() {
uri += "?";
@ -459,23 +446,39 @@ impl<F, C> Api<C> for Client<F> where
let uri = match Uri::from_str(&uri) {
Ok(uri) => uri,
Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to build URI: {}", err))))),
Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))),
};
let mut request = hyper::Request::new(hyper::Method::Post, uri);
let mut request = match hyper::Request::builder()
.method("POST")
.uri(uri)
.body(Body::empty()) {
Ok(req) => req,
Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e))))
};
let body = param_body;
request.set_body(body);
*request.body_mut() = Body::from(body);
request.headers_mut().set(ContentType(mimetypes::requests::HTML_POST.clone()));
let header = &mimetypes::requests::HTML_POST;
request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) {
Ok(h) => h,
Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e))))
});
request.headers_mut().set(XSpanId((context as &dyn Has<XSpanIdString>).get().0.clone()));
Box::new(self.client_service.call(request)
let header = HeaderValue::from_str((context as &dyn Has<XSpanIdString>).get().0.clone().to_string().as_str());
request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header {
Ok(h) => h,
Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e))))
});
Box::new(self.client_service.request(request)
.map_err(|e| ApiError(format!("No response received: {}", e)))
.and_then(|mut response| {
match response.status().as_u16() {
200 => {
let body = response.body();
let body = response.into_body();
Box::new(
body
.concat2()
@ -488,13 +491,14 @@ impl<F, C> Api<C> for Client<F> where
)
)
.map(move |body| {
HtmlPostResponse::Success(body)
HtmlPostResponse::Success
(body)
})
) as Box<dyn Future<Item=_, Error=_>>
) as Box<dyn Future<Item=_, Error=_> + Send>
},
code => {
let headers = response.headers().clone();
Box::new(response.body()
Box::new(response.into_body()
.take(100)
.concat2()
.then(move |body|
@ -509,22 +513,21 @@ impl<F, C> Api<C> for Client<F> where
Err(e) => Cow::from(format!("<Failed to read body: {}>", e)),
})))
)
) as Box<dyn Future<Item=_, Error=_>>
) as Box<dyn Future<Item=_, Error=_> + Send>
}
}
}))
}
fn raw_json_get(&self, context: &C) -> Box<dyn Future<Item=RawJsonGetResponse, Error=ApiError>> {
fn raw_json_get(&self, context: &C) -> Box<dyn Future<Item=RawJsonGetResponse, Error=ApiError> + Send> {
let mut uri = format!(
"{}/raw_json",
self.base_path
);
let mut query_string = self::url::form_urlencoded::Serializer::new("".to_owned());
// Query parameters
let mut query_string = url::form_urlencoded::Serializer::new("".to_owned());
let query_string_str = query_string.finish();
if !query_string_str.is_empty() {
uri += "?";
@ -533,19 +536,31 @@ impl<F, C> Api<C> for Client<F> where
let uri = match Uri::from_str(&uri) {
Ok(uri) => uri,
Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to build URI: {}", err))))),
Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))),
};
let mut request = hyper::Request::new(hyper::Method::Get, uri);
let mut request = match hyper::Request::builder()
.method("GET")
.uri(uri)
.body(Body::empty()) {
Ok(req) => req,
Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e))))
};
request.headers_mut().set(XSpanId((context as &dyn Has<XSpanIdString>).get().0.clone()));
Box::new(self.client_service.call(request)
let header = HeaderValue::from_str((context as &dyn Has<XSpanIdString>).get().0.clone().to_string().as_str());
request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header {
Ok(h) => h,
Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e))))
});
Box::new(self.client_service.request(request)
.map_err(|e| ApiError(format!("No response received: {}", e)))
.and_then(|mut response| {
match response.status().as_u16() {
200 => {
let body = response.body();
let body = response.into_body();
Box::new(
body
.concat2()
@ -559,13 +574,14 @@ impl<F, C> Api<C> for Client<F> where
)
)
.map(move |body| {
RawJsonGetResponse::Success(body)
RawJsonGetResponse::Success
(body)
})
) as Box<dyn Future<Item=_, Error=_>>
) as Box<dyn Future<Item=_, Error=_> + Send>
},
code => {
let headers = response.headers().clone();
Box::new(response.body()
Box::new(response.into_body()
.take(100)
.concat2()
.then(move |body|
@ -580,7 +596,7 @@ impl<F, C> Api<C> for Client<F> where
Err(e) => Cow::from(format!("<Failed to read body: {}>", e)),
})))
)
) as Box<dyn Future<Item=_, Error=_>>
) as Box<dyn Future<Item=_, Error=_> + Send>
}
}
}))
@ -592,13 +608,13 @@ impl<F, C> Api<C> for Client<F> where
#[derive(Debug)]
pub enum ClientInitError {
InvalidScheme,
InvalidUri(hyper::error::UriError),
InvalidUri(hyper::http::uri::InvalidUri),
MissingHost,
SslError(openssl::error::ErrorStack)
}
impl From<hyper::error::UriError> for ClientInitError {
fn from(err: hyper::error::UriError) -> ClientInitError {
impl From<hyper::http::uri::InvalidUri> for ClientInitError {
fn from(err: hyper::http::uri::InvalidUri) -> ClientInitError {
ClientInitError::InvalidUri(err)
}
}

View File

@ -1,18 +1,17 @@
#![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)]
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
// Crates with macros
#[macro_use]
extern crate serde_derive;
#[cfg(any(feature = "client", feature = "server"))]
#[cfg(any(feature = "server"))]
#[macro_use]
extern crate hyper;
extern crate lazy_static;
#[cfg(any(feature = "client", feature = "server"))]
#[macro_use]
extern crate url;
#[macro_use]
extern crate log;
// Crates for conversion support
#[cfg(feature = "conversion")]
@ -26,12 +25,37 @@ extern crate frunk_core;
extern crate mime;
extern crate serde;
extern crate serde_json;
extern crate futures;
extern crate chrono;
extern crate swagger;
#[cfg(any(feature = "client", feature = "server"))]
extern crate hyper;
#[cfg(any(feature = "client"))]
extern crate hyper_tls;
#[cfg(any(feature = "client", feature = "server"))]
extern crate openssl;
#[cfg(any(feature = "client", feature = "server"))]
extern crate native_tls;
#[cfg(feature = "server")]
extern crate percent_encoding;
#[cfg(any(feature = "client", feature = "server"))]
extern crate serde_json;
#[cfg(any(feature = "client", feature = "server"))]
extern crate serde_ignored;
#[cfg(any(feature = "client", feature = "server"))]
extern crate tokio;
#[cfg(any(feature = "client", feature = "server"))]
#[cfg(any(feature = "client", feature = "server"))]
use hyper::header::HeaderValue;
use futures::Stream;
use std::io::Error;
@ -88,19 +112,19 @@ pub enum RawJsonGetResponse {
pub trait Api<C> {
/// A dummy endpoint to make the spec valid.
fn dummy_get(&self, context: &C) -> Box<dyn Future<Item=DummyGetResponse, Error=ApiError>>;
fn dummy_get(&self, context: &C) -> Box<dyn Future<Item=DummyGetResponse, Error=ApiError> + Send>;
fn dummy_put(&self, nested_response: models::InlineObject, context: &C) -> Box<dyn Future<Item=DummyPutResponse, Error=ApiError>>;
fn dummy_put(&self, nested_response: models::InlineObject, context: &C) -> Box<dyn Future<Item=DummyPutResponse, Error=ApiError> + Send>;
/// Get a file
fn file_response_get(&self, context: &C) -> Box<dyn Future<Item=FileResponseGetResponse, Error=ApiError>>;
fn file_response_get(&self, context: &C) -> Box<dyn Future<Item=FileResponseGetResponse, Error=ApiError> + Send>;
/// Test HTML handling
fn html_post(&self, body: String, context: &C) -> Box<dyn Future<Item=HtmlPostResponse, Error=ApiError>>;
fn html_post(&self, body: String, context: &C) -> Box<dyn Future<Item=HtmlPostResponse, Error=ApiError> + Send>;
/// Get an arbitrary JSON blob.
fn raw_json_get(&self, context: &C) -> Box<dyn Future<Item=RawJsonGetResponse, Error=ApiError>>;
fn raw_json_get(&self, context: &C) -> Box<dyn Future<Item=RawJsonGetResponse, Error=ApiError> + Send>;
}
@ -108,19 +132,19 @@ pub trait Api<C> {
pub trait ApiNoContext {
/// A dummy endpoint to make the spec valid.
fn dummy_get(&self) -> Box<dyn Future<Item=DummyGetResponse, Error=ApiError>>;
fn dummy_get(&self) -> Box<dyn Future<Item=DummyGetResponse, Error=ApiError> + Send>;
fn dummy_put(&self, nested_response: models::InlineObject) -> Box<dyn Future<Item=DummyPutResponse, Error=ApiError>>;
fn dummy_put(&self, nested_response: models::InlineObject) -> Box<dyn Future<Item=DummyPutResponse, Error=ApiError> + Send>;
/// Get a file
fn file_response_get(&self) -> Box<dyn Future<Item=FileResponseGetResponse, Error=ApiError>>;
fn file_response_get(&self) -> Box<dyn Future<Item=FileResponseGetResponse, Error=ApiError> + Send>;
/// Test HTML handling
fn html_post(&self, body: String) -> Box<dyn Future<Item=HtmlPostResponse, Error=ApiError>>;
fn html_post(&self, body: String) -> Box<dyn Future<Item=HtmlPostResponse, Error=ApiError> + Send>;
/// Get an arbitrary JSON blob.
fn raw_json_get(&self) -> Box<dyn Future<Item=RawJsonGetResponse, Error=ApiError>>;
fn raw_json_get(&self) -> Box<dyn Future<Item=RawJsonGetResponse, Error=ApiError> + Send>;
}
@ -139,27 +163,27 @@ impl<'a, T: Api<C> + Sized, C> ContextWrapperExt<'a, C> for T {
impl<'a, T: Api<C>, C> ApiNoContext for ContextWrapper<'a, T, C> {
/// A dummy endpoint to make the spec valid.
fn dummy_get(&self) -> Box<dyn Future<Item=DummyGetResponse, Error=ApiError>> {
fn dummy_get(&self) -> Box<dyn Future<Item=DummyGetResponse, Error=ApiError> + Send> {
self.api().dummy_get(&self.context())
}
fn dummy_put(&self, nested_response: models::InlineObject) -> Box<dyn Future<Item=DummyPutResponse, Error=ApiError>> {
fn dummy_put(&self, nested_response: models::InlineObject) -> Box<dyn Future<Item=DummyPutResponse, Error=ApiError> + Send> {
self.api().dummy_put(nested_response, &self.context())
}
/// Get a file
fn file_response_get(&self) -> Box<dyn Future<Item=FileResponseGetResponse, Error=ApiError>> {
fn file_response_get(&self) -> Box<dyn Future<Item=FileResponseGetResponse, Error=ApiError> + Send> {
self.api().file_response_get(&self.context())
}
/// Test HTML handling
fn html_post(&self, body: String) -> Box<dyn Future<Item=HtmlPostResponse, Error=ApiError>> {
fn html_post(&self, body: String) -> Box<dyn Future<Item=HtmlPostResponse, Error=ApiError> + Send> {
self.api().html_post(body, &self.context())
}
/// Get an arbitrary JSON blob.
fn raw_json_get(&self) -> Box<dyn Future<Item=RawJsonGetResponse, Error=ApiError>> {
fn raw_json_get(&self) -> Box<dyn Future<Item=RawJsonGetResponse, Error=ApiError> + Send> {
self.api().raw_json_get(&self.context())
}

View File

@ -1,38 +1,25 @@
/// mime types for requests and responses
pub mod responses {
use hyper::mime::*;
// The macro is called per-operation to beat the recursion limit
lazy_static! {
/// Create Mime objects for the response content types for FileResponseGet
pub static ref FILE_RESPONSE_GET_SUCCESS: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the response content types for FileResponseGet
pub static FILE_RESPONSE_GET_SUCCESS: &str = "application/json";
lazy_static! {
/// Create Mime objects for the response content types for HtmlPost
pub static ref HTML_POST_SUCCESS: Mime = "text/html".parse().unwrap();
}
/// Create &str objects for the response content types for HtmlPost
pub static HTML_POST_SUCCESS: &str = "text/html";
lazy_static! {
/// Create Mime objects for the response content types for RawJsonGet
pub static ref RAW_JSON_GET_SUCCESS: Mime = "*/*".parse().unwrap();
}
/// Create &str objects for the response content types for RawJsonGet
pub static RAW_JSON_GET_SUCCESS: &str = "*/*";
}
pub mod requests {
use hyper::mime::*;
lazy_static! {
/// Create Mime objects for the request content types for DummyPut
pub static ref DUMMY_PUT: Mime = "application/json".parse().unwrap();
}
/// Create &str objects for the request content types for DummyPut
pub static DUMMY_PUT: &str = "application/json";
lazy_static! {
/// Create Mime objects for the request content types for HtmlPost
pub static ref HTML_POST: Mime = "text/html".parse().unwrap();
}
/// Create &str objects for the request content types for HtmlPost
pub static HTML_POST: &str = "text/html";
}

View File

@ -1,5 +1,4 @@
#![allow(unused_imports, unused_qualifications, unused_extern_crates)]
extern crate chrono;
#![allow(unused_imports, unused_qualifications)]
use serde::ser::Serializer;

View File

@ -1,64 +1,86 @@
use futures::Future;
use hyper;
use hyper::header::HeaderName;
use hyper::{Error, Request, Response, StatusCode, service::Service, body::Payload};
use url::form_urlencoded;
use std::default::Default;
use std::io;
use std::marker::PhantomData;
use 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 swagger::auth::{AuthData, Authorization, Bearer, Scopes};
use swagger::context::ContextualPayload;
use swagger::{EmptyContext, Has, Pop, Push, XSpanIdString};
use Api;
pub struct NewAddContext<T, A>
{
pub struct MakeAddContext<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,
impl<T, A, B, C, D> MakeAddContext<T, A>
where
A: Default + Push<XSpanIdString, Result = B>,
B: Push<Option<AuthData>, Result = C>,
C: Push<Option<Authorization>, Result = D>,
{
pub fn new(inner: T) -> NewAddContext<T, A> {
NewAddContext {
pub fn new(inner: T) -> MakeAddContext<T, A> {
MakeAddContext {
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,
// Make a service that adds context.
impl<'a, T, SC, A, B, C, D, E, ME, S, OB, F> hyper::service::MakeService<&'a SC> for
MakeAddContext<T, A>
where
A: Default + Push<XSpanIdString, Result = B>,
B: Push<Option<AuthData>, Result = C>,
C: Push<Option<Authorization>, Result = D>,
D: Send + 'static,
T: hyper::service::MakeService<
&'a SC,
Error = E,
MakeError = ME,
Service = S,
ReqBody = ContextualPayload<hyper::Body, D>,
ResBody = OB,
Future = F
>,
S: Service<
Error = E,
ReqBody = ContextualPayload<hyper::Body, D>,
ResBody = OB> + 'static,
ME: swagger::ErrorBound,
E: swagger::ErrorBound,
F: Future<Item=S, Error=ME> + Send + 'static,
S::Future: Send,
OB: Payload,
{
type Request = Request;
type Response = Response;
type Error = Error;
type Instance = AddContext<T::Instance, A>;
type ReqBody = hyper::Body;
type ResBody = OB;
type Error = E;
type MakeError = ME;
type Service = AddContext<S, A>;
type Future = Box<dyn Future<Item = Self::Service, Error = ME> + Send + 'static>;
fn new_service(&self) -> Result<Self::Instance, io::Error> {
self.inner.new_service().map(|s| AddContext::new(s))
fn make_service(&mut self, ctx: &'a SC) -> Self::Future {
Box::new(self.inner.make_service(ctx).map(|s| AddContext::new(s)))
}
}
/// Middleware to extract authentication data from request
pub struct AddContext<T, A>
{
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>,
where
A: Default + Push<XSpanIdString, Result = B>,
B: Push<Option<AuthData>, Result = C>,
C: Push<Option<Authorization>, Result = D>,
T: Service,
{
pub fn new(inner: T) -> AddContext<T, A> {
AddContext {
@ -68,24 +90,33 @@ impl<T, A, B, C, D> AddContext<T, A>
}
}
impl<T, A, B, C, D> hyper::server::Service for AddContext<T, A>
impl<T, A, B, C, D> Service for AddContext<T, A>
where
A: Default + Push<XSpanIdString, Result=B>,
B: Push<Option<AuthData>, Result=C>,
C: Push<Option<Authorization>, Result=D>,
T: hyper::server::Service<Request = (Request, D), Response = Response, Error = Error>,
D: Send + 'static,
T: Service<ReqBody = ContextualPayload<hyper::Body, D>>,
T::Future: Future<Item=Response<T::ResBody>, Error=T::Error> + Send + 'static
{
type Request = Request;
type Response = Response;
type Error = Error;
type Future = T::Future;
type ReqBody = hyper::Body;
type ResBody = T::ResBody;
type Error = T::Error;
type Future = Box<dyn Future<Item=Response<T::ResBody>, Error=T::Error> + Send + 'static>;
fn call(&self, req: Self::Request) -> Self::Future {
fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future {
let context = A::default().push(XSpanIdString::get_or_generate(&req));
let (head, body) = req.into_parts();
let headers = head.headers.clone();
let context = context.push(None::<AuthData>);
let context = context.push(None::<Authorization>);
return self.inner.call((req, context));
let body = ContextualPayload {
inner: body,
context: context,
};
Box::new(self.inner.call(hyper::Request::from_parts(head, body)))
}
}

View File

@ -1,36 +1,22 @@
#![allow(unused_extern_crates)]
extern crate serde_ignored;
extern crate tokio_core;
extern crate native_tls;
extern crate hyper_tls;
extern crate openssl;
extern crate mime;
extern crate chrono;
extern crate percent_encoding;
extern crate url;
use std::sync::Arc;
#[allow(unused_imports)]
use std::collections::{HashMap, BTreeMap, BTreeSet};
use std::marker::PhantomData;
use futures::{Future, future, Stream, stream};
use hyper;
use hyper::{Request, Response, Error, StatusCode};
use hyper::header::{Headers, ContentType};
use self::url::form_urlencoded;
use mimetypes;
use hyper::{Request, Response, Error, StatusCode, Body, HeaderMap};
use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE};
use serde_json;
#[allow(unused_imports)]
use std::collections::{HashMap, BTreeMap};
use std::io;
#[allow(unused_imports)]
use swagger;
use std::io;
use swagger::{ApiError, XSpanIdString, Has, RequestParser};
use swagger::auth::Scopes;
use swagger::context::ContextualPayload;
use url::form_urlencoded;
#[allow(unused_imports)]
use std::collections::BTreeSet;
use mimetypes;
pub use swagger::auth::Authorization;
use swagger::{ApiError, XSpanId, XSpanIdString, Has, RequestParser};
use swagger::auth::Scopes;
use {Api,
DummyGetResponse,
@ -39,13 +25,12 @@ use {Api,
HtmlPostResponse,
RawJsonGetResponse
};
#[allow(unused_imports)]
use models;
pub mod context;
header! { (Warning, "Warning") => [String] }
mod paths {
extern crate regex;
@ -55,7 +40,8 @@ mod paths {
r"^/file_response$",
r"^/html$",
r"^/raw_json$"
]).unwrap();
])
.expect("Unable to create global regex set");
}
pub static ID_DUMMY: usize = 0;
pub static ID_FILE_RESPONSE: usize = 1;
@ -63,77 +49,97 @@ mod paths {
pub static ID_RAW_JSON: usize = 3;
}
pub struct NewService<T, C> {
api_impl: Arc<T>,
marker: PhantomData<C>,
pub struct MakeService<T, RC> {
api_impl: T,
marker: PhantomData<RC>,
}
impl<T, C> NewService<T, C>
impl<T, RC> MakeService<T, RC>
where
T: Api<C> + Clone + 'static,
C: Has<XSpanIdString> + 'static
T: Api<RC> + Clone + Send + 'static,
RC: Has<XSpanIdString> + 'static
{
pub fn new<U: Into<Arc<T>>>(api_impl: U) -> NewService<T, C> {
NewService{api_impl: api_impl.into(), marker: PhantomData}
pub fn new(api_impl: T) -> Self {
MakeService {
api_impl,
marker: PhantomData
}
}
}
impl<T, C> hyper::server::NewService for NewService<T, C>
impl<'a, T, SC, RC> hyper::service::MakeService<&'a SC> for MakeService<T, RC>
where
T: Api<C> + Clone + 'static,
C: Has<XSpanIdString> + 'static
T: Api<RC> + Clone + Send + 'static,
RC: Has<XSpanIdString> + 'static + Send
{
type Request = (Request, C);
type Response = Response;
type ReqBody = ContextualPayload<Body, RC>;
type ResBody = Body;
type Error = Error;
type Instance = Service<T, C>;
type Service = Service<T, RC>;
type Future = future::FutureResult<Self::Service, Self::MakeError>;
type MakeError = Error;
fn new_service(&self) -> Result<Self::Instance, io::Error> {
Ok(Service::new(self.api_impl.clone()))
fn make_service(&mut self, _ctx: &'a SC) -> Self::Future {
future::FutureResult::from(Ok(Service::new(
self.api_impl.clone(),
)))
}
}
pub struct Service<T, C> {
api_impl: Arc<T>,
marker: PhantomData<C>,
pub struct Service<T, RC> {
api_impl: T,
marker: PhantomData<RC>,
}
impl<T, C> Service<T, C>
impl<T, RC> Service<T, RC>
where
T: Api<C> + Clone + 'static,
C: Has<XSpanIdString> + 'static {
pub fn new<U: Into<Arc<T>>>(api_impl: U) -> Service<T, C> {
Service{api_impl: api_impl.into(), marker: PhantomData}
T: Api<RC> + Clone + Send + 'static,
RC: Has<XSpanIdString> + 'static {
pub fn new(api_impl: T) -> Self {
Service {
api_impl: api_impl,
marker: PhantomData
}
}
}
impl<T, C> hyper::server::Service for Service<T, C>
impl<T, C> hyper::service::Service for Service<T, C>
where
T: Api<C> + Clone + 'static,
C: Has<XSpanIdString> + 'static
T: Api<C> + Clone + Send + 'static,
C: Has<XSpanIdString> + 'static + Send
{
type Request = (Request, C);
type Response = Response;
type ReqBody = ContextualPayload<Body, C>;
type ResBody = Body;
type Error = Error;
type Future = Box<dyn Future<Item=Response, Error=Error>>;
type Future = Box<dyn Future<Item = Response<Self::ResBody>, Error = Self::Error> + Send>;
fn call(&self, (req, mut context): Self::Request) -> Self::Future {
fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future {
let api_impl = self.api_impl.clone();
let (method, uri, _, headers, body) = req.deconstruct();
let (parts, body) = req.into_parts();
let (method, uri, headers) = (parts.method, parts.uri, parts.headers);
let path = paths::GLOBAL_REGEX_SET.matches(uri.path());
let mut context = body.context;
let body = body.inner;
// This match statement is duplicated below in `parse_operation_id()`.
// Please update both places if changing how this code is autogenerated.
match &method {
// DummyGet - GET /dummy
&hyper::Method::Get if path.matched(paths::ID_DUMMY) => {
&hyper::Method::GET if path.matched(paths::ID_DUMMY) => {
Box::new({
{{
Box::new(api_impl.dummy_get(&context)
.then(move |result| {
let mut response = Response::new();
response.headers_mut().set(XSpanId((&context as &dyn Has<XSpanIdString>).get().0.to_string()));
Box::new(
api_impl.dummy_get(
&context
).then(move |result| {
let mut response = Response::new(Body::empty());
response.headers_mut().insert(
HeaderName::from_static("x-span-id"),
HeaderValue::from_str((&context as &dyn Has<XSpanIdString>).get().0.clone().to_string().as_str())
.expect("Unable to create X-Span-ID header value"));
match result {
Ok(rsp) => match rsp {
@ -141,15 +147,15 @@ where
=> {
response.set_status(StatusCode::try_from(200).unwrap());
*response.status_mut() = StatusCode::from_u16(200).expect("Unable to turn 200 into a StatusCode");
},
},
Err(_) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.set_status(StatusCode::InternalServerError);
response.set_body("An internal error occurred");
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
*response.body_mut() = Body::from("An internal error occurred");
},
}
@ -157,16 +163,16 @@ where
}
))
}}
}) as Box<dyn Future<Item=Response, Error=Error>>
}) as Self::Future
},
// DummyPut - PUT /dummy
&hyper::Method::Put if path.matched(paths::ID_DUMMY) => {
&hyper::Method::PUT if path.matched(paths::ID_DUMMY) => {
// Body parameters (note that non-required body parameters will ignore garbage
// values, rather than causing a 400 response). Produce warning header and logs for
// any unused fields.
Box::new(body.concat2()
.then(move |result| -> Box<dyn Future<Item=Response, Error=Error>> {
.then(move |result| -> Self::Future {
match result {
Ok(body) => {
let mut unused_elements = Vec::new();
@ -177,22 +183,39 @@ where
unused_elements.push(path.to_string());
}) {
Ok(param_nested_response) => param_nested_response,
Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse body parameter nested_response - doesn't match schema: {}", e)))),
Err(e) => return Box::new(future::ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("Couldn't parse body parameter nested_response - doesn't match schema: {}", e)))
.expect("Unable to create Bad Request response for invalid body parameter nested_response due to schema"))),
}
} else {
None
};
let param_nested_response = match param_nested_response {
Some(param_nested_response) => param_nested_response,
None => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body("Missing required body parameter nested_response"))),
None => return Box::new(future::ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from("Missing required body parameter nested_response"))
.expect("Unable to create Bad Request response for missing body parameter nested_response"))),
};
Box::new(api_impl.dummy_put(param_nested_response, &context)
.then(move |result| {
let mut response = Response::new();
response.headers_mut().set(XSpanId((&context as &dyn Has<XSpanIdString>).get().0.to_string()));
Box::new(
api_impl.dummy_put(
param_nested_response,
&context
).then(move |result| {
let mut response = Response::new(Body::empty());
response.headers_mut().insert(
HeaderName::from_static("x-span-id"),
HeaderValue::from_str((&context as &dyn Has<XSpanIdString>).get().0.clone().to_string().as_str())
.expect("Unable to create X-Span-ID header value"));
if !unused_elements.is_empty() {
response.headers_mut().set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements)));
response.headers_mut().insert(
HeaderName::from_static("warning"),
HeaderValue::from_str(format!("Ignoring unknown fields in body: {:?}", unused_elements).as_str())
.expect("Unable to create Warning header value"));
}
match result {
@ -201,15 +224,15 @@ where
=> {
response.set_status(StatusCode::try_from(200).unwrap());
*response.status_mut() = StatusCode::from_u16(200).expect("Unable to turn 200 into a StatusCode");
},
},
Err(_) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.set_status(StatusCode::InternalServerError);
response.set_body("An internal error occurred");
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
*response.body_mut() = Body::from("An internal error occurred");
},
}
@ -217,20 +240,30 @@ where
}
))
},
Err(e) => Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't read body parameter nested_response: {}", e)))),
Err(e) => Box::new(future::ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("Couldn't read body parameter nested_response: {}", e)))
.expect("Unable to create Bad Request response due to unable to read body parameter nested_response"))),
}
})
) as Box<dyn Future<Item=Response, Error=Error>>
) as Self::Future
},
// FileResponseGet - GET /file_response
&hyper::Method::Get if path.matched(paths::ID_FILE_RESPONSE) => {
&hyper::Method::GET if path.matched(paths::ID_FILE_RESPONSE) => {
Box::new({
{{
Box::new(api_impl.file_response_get(&context)
.then(move |result| {
let mut response = Response::new();
response.headers_mut().set(XSpanId((&context as &dyn Has<XSpanIdString>).get().0.to_string()));
Box::new(
api_impl.file_response_get(
&context
).then(move |result| {
let mut response = Response::new(Body::empty());
response.headers_mut().insert(
HeaderName::from_static("x-span-id"),
HeaderValue::from_str((&context as &dyn Has<XSpanIdString>).get().0.clone().to_string().as_str())
.expect("Unable to create X-Span-ID header value"));
match result {
Ok(rsp) => match rsp {
@ -240,19 +273,22 @@ where
=> {
response.set_status(StatusCode::try_from(200).unwrap());
*response.status_mut() = StatusCode::from_u16(200).expect("Unable to turn 200 into a StatusCode");
response.headers_mut().set(ContentType(mimetypes::responses::FILE_RESPONSE_GET_SUCCESS.clone()));
response.headers_mut().insert(
CONTENT_TYPE,
HeaderValue::from_str(mimetypes::responses::FILE_RESPONSE_GET_SUCCESS)
.expect("Unable to create Content-Type header for FILE_RESPONSE_GET_SUCCESS"));
let body = serde_json::to_string(&body).expect("impossible to fail to serialize");
response.set_body(body);
*response.body_mut() = Body::from(body);
},
},
Err(_) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.set_status(StatusCode::InternalServerError);
response.set_body("An internal error occurred");
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
*response.body_mut() = Body::from("An internal error occurred");
},
}
@ -260,31 +296,48 @@ where
}
))
}}
}) as Box<dyn Future<Item=Response, Error=Error>>
}) as Self::Future
},
// HtmlPost - POST /html
&hyper::Method::Post if path.matched(paths::ID_HTML) => {
&hyper::Method::POST if path.matched(paths::ID_HTML) => {
// Body parameters (note that non-required body parameters will ignore garbage
// values, rather than causing a 400 response). Produce warning header and logs for
// any unused fields.
Box::new(body.concat2()
.then(move |result| -> Box<dyn Future<Item=Response, Error=Error>> {
.then(move |result| -> Self::Future {
match result {
Ok(body) => {
let param_body: Option<String> = if !body.is_empty() {
Some(String::from_utf8(body.to_vec()).unwrap())
match String::from_utf8(body.to_vec()) {
Ok(param_body) => Some(param_body),
Err(e) => return Box::new(future::ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("Couldn't parse body parameter body - not valid UTF-8: {}", e)))
.expect("Unable to create Bad Request response for invalid body parameter body due to UTF-8"))),
}
} else {
None
};
let param_body = match param_body {
Some(param_body) => param_body,
None => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body("Missing required body parameter body"))),
None => return Box::new(future::ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from("Missing required body parameter body"))
.expect("Unable to create Bad Request response for missing body parameter body"))),
};
Box::new(api_impl.html_post(param_body, &context)
.then(move |result| {
let mut response = Response::new();
response.headers_mut().set(XSpanId((&context as &dyn Has<XSpanIdString>).get().0.to_string()));
Box::new(
api_impl.html_post(
param_body,
&context
).then(move |result| {
let mut response = Response::new(Body::empty());
response.headers_mut().insert(
HeaderName::from_static("x-span-id"),
HeaderValue::from_str((&context as &dyn Has<XSpanIdString>).get().0.clone().to_string().as_str())
.expect("Unable to create X-Span-ID header value"));
match result {
Ok(rsp) => match rsp {
@ -294,19 +347,22 @@ where
=> {
response.set_status(StatusCode::try_from(200).unwrap());
*response.status_mut() = StatusCode::from_u16(200).expect("Unable to turn 200 into a StatusCode");
response.headers_mut().set(ContentType(mimetypes::responses::HTML_POST_SUCCESS.clone()));
response.headers_mut().insert(
CONTENT_TYPE,
HeaderValue::from_str(mimetypes::responses::HTML_POST_SUCCESS)
.expect("Unable to create Content-Type header for HTML_POST_SUCCESS"));
let body = body;
response.set_body(body);
*response.body_mut() = Body::from(body);
},
},
Err(_) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.set_status(StatusCode::InternalServerError);
response.set_body("An internal error occurred");
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
*response.body_mut() = Body::from("An internal error occurred");
},
}
@ -314,20 +370,30 @@ where
}
))
},
Err(e) => Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't read body parameter body: {}", e)))),
Err(e) => Box::new(future::ok(Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("Couldn't read body parameter body: {}", e)))
.expect("Unable to create Bad Request response due to unable to read body parameter body"))),
}
})
) as Box<dyn Future<Item=Response, Error=Error>>
) as Self::Future
},
// RawJsonGet - GET /raw_json
&hyper::Method::Get if path.matched(paths::ID_RAW_JSON) => {
&hyper::Method::GET if path.matched(paths::ID_RAW_JSON) => {
Box::new({
{{
Box::new(api_impl.raw_json_get(&context)
.then(move |result| {
let mut response = Response::new();
response.headers_mut().set(XSpanId((&context as &dyn Has<XSpanIdString>).get().0.to_string()));
Box::new(
api_impl.raw_json_get(
&context
).then(move |result| {
let mut response = Response::new(Body::empty());
response.headers_mut().insert(
HeaderName::from_static("x-span-id"),
HeaderValue::from_str((&context as &dyn Has<XSpanIdString>).get().0.clone().to_string().as_str())
.expect("Unable to create X-Span-ID header value"));
match result {
Ok(rsp) => match rsp {
@ -337,19 +403,22 @@ where
=> {
response.set_status(StatusCode::try_from(200).unwrap());
*response.status_mut() = StatusCode::from_u16(200).expect("Unable to turn 200 into a StatusCode");
response.headers_mut().set(ContentType(mimetypes::responses::RAW_JSON_GET_SUCCESS.clone()));
response.headers_mut().insert(
CONTENT_TYPE,
HeaderValue::from_str(mimetypes::responses::RAW_JSON_GET_SUCCESS)
.expect("Unable to create Content-Type header for RAW_JSON_GET_SUCCESS"));
let body = serde_json::to_string(&body).expect("impossible to fail to serialize");
response.set_body(body);
*response.body_mut() = Body::from(body);
},
},
Err(_) => {
// Application code returned an error. This should not happen, as the implementation should
// return a valid response.
response.set_status(StatusCode::InternalServerError);
response.set_body("An internal error occurred");
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
*response.body_mut() = Body::from("An internal error occurred");
},
}
@ -357,15 +426,19 @@ where
}
))
}}
}) as Box<dyn Future<Item=Response, Error=Error>>
}) as Self::Future
},
_ => Box::new(future::ok(Response::new().with_status(StatusCode::NotFound))) as Box<dyn Future<Item=Response, Error=Error>>,
_ => Box::new(future::ok(
Response::builder().status(StatusCode::NOT_FOUND)
.body(Body::empty())
.expect("Unable to create Not Found response")
)) as Self::Future
}
}
}
impl<T, C> Clone for Service<T, C>
impl<T, C> Clone for Service<T, C> where T: Clone
{
fn clone(&self) -> Self {
Service {
@ -375,28 +448,27 @@ impl<T, C> Clone for Service<T, C>
}
}
/// Request parser for `Api`.
pub struct ApiRequestParser;
impl RequestParser for ApiRequestParser {
fn parse_operation_id(request: &Request) -> Result<&'static str, ()> {
impl<T> RequestParser<T> for ApiRequestParser {
fn parse_operation_id(request: &Request<T>) -> Result<&'static str, ()> {
let path = paths::GLOBAL_REGEX_SET.matches(request.uri().path());
match request.method() {
// DummyGet - GET /dummy
&hyper::Method::Get if path.matched(paths::ID_DUMMY) => Ok("DummyGet"),
&hyper::Method::GET if path.matched(paths::ID_DUMMY) => Ok("DummyGet"),
// DummyPut - PUT /dummy
&hyper::Method::Put if path.matched(paths::ID_DUMMY) => Ok("DummyPut"),
&hyper::Method::PUT if path.matched(paths::ID_DUMMY) => Ok("DummyPut"),
// FileResponseGet - GET /file_response
&hyper::Method::Get if path.matched(paths::ID_FILE_RESPONSE) => Ok("FileResponseGet"),
&hyper::Method::GET if path.matched(paths::ID_FILE_RESPONSE) => Ok("FileResponseGet"),
// HtmlPost - POST /html
&hyper::Method::Post if path.matched(paths::ID_HTML) => Ok("HtmlPost"),
&hyper::Method::POST if path.matched(paths::ID_HTML) => Ok("HtmlPost"),
// RawJsonGet - GET /raw_json
&hyper::Method::Get if path.matched(paths::ID_RAW_JSON) => Ok("RawJsonGet"),
&hyper::Method::GET if path.matched(paths::ID_RAW_JSON) => Ok("RawJsonGet"),
_ => Err(()),
}
}