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;
{{^apiUsesUuid}}extern crate uuid;{{/apiUsesUuid}}
extern crate chrono;
{{#apiHasFile}}extern crate multipart;{{/apiHasFile}}
extern crate percent_encoding;
extern crate url;
{{#apiUsesUuid}}use uuid;{{/apiUsesUuid}}
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;
{{#apiHasFile}}use self::multipart::server::Multipart;
use self::multipart::server::save::SaveResult;{{/apiHasFile}}
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};
use swagger::auth::Scopes;
use {Api{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}},
{{operationId}}Response{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
};
#[allow(unused_imports)]
use models;
pub mod auth;
header! { (Warning, "Warning") => [String] }
mod paths {
extern crate regex;
lazy_static! {
pub static ref GLOBAL_REGEX_SET: regex::RegexSet = regex::RegexSet::new(&[
{{#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());
match &method {
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
// {{operationId}} - {{httpMethod}} {{path}}
&hyper::Method::{{vendorExtensions.HttpMethod}} if path.matched(paths::ID_{{vendorExtensions.PATH_ID}}) => {
{{#hasAuthMethods}}
{
let authorization = match (&context as &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}}{{#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["{{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(_) => 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}}"]))))
};
{{/pathParams}}
{{#headerParams}}{{#-first}}
// Header parameters
{{/-first}}
header! { (Request{{vendorExtensions.typeName}}, "{{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.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}}
{{#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}}
match String::from_utf8(body.to_vec()) {
Ok(param_{{paramName}}) => Some(param_{{paramName}}),
Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse body parameter {{baseName}} - not valid UTF-8: {}", e)))),
}
{{/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}}
{{^bodyParams}}{{#vendorExtensions}}{{#hasFile}}
let boundary = match 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"))),
};
Box::new(body.concat2()
.then(move |result| -> Box> {
match result {
Ok(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}}
// Form parameters
{{/-first}}
let param_{{paramName}} = entries.fields.remove("{{paramName}}");
let param_{{paramName}} = match param_{{paramName}} {
Some(entry) =>
{{#isFile}}
{{^required}}Some({{/required}}Box::new(stream::once(Ok(entry.as_bytes().to_vec()))) as Box, Error=io::Error> + Send>{{^required}}){{/required}},
{{/isFile}}{{^isFile}}
match entry.parse::<{{{dataType}}}>() {
Ok(entry) => {{^required}}Some({{/required}}entry{{^required}}){{/required}},
{{#required}}
Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse form parameter {{baseName}} - doesn't match schema: {}", e)))),
{{/required}}{{^required}}
Err(_) => None,
{{/required}}
},
{{/isFile}}
{{#required}}
None => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Missing required form parameter {{paramName}}")))),
{{/required}}{{^required}}
None => None,
{{/required}}
};
{{^required}}{{#isFile}} let param_{{paramName}} = Box::new(future::ok(param_{{paramName}}));{{/isFile}}{{/required}}
{{/formParams}}
{{/hasFile}}{{^hasFile}}
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}}
{{/hasFile}}{{/vendorExtensions}}{{/bodyParams}}
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 &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}}
=> {
{{^isFile}} 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(), models::namespaces::{{uppercase_data_type}}.clone());
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}}{{/vendorExtensions}}
response.set_body(body);
{{/dataType}}{{/isFile}}{{#isFile}}
let body = body.fold(Vec::new(), | mut body, chunk| {
body.extend(chunk.iter());
future::ok::, io::Error>(body)
})
// Block whilst waiting for the stream to complete
.wait();
match body {
// If no error occurred then create successful hyper response
Ok(vec) => {
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}}
response.set_body(vec);
},
// It's possible that errors were received in the stream, if this is the case then we can't return a success response to the client and instead must return an internal error.
Err(e) => {
response.set_status(StatusCode::InternalServerError);
response.set_body("An internal error occurred");
}
}
{{/isFile}}
},
{{/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)
}
))
{{^bodyParams}}{{#vendorExtensions}}{{^hasFile}}
}}
}) as Box>
{{/hasFile}}{{#hasFile}}
as Box>
},
Err(e) => Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't read multipart body")))),
}
})
)
{{/hasFile}}{{/vendorExtensions}}{{/bodyParams}}
{{#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}}
},
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
_ => Box::new(future::ok(Response::new().with_status(StatusCode::NotFound))) as Box>,
}
}
}
{{#apiHasFile}}
/// 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::().and_then(|content_type| {
let ContentType(ref mime) = *content_type;
if mime.type_() == mime::MULTIPART && mime.subtype() == mime::FORM_DATA {
mime.get_param(mime::BOUNDARY).map(|x| x.as_str())
} else {
None
}
})
}
{{/apiHasFile}}