Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
rust-server.server-mod.mustache Maven / Gradle / Ivy
#![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;
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 serde_json;
{{#usesXml}}
use serde_xml_rs;
{{/usesXml}}
#[allow(unused_imports)]
use std::collections::{HashMap, BTreeMap};
#[allow(unused_imports)]
use swagger;
use std::io;
#[allow(unused_imports)]
use std::collections::BTreeSet;
pub use swagger::auth::Authorization;
use swagger::{ApiError, XSpanId, XSpanIdString, Has, RequestParser};
use swagger::auth::Scopes;
use swagger::headers::SafeHeaders;
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;
lazy_static! {
pub static ref GLOBAL_REGEX_SET: regex::RegexSet = regex::RegexSet::new(vec![
{{#pathSet}}
r"^{{{basePathWithoutHost}}}{{{pathRegEx}}}"{{^-last}},{{/-last}}
{{/pathSet}}
]).unwrap();
}
{{#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();
}
{{/hasPathParams}}
{{/pathSet}}
}
pub struct NewService {
api_impl: Arc,
marker: PhantomData,
}
impl NewService
where
T: Api + Clone + 'static,
C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + 'static
{
pub fn new>>(api_impl: U) -> NewService {
NewService{api_impl: api_impl.into(), marker: PhantomData}
}
}
impl hyper::server::NewService for NewService
where
T: Api + Clone + 'static,
C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + 'static
{
type Request = (Request, C);
type Response = Response;
type Error = Error;
type Instance = Service;
fn new_service(&self) -> Result {
Ok(Service::new(self.api_impl.clone()))
}
}
pub struct Service {
api_impl: Arc,
marker: PhantomData,
}
impl Service
where
T: Api + Clone + 'static,
C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + 'static {
pub fn new>>(api_impl: U) -> Service {
Service{api_impl: api_impl.into(), marker: PhantomData}
}
}
impl hyper::server::Service for Service
where
T: Api + Clone + 'static,
C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + 'static
{
type Request = (Request, C);
type Response = Response;
type Error = Error;
type Future = Box>;
fn call(&self, (req, mut context): Self::Request) -> Self::Future {
let api_impl = self.api_impl.clone();
let (method, uri, _, headers, body) = req.deconstruct();
let path = paths::GLOBAL_REGEX_SET.matches(uri.path());
// This match statement is duplicated below in `parse_operation_id()`.
// Please update both places if changing how this code is autogenerated.
match &method {
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
// {{{operationId}}} - {{{httpMethod}}} {{{path}}}
&hyper::Method::{{vendorExtensions.x-http-method}} if path.matched(paths::ID_{{vendorExtensions.x-path-id}}) => {
{{#hasAuthMethods}}
{
let authorization = match (&context as &dyn Has>).get() {
&Some(ref authorization) => authorization,
&None => return Box::new(future::ok(Response::new()
.with_status(StatusCode::Forbidden)
.with_body("Unauthenticated"))),
};
{{#authMethods}}
{{#isOAuth}}
// Authorization
if let Scopes::Some(ref scopes) = authorization.scopes {
let required_scopes: BTreeSet = vec![
{{#scopes}}
"{{{scope}}}".to_string(), // {{{description}}}
{{/scopes}}
].into_iter().collect();
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(
"Insufficient authorization, missing scopes".to_string(),
|s, scope| format!("{} {}", s, scope)
))
));
}
}
{{/isOAuth}}
{{/authMethods}}
}
{{/hasAuthMethods}}
{{#vendorExtensions}}
{{#consumesMultipart}}
let boundary = match multipart_boundary(&headers) {
Some(boundary) => boundary,
None => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body("Couldn't find valid multipart body"))),
};
{{/consumesMultipart}}
{{#hasPathParams}}
// Path parameters
let path = uri.path().to_string();
let path_params =
paths::REGEX_{{{PATH_ID}}}
.captures(&path)
.unwrap_or_else(||
panic!("Path {} matched RE {{{PATH_ID}}} in set but failed match against \"{}\"", path, paths::REGEX_{{{PATH_ID}}}.as_str())
);
{{/hasPathParams}}
{{/vendorExtensions}}
{{#pathParams}}
let param_{{{paramName}}} = match percent_encoding::percent_decode(path_params["{{{paramName}}}"].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(_) => 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["{{{paramName}}}"]))))
};
{{/pathParams}}
{{#headerParams}}
{{#-first}}
// Header parameters
{{/-first}}
header! { (Request{{vendorExtensions.x-type-name}}, "{{{baseName}}}") => {{#isListContainer}}({{{baseType}}})*{{/isListContainer}}{{^isListContainer}}[{{{dataType}}}]{{/isListContainer}} }
{{#required}}
let param_{{{paramName}}} = match headers.get::() {
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}}}"))),
};
{{/required}}
{{^required}}
let param_{{{paramName}}} = headers.safe_get::().map(|header| header.0.clone());
{{/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::>();
{{/-first}}
let param_{{{paramName}}} = query_params.iter().filter(|e| e.0 == "{{{baseName}}}").map(|e| e.1.to_owned())
{{#isListContainer}}
.filter_map(|param_{{{paramName}}}| param_{{{paramName}}}.parse::<{{{baseType}}}>().ok())
.collect::>();
{{^required}}
let param_{{{paramName}}} = if !param_{{{paramName}}}.is_empty() {
Some(param_{{{paramName}}})
} else {
None
};
{{/required}}
{{/isListContainer}}
{{^isListContainer}}
.nth(0);
{{#required}}
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)))),
},
None => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body("Missing required query parameter {{{baseName}}}"))),
};
{{/required}}{{^required}}
let param_{{{paramName}}} = param_{{{paramName}}}.and_then(|param_{{{paramName}}}| param_{{{paramName}}}.parse::<{{{baseType}}}>().ok());
{{/required}}
{{/isListContainer}}
{{/queryParams}}
{{#vendorExtensions}}
{{^consumesMultipart}}
{{#bodyParams}}
{{#-first}}
// 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> {
match result {
Ok(body) => {
{{#vendorExtensions}}
{{^consumesPlainText}}
let mut unused_elements = Vec::new();
{{/consumesPlainText}}
let param_{{{paramName}}}: Option<{{{dataType}}}> = if !body.is_empty() {
{{#consumesXml}}
let deserializer = &mut serde_xml_rs::de::Deserializer::new_from_reader(&*body);
{{/consumesXml}}
{{#consumesJson}}
let deserializer = &mut serde_json::Deserializer::from_slice(&*body);
{{/consumesJson}}
{{^consumesPlainText}}
match serde_ignored::deserialize(deserializer, |path| {
warn!("Ignoring unknown field in body: {}", path);
unused_elements.push(path.to_string());
}) {
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)))),
{{/required}}
{{^required}}
Err(_) => None,
{{/required}}
}
{{/consumesPlainText}}
{{#consumesPlainText}}
{{#isByteArray}}
Some(swagger::ByteArray(body.to_vec()))
{{/isByteArray}}
{{#isString}}
Some(String::from_utf8(body.to_vec()).unwrap())
{{/isString}}
{{/consumesPlainText}}
{{/vendorExtensions}}
} else {
None
};
{{#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}}}"))),
};
{{/required}}
{{/-first}}
{{/bodyParams}}
{{/consumesMultipart}}
{{#consumesMultipart}}
{{^bodyParams}}
{{#vendorExtensions}}
// 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> {
match result {
Ok(body) => {
// 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"))))
},
};
{{#formParams}}{{#-first}}{{/-first}}
{{#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}}
{{/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) {
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))))
}
};
{{{paramName}}}_model
}
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}}
{{/consumesMultipart}}
{{^consumesMultipart}}
{{^bodyParams}}
{{#vendorExtensions}}
Box::new({
{{
{{#formParams}}
{{#-first}}
// Form parameters
{{/-first}}
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).get().0.to_string()));
{{#bodyParams}}{{#vendorExtensions}}{{^consumesPlainText}}
if !unused_elements.is_empty() {
response.headers_mut().set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements)));
}
{{/consumesPlainText}}{{/vendorExtensions}}{{/bodyParams}}
match result {
Ok(rsp) => match rsp {
{{#responses}}
{{{operationId}}}Response::{{#vendorExtensions}}{{x-responseId}}{{/vendorExtensions}}
{{#dataType}}{{^headers}}
(body)
{{/headers}}{{#headers}}
{{#-first}}
{
body,
{{/-first}}
{{{name}}}{{^-last}}, {{/-last}}
{{#-last}}
}
{{/-last}}
{{/headers}}{{/dataType}}
{{^dataType}}{{#headers}}{{#-first}}
{
{{/-first}}
{{{name}}}{{^-last}}, {{/-last}}
{{#-last}}
}
{{/-last}}
{{/headers}}{{/dataType}}
=> {
response.set_status(StatusCode::try_from({{{code}}}).unwrap());
{{#headers}}
header! { (Response{{{nameInCamelCase}}}, "{{{baseName}}}") => [{{{dataType}}}] }
response.headers_mut().set(Response{{{nameInCamelCase}}}({{{name}}}));
{{/headers}}
{{#produces}}{{#-first}}{{#dataType}}
response.headers_mut().set(ContentType(mimetypes::responses::{{#vendorExtensions}}{{{uppercase_operation_id}}}_{{x-uppercaseResponseId}}{{/vendorExtensions}}.clone()));
{{/dataType}}{{/-first}}{{/produces}}
{{#dataType}}
{{#vendorExtensions}}
{{#producesXml}}
{{^has_namespace}}
let body = serde_xml_rs::to_string(&body).expect("impossible to fail to serialize");
{{/has_namespace}}
{{#has_namespace}}
let mut namespaces = BTreeMap::new();
// An empty string is used to indicate a global namespace in xmltree.
namespaces.insert("".to_string(), {{{dataType}}}::NAMESPACE.to_string());
let body = serde_xml_rs::to_string_with_namespaces(&body, namespaces).expect("impossible to fail to serialize");
{{/has_namespace}}
{{/producesXml}}
{{#producesJson}}
let body = serde_json::to_string(&body).expect("impossible to fail to serialize");
{{/producesJson}}
{{#producesBytes}}
let body = body.0;
{{/producesBytes}}
{{#producesPlainText}}
let body = body;
{{/producesPlainText}}
{{/vendorExtensions}}
response.set_body(body);
{{/dataType}}
},
{{/responses}}
},
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");
},
}
future::ok(response)
}
))
{{#vendorExtensions}}
{{^consumesMultipart}}
{{^bodyParams}}
}}
}) as Box>
{{/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)))),
}
})
) as Box>
{{/-first}}
{{/bodyParams}}
{{#vendorExtensions}}
{{#consumesMultipart}}
{{^bodyParams}}
as Box>
},
Err(e) => Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't read multipart body")))),
}
})
)
{{/bodyParams}}
{{/consumesMultipart}}
{{/vendorExtensions}}
},
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
_ => Box::new(future::ok(Response::new().with_status(StatusCode::NotFound))) as Box>,
}
}
}
impl Clone for Service
{
fn clone(&self) -> Self {
Service {
api_impl: self.api_impl.clone(),
marker: self.marker.clone(),
}
}
}
{{#apiUsesMultipart}}
/// Utility function to get the multipart boundary marker (if any) from the Headers.
fn multipart_boundary(headers: &Headers) -> Option {
headers.safe_get::().and_then(|content_type| {
let ContentType(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().to_string())
} else {
None
}
})
}
{{/apiUsesMultipart}}
/// Request parser for `Api`.
pub struct ApiRequestParser;
impl RequestParser for ApiRequestParser {
fn parse_operation_id(request: &Request) -> Result<&'static str, ()> {
let path = paths::GLOBAL_REGEX_SET.matches(request.uri().path());
match request.method() {
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
// {{{operationId}}} - {{{httpMethod}}} {{{path}}}
&hyper::Method::{{{vendorExtensions.x-http-method}}} if path.matched(paths::ID_{{{vendorExtensions.x-path-id}}}) => Ok("{{{operationId}}}"),
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} _ => Err(()),
}
}
}