From 248cfcfdbe4c8a4568656d4a6f97983a78373a19 Mon Sep 17 00:00:00 2001 From: Euan Kemp Date: Mon, 9 Jul 2018 12:27:00 -0700 Subject: [PATCH 1/3] [Rust] Move request logic into standalone file This reduces the number of variables which are used in the generated operations, thus fixing #512. This also fixed a TODO related to URI parsing errors. Other than that, it is meant to be functionally identical. --- .../codegen/languages/RustClientCodegen.java | 3 +- .../src/main/resources/rust/api.mustache | 157 ++--- .../src/main/resources/rust/api_mod.mustache | 3 + .../src/main/resources/rust/request.rs | 227 +++++++ .../petstore/rust/.openapi-generator/VERSION | 2 +- .../client/petstore/rust/examples/client.rs | 4 +- .../petstore/rust/examples/error_handling.rs | 6 +- samples/client/petstore/rust/src/apis/mod.rs | 3 + .../client/petstore/rust/src/apis/pet_api.rs | 557 ++---------------- .../client/petstore/rust/src/apis/request.rs | 227 +++++++ .../petstore/rust/src/apis/store_api.rs | 230 +------- .../client/petstore/rust/src/apis/user_api.rs | 415 ++----------- 12 files changed, 599 insertions(+), 1235 deletions(-) create mode 100644 modules/openapi-generator/src/main/resources/rust/request.rs create mode 100644 samples/client/petstore/rust/src/apis/request.rs diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustClientCodegen.java index f7e46ea78d2c..76411f0406c3 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustClientCodegen.java @@ -165,8 +165,9 @@ public void processOpts() { supportingFiles.add(new SupportingFile("configuration.mustache", apiFolder, "configuration.rs")); supportingFiles.add(new SupportingFile(".travis.yml", "", ".travis.yml")); - supportingFiles.add(new SupportingFile("client.mustache", apiFolder, "client.rs")); supportingFiles.add(new SupportingFile("api_mod.mustache", apiFolder, "mod.rs")); + supportingFiles.add(new SupportingFile("client.mustache", apiFolder, "client.rs")); + supportingFiles.add(new SupportingFile("request.rs", apiFolder, "request.rs")); supportingFiles.add(new SupportingFile("model_mod.mustache", modelFolder, "mod.rs")); supportingFiles.add(new SupportingFile("lib.rs", "src", "lib.rs")); supportingFiles.add(new SupportingFile("Cargo.mustache", "", "Cargo.toml")); diff --git a/modules/openapi-generator/src/main/resources/rust/api.mustache b/modules/openapi-generator/src/main/resources/rust/api.mustache index 55604ca79332..eca462527dbd 100644 --- a/modules/openapi-generator/src/main/resources/rust/api.mustache +++ b/modules/openapi-generator/src/main/resources/rust/api.mustache @@ -1,17 +1,13 @@ {{>partial_header}} use std::rc::Rc; use std::borrow::Borrow; -use std::borrow::Cow; -use std::collections::HashMap; use hyper; use serde_json; -use futures; -use futures::{Future, Stream}; - -use hyper::header::UserAgent; +use futures::Future; use super::{Error, configuration}; +use super::request as __internal_request; pub struct {{{classname}}}Client { configuration: Rc>, @@ -38,129 +34,44 @@ impl{{classname}} for {{classname}}Client { {{#operations}} {{#operation}} fn {{{operationId}}}(&self, {{#allParams}}{{paramName}}: {{#isString}}&str{{/isString}}{{#isUuid}}&str{{/isUuid}}{{^isString}}{{^isUuid}}{{^isPrimitiveType}}{{^isContainer}}::models::{{/isContainer}}{{/isPrimitiveType}}{{{dataType}}}{{/isUuid}}{{/isString}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) -> Box>> { - let configuration: &configuration::Configuration = self.configuration.borrow(); - -{{#hasAuthMethods}} - let mut auth_headers = HashMap::::new(); - let mut auth_query = HashMap::::new(); -{{#authMethods}} -{{#isApiKey}} - if let Some(ref apikey) = configuration.api_key { - let key = apikey.key.clone(); - let val = match apikey.prefix { - Some(ref prefix) => format!("{} {}", prefix, key), - None => key, - }; - {{#isKeyInHeader}} - auth_headers.insert("{{keyParamName}}".to_owned(), val); - {{/isKeyInHeader}} - {{#isKeyInQuery}} - auth_query.insert("{{keyParamName}}".to_owned(), val); - {{/isKeyInQuery}} - }; -{{/isApiKey}} -{{#isBasic}} - if let Some(ref auth_conf) = configuration.basic_auth { - let auth = hyper::header::Authorization( - hyper::header::Basic { - username: auth_conf.0.to_owned(), - password: auth_conf.1.to_owned(), - } - ); - auth_headers.insert("Authorization".to_owned(), auth.to_string()); - }; -{{/isBasic}} -{{#isOAuth}} - if let Some(ref token) = configuration.oauth_access_token { - let auth = hyper::header::Authorization( - hyper::header::Bearer { - token: token.to_owned(), - } - ); - auth_headers.insert("Authorization".to_owned(), auth.to_string()); - }; -{{/isOAuth}} -{{/authMethods}} -{{/hasAuthMethods}} - let method = hyper::Method::{{httpMethod}}; - - let query_string = { - let mut query = ::url::form_urlencoded::Serializer::new(String::new()); -{{#queryParams}} - query.append_pair("{{baseName}}", &{{paramName}}{{#isListContainer}}.join(","){{/isListContainer}}.to_string()); -{{/queryParams}} -{{#hasAuthMethods}} - for (key, val) in &auth_query { - query.append_pair(key, val); - } -{{/hasAuthMethods}} - query.finish() - }; - let uri_str = format!("{}{{{path}}}?{}", configuration.base_path, query_string{{#pathParams}}, {{baseName}}={{paramName}}{{#isListContainer}}.join(",").as_ref(){{/isListContainer}}{{/pathParams}}); - - // TODO(farcaller): handle error - // if let Err(e) = uri { - // return Box::new(futures::future::err(e)); - // } - let mut uri: hyper::Uri = uri_str.parse().unwrap(); - - let mut req = hyper::Request::new(method, uri); - - if let Some(ref user_agent) = configuration.user_agent { - req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone()))); - } - - {{#hasHeaderParams}} - { - let mut headers = req.headers_mut(); - {{#headerParams}} - headers.set_raw("{{baseName}}", {{paramName}}{{#isListContainer}}.join(",").as_ref(){{/isListContainer}}); - {{/headerParams}} - } - {{/hasHeaderParams}} - + __internal_request::Request::new(hyper::Method::{{httpMethod}}, "{{{path}}}".to_string()) {{#hasAuthMethods}} - for (key, val) in auth_headers { - req.headers_mut().set_raw(key, val); - } + {{#authMethods}} + {{#isApiKey}} + .with_auth(__internal_request::Auth::ApiKey(__internal_request::ApiKey{ + in_header: {{#isKeyInHeader}}true{{/isKeyInHeader}}{{^isKeyInHeader}}false{{/isKeyInHeader}}, + in_query: {{#isKeyInQuery}}true{{/isKeyInQuery}}{{^isKeyInQuery}}false{{/isKeyInQuery}}, + param_name: "{{{keyParamName}}}".to_owned(), + })) + {{/isApiKey}} + {{#isBasic}} + .with_auth(__internal_request::Auth::Basic) + {{/isBasic}} + {{#isOAuth}} + .with_auth(__internal_request::Auth::Oauth) + {{/isOAuth}} + {{/authMethods}} {{/hasAuthMethods}} - + {{#queryParams}} + .with_query_param("{{baseName}}".to_string(), {{paramName}}{{#isListContainer}}.join(","){{/isListContainer}}.to_string()) + {{/queryParams}} + {{#pathParams}} + .with_path_param("{{baseName}}".to_string(), {{paramName}}{{#isListContainer}}.join(","){{/isListContainer}}.to_string()) + {{/pathParams}} + {{#hasHeaderParams}} + {{#headerParams}} + .with_header_param("{{baseName}}".to_string(), {{paramName}}{{#isListContainer}}.join(","){{/isListContainer}}.to_string()) + {{/headerParams}} + {{/hasHeaderParams}} {{#hasBodyParam}} {{#bodyParams}} - let serialized = serde_json::to_string(&{{paramName}}).unwrap(); - req.headers_mut().set(hyper::header::ContentType::json()); - req.headers_mut().set(hyper::header::ContentLength(serialized.len() as u64)); - req.set_body(serialized); + .with_body_param({{paramName}}) {{/bodyParams}} {{/hasBodyParam}} - - // send request - Box::new( - configuration.client.request(req) - .map_err(|e| Error::from(e)) - .and_then(|resp| { - let status = resp.status(); - resp.body().concat2() - .and_then(move |body| Ok((status, body))) - .map_err(|e| Error::from(e)) - }) - .and_then(|(status, body)| { - if status.is_success() { - Ok(body) - } else { - Err(Error::from((status, &*body))) - } - }) - {{^returnType}} - .and_then(|_| futures::future::ok(())) - {{/returnType}} - {{#returnType}} - .and_then(|body| { - let parsed: Result<{{{returnType}}}, _> = serde_json::from_slice(&body); - parsed.map_err(|e| Error::from(e)) - }) - {{/returnType}} - ) + {{^returnType}} + .returns_nothing() + {{/returnType}} + .execute(self.configuration.borrow()) } {{/operation}} diff --git a/modules/openapi-generator/src/main/resources/rust/api_mod.mustache b/modules/openapi-generator/src/main/resources/rust/api_mod.mustache index 5c8f6b86a4df..1f587b0d52fa 100644 --- a/modules/openapi-generator/src/main/resources/rust/api_mod.mustache +++ b/modules/openapi-generator/src/main/resources/rust/api_mod.mustache @@ -4,6 +4,7 @@ use serde_json; #[derive(Debug)] pub enum Error { + UriError(hyper::error::UriError), Hyper(hyper::Error), Serde(serde_json::Error), ApiError(ApiError), @@ -50,6 +51,8 @@ impl From for Error { use super::models::*; +mod request; + {{#apiInfo}} {{#apis}} mod {{classFilename}}; diff --git a/modules/openapi-generator/src/main/resources/rust/request.rs b/modules/openapi-generator/src/main/resources/rust/request.rs new file mode 100644 index 000000000000..2b996d79703d --- /dev/null +++ b/modules/openapi-generator/src/main/resources/rust/request.rs @@ -0,0 +1,227 @@ +use std::borrow::Cow; +use std::collections::HashMap; + +use super::{configuration, Error}; +use futures; +use futures::{Future, Stream}; +use hyper; +use hyper::header::UserAgent; +use serde; +use serde_json; + +pub(crate) struct ApiKey { + pub in_header: bool, + pub in_query: bool, + pub param_name: String, +} + +impl ApiKey { + fn key(&self, prefix: &Option, key: &str) -> String { + match prefix { + None => key.to_owned(), + Some(ref prefix) => format!("{} {}", prefix, key), + } + } +} + +pub(crate) enum Auth { + None, + ApiKey(ApiKey), + Basic, + Oauth, +} + +pub(crate) struct Request { + auth: Auth, + method: hyper::Method, + path: String, + query_params: HashMap, + no_return_type: bool, + path_params: HashMap, + header_params: HashMap, + // TODO: multiple body params are possible technically, but not supported here. + serialized_body: Option, +} + +impl Request { + pub fn new(method: hyper::Method, path: String) -> Self { + Request { + auth: Auth::None, + method: method, + path: path, + query_params: HashMap::new(), + path_params: HashMap::new(), + header_params: HashMap::new(), + serialized_body: None, + no_return_type: false, + } + } + + pub fn with_body_param(mut self, param: T) -> Self { + self.serialized_body = Some(serde_json::to_string(¶m).unwrap()); + self + } + + pub fn with_header_param(mut self, basename: String, param: String) -> Self { + self.header_params.insert(basename, param); + self + } + + pub fn with_query_param(mut self, basename: String, param: String) -> Self { + self.query_params.insert(basename, param); + self + } + + pub fn with_path_param(mut self, basename: String, param: String) -> Self { + self.path_params.insert(basename, param); + self + } + + pub fn with_form_param(mut self, basename: String, param: String) -> Self { + self.form_params.insert(basename, param); + self + } + + pub fn returns_nothing(mut self) -> Self { + self.no_return_type = true; + self + } + + pub fn with_auth(mut self, auth: Auth) -> Self { + self.auth = auth; + self + } + + pub fn execute<'a, C, U>( + self, + conf: &configuration::Configuration, + ) -> Box> + 'a> + where + C: hyper::client::Connect, + U: Sized + 'a, + for<'de> U: serde::Deserialize<'de>, + { + let mut query_string = ::url::form_urlencoded::Serializer::new("".to_owned()); + // raw_headers is for headers we don't know the proper type of (e.g. custom api key + // headers); headers is for ones we do know the type of. + let mut raw_headers = HashMap::new(); + let mut headers: hyper::header::Headers = hyper::header::Headers::new(); + + let mut path = self.path; + for (k, v) in self.path_params { + // replace {id} with the value of the id path param + path = path.replace(&format!("{{{}}}", k), &v); + } + + for (k, v) in self.header_params { + raw_headers.insert(k, v); + } + + for (key, val) in self.query_params { + query_string.append_pair(&key, &val); + } + + match self.auth { + Auth::ApiKey(apikey) => { + if let Some(ref key) = conf.api_key { + let val = apikey.key(&key.prefix, &key.key); + if apikey.in_query { + query_string.append_pair(&apikey.param_name, &val); + } + if apikey.in_header { + raw_headers.insert(apikey.param_name, val); + } + } + } + Auth::Basic => { + if let Some(ref auth_conf) = conf.basic_auth { + let auth = hyper::header::Authorization(hyper::header::Basic { + username: auth_conf.0.to_owned(), + password: auth_conf.1.to_owned(), + }); + headers.set(auth); + } + } + Auth::Oauth => { + if let Some(ref token) = conf.oauth_access_token { + let auth = hyper::header::Authorization(hyper::header::Bearer { + token: token.to_owned(), + }); + headers.set(auth); + } + } + Auth::None => {} + } + + let mut uri_str = format!("{}{}", conf.base_path, path); + + let query_string_str = query_string.finish(); + if query_string_str != "" { + uri_str += "?"; + uri_str += &query_string_str; + } + let uri: hyper::Uri = match uri_str.parse() { + Err(e) => { + return Box::new(futures::future::err(Error::UriError(e))); + } + Ok(u) => u, + }; + + let mut req = hyper::Request::new(self.method, uri); + { + let req_headers = req.headers_mut(); + if let Some(ref user_agent) = conf.user_agent { + req_headers.set(UserAgent::new(Cow::Owned(user_agent.clone()))); + } + + req_headers.extend(headers.iter()); + + for (key, val) in raw_headers { + req_headers.set_raw(key, val); + } + } + + if let Some(body) = self.serialized_body { + req.headers_mut().set(hyper::header::ContentType::json()); + req.headers_mut() + .set(hyper::header::ContentLength(body.len() as u64)); + req.set_body(body); + } + + let no_ret_type = self.no_return_type; + let res = conf.client + .request(req) + .map_err(|e| Error::from(e)) + .and_then(|resp| { + let status = resp.status(); + resp.body() + .concat2() + .and_then(move |body| Ok((status, body))) + .map_err(|e| Error::from(e)) + }) + .and_then(|(status, body)| { + if status.is_success() { + Ok(body) + } else { + Err(Error::from((status, &*body))) + } + }); + Box::new( + res + .and_then(move |body| { + let parsed: Result = if no_ret_type { + // This is a hack; if there's no_ret_type, U is (), but serde_json gives an + // error when deserializing "" into (), so deserialize 'null' into it + // instead. + // An alternate option would be to require U: Default, and then return + // U::default() here instead since () implements that, but then we'd + // need to impl default for all models. + serde_json::from_str("null") + } else { + serde_json::from_slice(&body) + }; + parsed.map_err(|e| Error::from(e)) + }) + ) + } +} diff --git a/samples/client/petstore/rust/.openapi-generator/VERSION b/samples/client/petstore/rust/.openapi-generator/VERSION index 096bf47efe31..a0cd9f0ccb01 100644 --- a/samples/client/petstore/rust/.openapi-generator/VERSION +++ b/samples/client/petstore/rust/.openapi-generator/VERSION @@ -1 +1 @@ -3.0.0-SNAPSHOT \ No newline at end of file +3.1.0 \ No newline at end of file diff --git a/samples/client/petstore/rust/examples/client.rs b/samples/client/petstore/rust/examples/client.rs index 6afa7a900b02..b406ba718845 100644 --- a/samples/client/petstore/rust/examples/client.rs +++ b/samples/client/petstore/rust/examples/client.rs @@ -3,10 +3,10 @@ extern crate hyper; extern crate petstore_client; extern crate tokio_core; -use hyper::Client; +use futures::Future; use hyper::client::HttpConnector; +use hyper::Client; use tokio_core::reactor::Core; -use futures::Future; fn main() { let mut core = Core::new().expect("failed to init core"); diff --git a/samples/client/petstore/rust/examples/error_handling.rs b/samples/client/petstore/rust/examples/error_handling.rs index cb3a91d28330..dbd03d0e7208 100644 --- a/samples/client/petstore/rust/examples/error_handling.rs +++ b/samples/client/petstore/rust/examples/error_handling.rs @@ -3,12 +3,12 @@ extern crate hyper; extern crate petstore_client; extern crate tokio_core; -use hyper::Client; -use hyper::client::HttpConnector; -use tokio_core::reactor::Core; use futures::Future; +use hyper::client::HttpConnector; +use hyper::Client; use petstore_client::apis::client::APIClient; use petstore_client::apis::Error; +use tokio_core::reactor::Core; fn main() { let mut core = Core::new().expect("failed to init core"); diff --git a/samples/client/petstore/rust/src/apis/mod.rs b/samples/client/petstore/rust/src/apis/mod.rs index 7199222c3f70..06935c28a931 100644 --- a/samples/client/petstore/rust/src/apis/mod.rs +++ b/samples/client/petstore/rust/src/apis/mod.rs @@ -4,6 +4,7 @@ use serde_json; #[derive(Debug)] pub enum Error { + UriError(hyper::error::UriError), Hyper(hyper::Error), Serde(serde_json::Error), ApiError(ApiError), @@ -50,6 +51,8 @@ impl From for Error { use super::models::*; +mod request; + mod pet_api; pub use self::pet_api::{ PetApi, PetApiClient }; mod store_api; diff --git a/samples/client/petstore/rust/src/apis/pet_api.rs b/samples/client/petstore/rust/src/apis/pet_api.rs index 0191b7b87dbd..f46dccfb9e51 100644 --- a/samples/client/petstore/rust/src/apis/pet_api.rs +++ b/samples/client/petstore/rust/src/apis/pet_api.rs @@ -10,17 +10,13 @@ use std::rc::Rc; use std::borrow::Borrow; -use std::borrow::Cow; -use std::collections::HashMap; use hyper; use serde_json; -use futures; -use futures::{Future, Stream}; - -use hyper::header::UserAgent; +use futures::Future; use super::{Error, configuration}; +use super::request as __internal_request; pub struct PetApiClient { configuration: Rc>, @@ -48,533 +44,70 @@ pub trait PetApi { implPetApi for PetApiClient { fn add_pet(&self, pet: ::models::Pet) -> Box>> { - let configuration: &configuration::Configuration = self.configuration.borrow(); - - let mut auth_headers = HashMap::::new(); - let mut auth_query = HashMap::::new(); - if let Some(ref token) = configuration.oauth_access_token { - let auth = hyper::header::Authorization( - hyper::header::Bearer { - token: token.to_owned(), - } - ); - auth_headers.insert("Authorization".to_owned(), auth.to_string()); - }; - let method = hyper::Method::Post; - - let query_string = { - let mut query = ::url::form_urlencoded::Serializer::new(String::new()); - for (key, val) in &auth_query { - query.append_pair(key, val); - } - query.finish() - }; - let uri_str = format!("{}/pet?{}", configuration.base_path, query_string); - - // TODO(farcaller): handle error - // if let Err(e) = uri { - // return Box::new(futures::future::err(e)); - // } - let mut uri: hyper::Uri = uri_str.parse().unwrap(); - - let mut req = hyper::Request::new(method, uri); - - if let Some(ref user_agent) = configuration.user_agent { - req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone()))); - } - - - for (key, val) in auth_headers { - req.headers_mut().set_raw(key, val); - } - - let serialized = serde_json::to_string(&pet).unwrap(); - req.headers_mut().set(hyper::header::ContentType::json()); - req.headers_mut().set(hyper::header::ContentLength(serialized.len() as u64)); - req.set_body(serialized); - - // send request - Box::new( - configuration.client.request(req) - .map_err(|e| Error::from(e)) - .and_then(|resp| { - let status = resp.status(); - resp.body().concat2() - .and_then(move |body| Ok((status, body))) - .map_err(|e| Error::from(e)) - }) - .and_then(|(status, body)| { - if status.is_success() { - Ok(body) - } else { - Err(Error::from((status, &*body))) - } - }) - .and_then(|_| futures::future::ok(())) - ) + __internal_request::Request::new(hyper::Method::Post, "/pet".to_string()) + .with_auth(__internal_request::Auth::Oauth) + .with_body_param(pet) + .returns_nothing() + .execute(self.configuration.borrow()) } fn delete_pet(&self, pet_id: i64, api_key: &str) -> Box>> { - let configuration: &configuration::Configuration = self.configuration.borrow(); - - let mut auth_headers = HashMap::::new(); - let mut auth_query = HashMap::::new(); - if let Some(ref token) = configuration.oauth_access_token { - let auth = hyper::header::Authorization( - hyper::header::Bearer { - token: token.to_owned(), - } - ); - auth_headers.insert("Authorization".to_owned(), auth.to_string()); - }; - let method = hyper::Method::Delete; - - let query_string = { - let mut query = ::url::form_urlencoded::Serializer::new(String::new()); - for (key, val) in &auth_query { - query.append_pair(key, val); - } - query.finish() - }; - let uri_str = format!("{}/pet/{petId}?{}", configuration.base_path, query_string, petId=pet_id); - - // TODO(farcaller): handle error - // if let Err(e) = uri { - // return Box::new(futures::future::err(e)); - // } - let mut uri: hyper::Uri = uri_str.parse().unwrap(); - - let mut req = hyper::Request::new(method, uri); - - if let Some(ref user_agent) = configuration.user_agent { - req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone()))); - } - - { - let mut headers = req.headers_mut(); - headers.set_raw("api_key", api_key); - } - - for (key, val) in auth_headers { - req.headers_mut().set_raw(key, val); - } - - - // send request - Box::new( - configuration.client.request(req) - .map_err(|e| Error::from(e)) - .and_then(|resp| { - let status = resp.status(); - resp.body().concat2() - .and_then(move |body| Ok((status, body))) - .map_err(|e| Error::from(e)) - }) - .and_then(|(status, body)| { - if status.is_success() { - Ok(body) - } else { - Err(Error::from((status, &*body))) - } - }) - .and_then(|_| futures::future::ok(())) - ) + __internal_request::Request::new(hyper::Method::Delete, "/pet/{petId}".to_string()) + .with_auth(__internal_request::Auth::Oauth) + .with_path_param("petId".to_string(), pet_id.to_string()) + .with_header_param("api_key".to_string(), api_key.to_string()) + .returns_nothing() + .execute(self.configuration.borrow()) } fn find_pets_by_status(&self, status: Vec) -> Box, Error = Error>> { - let configuration: &configuration::Configuration = self.configuration.borrow(); - - let mut auth_headers = HashMap::::new(); - let mut auth_query = HashMap::::new(); - if let Some(ref token) = configuration.oauth_access_token { - let auth = hyper::header::Authorization( - hyper::header::Bearer { - token: token.to_owned(), - } - ); - auth_headers.insert("Authorization".to_owned(), auth.to_string()); - }; - let method = hyper::Method::Get; - - let query_string = { - let mut query = ::url::form_urlencoded::Serializer::new(String::new()); - query.append_pair("status", &status.join(",").to_string()); - for (key, val) in &auth_query { - query.append_pair(key, val); - } - query.finish() - }; - let uri_str = format!("{}/pet/findByStatus?{}", configuration.base_path, query_string); - - // TODO(farcaller): handle error - // if let Err(e) = uri { - // return Box::new(futures::future::err(e)); - // } - let mut uri: hyper::Uri = uri_str.parse().unwrap(); - - let mut req = hyper::Request::new(method, uri); - - if let Some(ref user_agent) = configuration.user_agent { - req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone()))); - } - - - for (key, val) in auth_headers { - req.headers_mut().set_raw(key, val); - } - - - // send request - Box::new( - configuration.client.request(req) - .map_err(|e| Error::from(e)) - .and_then(|resp| { - let status = resp.status(); - resp.body().concat2() - .and_then(move |body| Ok((status, body))) - .map_err(|e| Error::from(e)) - }) - .and_then(|(status, body)| { - if status.is_success() { - Ok(body) - } else { - Err(Error::from((status, &*body))) - } - }) - .and_then(|body| { - let parsed: Result, _> = serde_json::from_slice(&body); - parsed.map_err(|e| Error::from(e)) - }) - ) + __internal_request::Request::new(hyper::Method::Get, "/pet/findByStatus".to_string()) + .with_auth(__internal_request::Auth::Oauth) + .with_query_param("status".to_string(), status.join(",").to_string()) + .execute(self.configuration.borrow()) } fn find_pets_by_tags(&self, tags: Vec) -> Box, Error = Error>> { - let configuration: &configuration::Configuration = self.configuration.borrow(); - - let mut auth_headers = HashMap::::new(); - let mut auth_query = HashMap::::new(); - if let Some(ref token) = configuration.oauth_access_token { - let auth = hyper::header::Authorization( - hyper::header::Bearer { - token: token.to_owned(), - } - ); - auth_headers.insert("Authorization".to_owned(), auth.to_string()); - }; - let method = hyper::Method::Get; - - let query_string = { - let mut query = ::url::form_urlencoded::Serializer::new(String::new()); - query.append_pair("tags", &tags.join(",").to_string()); - for (key, val) in &auth_query { - query.append_pair(key, val); - } - query.finish() - }; - let uri_str = format!("{}/pet/findByTags?{}", configuration.base_path, query_string); - - // TODO(farcaller): handle error - // if let Err(e) = uri { - // return Box::new(futures::future::err(e)); - // } - let mut uri: hyper::Uri = uri_str.parse().unwrap(); - - let mut req = hyper::Request::new(method, uri); - - if let Some(ref user_agent) = configuration.user_agent { - req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone()))); - } - - - for (key, val) in auth_headers { - req.headers_mut().set_raw(key, val); - } - - - // send request - Box::new( - configuration.client.request(req) - .map_err(|e| Error::from(e)) - .and_then(|resp| { - let status = resp.status(); - resp.body().concat2() - .and_then(move |body| Ok((status, body))) - .map_err(|e| Error::from(e)) - }) - .and_then(|(status, body)| { - if status.is_success() { - Ok(body) - } else { - Err(Error::from((status, &*body))) - } - }) - .and_then(|body| { - let parsed: Result, _> = serde_json::from_slice(&body); - parsed.map_err(|e| Error::from(e)) - }) - ) + __internal_request::Request::new(hyper::Method::Get, "/pet/findByTags".to_string()) + .with_auth(__internal_request::Auth::Oauth) + .with_query_param("tags".to_string(), tags.join(",").to_string()) + .execute(self.configuration.borrow()) } fn get_pet_by_id(&self, pet_id: i64) -> Box>> { - let configuration: &configuration::Configuration = self.configuration.borrow(); - - let mut auth_headers = HashMap::::new(); - let mut auth_query = HashMap::::new(); - if let Some(ref apikey) = configuration.api_key { - let key = apikey.key.clone(); - let val = match apikey.prefix { - Some(ref prefix) => format!("{} {}", prefix, key), - None => key, - }; - auth_headers.insert("api_key".to_owned(), val); - }; - let method = hyper::Method::Get; - - let query_string = { - let mut query = ::url::form_urlencoded::Serializer::new(String::new()); - for (key, val) in &auth_query { - query.append_pair(key, val); - } - query.finish() - }; - let uri_str = format!("{}/pet/{petId}?{}", configuration.base_path, query_string, petId=pet_id); - - // TODO(farcaller): handle error - // if let Err(e) = uri { - // return Box::new(futures::future::err(e)); - // } - let mut uri: hyper::Uri = uri_str.parse().unwrap(); - - let mut req = hyper::Request::new(method, uri); - - if let Some(ref user_agent) = configuration.user_agent { - req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone()))); - } - - - for (key, val) in auth_headers { - req.headers_mut().set_raw(key, val); - } - - - // send request - Box::new( - configuration.client.request(req) - .map_err(|e| Error::from(e)) - .and_then(|resp| { - let status = resp.status(); - resp.body().concat2() - .and_then(move |body| Ok((status, body))) - .map_err(|e| Error::from(e)) - }) - .and_then(|(status, body)| { - if status.is_success() { - Ok(body) - } else { - Err(Error::from((status, &*body))) - } - }) - .and_then(|body| { - let parsed: Result<::models::Pet, _> = serde_json::from_slice(&body); - parsed.map_err(|e| Error::from(e)) - }) - ) + __internal_request::Request::new(hyper::Method::Get, "/pet/{petId}".to_string()) + .with_auth(__internal_request::Auth::ApiKey(__internal_request::ApiKey{ + in_header: true, + in_query: false, + param_name: "api_key".to_owned(), + })) + .with_path_param("petId".to_string(), pet_id.to_string()) + .execute(self.configuration.borrow()) } fn update_pet(&self, pet: ::models::Pet) -> Box>> { - let configuration: &configuration::Configuration = self.configuration.borrow(); - - let mut auth_headers = HashMap::::new(); - let mut auth_query = HashMap::::new(); - if let Some(ref token) = configuration.oauth_access_token { - let auth = hyper::header::Authorization( - hyper::header::Bearer { - token: token.to_owned(), - } - ); - auth_headers.insert("Authorization".to_owned(), auth.to_string()); - }; - let method = hyper::Method::Put; - - let query_string = { - let mut query = ::url::form_urlencoded::Serializer::new(String::new()); - for (key, val) in &auth_query { - query.append_pair(key, val); - } - query.finish() - }; - let uri_str = format!("{}/pet?{}", configuration.base_path, query_string); - - // TODO(farcaller): handle error - // if let Err(e) = uri { - // return Box::new(futures::future::err(e)); - // } - let mut uri: hyper::Uri = uri_str.parse().unwrap(); - - let mut req = hyper::Request::new(method, uri); - - if let Some(ref user_agent) = configuration.user_agent { - req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone()))); - } - - - for (key, val) in auth_headers { - req.headers_mut().set_raw(key, val); - } - - let serialized = serde_json::to_string(&pet).unwrap(); - req.headers_mut().set(hyper::header::ContentType::json()); - req.headers_mut().set(hyper::header::ContentLength(serialized.len() as u64)); - req.set_body(serialized); - - // send request - Box::new( - configuration.client.request(req) - .map_err(|e| Error::from(e)) - .and_then(|resp| { - let status = resp.status(); - resp.body().concat2() - .and_then(move |body| Ok((status, body))) - .map_err(|e| Error::from(e)) - }) - .and_then(|(status, body)| { - if status.is_success() { - Ok(body) - } else { - Err(Error::from((status, &*body))) - } - }) - .and_then(|_| futures::future::ok(())) - ) + __internal_request::Request::new(hyper::Method::Put, "/pet".to_string()) + .with_auth(__internal_request::Auth::Oauth) + .with_body_param(pet) + .returns_nothing() + .execute(self.configuration.borrow()) } fn update_pet_with_form(&self, pet_id: i64, name: &str, status: &str) -> Box>> { - let configuration: &configuration::Configuration = self.configuration.borrow(); - - let mut auth_headers = HashMap::::new(); - let mut auth_query = HashMap::::new(); - if let Some(ref token) = configuration.oauth_access_token { - let auth = hyper::header::Authorization( - hyper::header::Bearer { - token: token.to_owned(), - } - ); - auth_headers.insert("Authorization".to_owned(), auth.to_string()); - }; - let method = hyper::Method::Post; - - let query_string = { - let mut query = ::url::form_urlencoded::Serializer::new(String::new()); - for (key, val) in &auth_query { - query.append_pair(key, val); - } - query.finish() - }; - let uri_str = format!("{}/pet/{petId}?{}", configuration.base_path, query_string, petId=pet_id); - - // TODO(farcaller): handle error - // if let Err(e) = uri { - // return Box::new(futures::future::err(e)); - // } - let mut uri: hyper::Uri = uri_str.parse().unwrap(); - - let mut req = hyper::Request::new(method, uri); - - if let Some(ref user_agent) = configuration.user_agent { - req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone()))); - } - - - for (key, val) in auth_headers { - req.headers_mut().set_raw(key, val); - } - - - // send request - Box::new( - configuration.client.request(req) - .map_err(|e| Error::from(e)) - .and_then(|resp| { - let status = resp.status(); - resp.body().concat2() - .and_then(move |body| Ok((status, body))) - .map_err(|e| Error::from(e)) - }) - .and_then(|(status, body)| { - if status.is_success() { - Ok(body) - } else { - Err(Error::from((status, &*body))) - } - }) - .and_then(|_| futures::future::ok(())) - ) + __internal_request::Request::new(hyper::Method::Post, "/pet/{petId}".to_string()) + .with_auth(__internal_request::Auth::Oauth) + .with_path_param("petId".to_string(), pet_id.to_string()) + .with_form_param("name".to_string(), name.to_string()) + .with_form_param("status".to_string(), status.to_string()) + .returns_nothing() + .execute(self.configuration.borrow()) } fn upload_file(&self, pet_id: i64, additional_metadata: &str, file: ::models::File) -> Box>> { - let configuration: &configuration::Configuration = self.configuration.borrow(); - - let mut auth_headers = HashMap::::new(); - let mut auth_query = HashMap::::new(); - if let Some(ref token) = configuration.oauth_access_token { - let auth = hyper::header::Authorization( - hyper::header::Bearer { - token: token.to_owned(), - } - ); - auth_headers.insert("Authorization".to_owned(), auth.to_string()); - }; - let method = hyper::Method::Post; - - let query_string = { - let mut query = ::url::form_urlencoded::Serializer::new(String::new()); - for (key, val) in &auth_query { - query.append_pair(key, val); - } - query.finish() - }; - let uri_str = format!("{}/pet/{petId}/uploadImage?{}", configuration.base_path, query_string, petId=pet_id); - - // TODO(farcaller): handle error - // if let Err(e) = uri { - // return Box::new(futures::future::err(e)); - // } - let mut uri: hyper::Uri = uri_str.parse().unwrap(); - - let mut req = hyper::Request::new(method, uri); - - if let Some(ref user_agent) = configuration.user_agent { - req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone()))); - } - - - for (key, val) in auth_headers { - req.headers_mut().set_raw(key, val); - } - - - // send request - Box::new( - configuration.client.request(req) - .map_err(|e| Error::from(e)) - .and_then(|resp| { - let status = resp.status(); - resp.body().concat2() - .and_then(move |body| Ok((status, body))) - .map_err(|e| Error::from(e)) - }) - .and_then(|(status, body)| { - if status.is_success() { - Ok(body) - } else { - Err(Error::from((status, &*body))) - } - }) - .and_then(|body| { - let parsed: Result<::models::ApiResponse, _> = serde_json::from_slice(&body); - parsed.map_err(|e| Error::from(e)) - }) - ) + __internal_request::Request::new(hyper::Method::Post, "/pet/{petId}/uploadImage".to_string()) + .with_auth(__internal_request::Auth::Oauth) + .with_path_param("petId".to_string(), pet_id.to_string()) + .execute(self.configuration.borrow()) } } diff --git a/samples/client/petstore/rust/src/apis/request.rs b/samples/client/petstore/rust/src/apis/request.rs new file mode 100644 index 000000000000..2b996d79703d --- /dev/null +++ b/samples/client/petstore/rust/src/apis/request.rs @@ -0,0 +1,227 @@ +use std::borrow::Cow; +use std::collections::HashMap; + +use super::{configuration, Error}; +use futures; +use futures::{Future, Stream}; +use hyper; +use hyper::header::UserAgent; +use serde; +use serde_json; + +pub(crate) struct ApiKey { + pub in_header: bool, + pub in_query: bool, + pub param_name: String, +} + +impl ApiKey { + fn key(&self, prefix: &Option, key: &str) -> String { + match prefix { + None => key.to_owned(), + Some(ref prefix) => format!("{} {}", prefix, key), + } + } +} + +pub(crate) enum Auth { + None, + ApiKey(ApiKey), + Basic, + Oauth, +} + +pub(crate) struct Request { + auth: Auth, + method: hyper::Method, + path: String, + query_params: HashMap, + no_return_type: bool, + path_params: HashMap, + header_params: HashMap, + // TODO: multiple body params are possible technically, but not supported here. + serialized_body: Option, +} + +impl Request { + pub fn new(method: hyper::Method, path: String) -> Self { + Request { + auth: Auth::None, + method: method, + path: path, + query_params: HashMap::new(), + path_params: HashMap::new(), + header_params: HashMap::new(), + serialized_body: None, + no_return_type: false, + } + } + + pub fn with_body_param(mut self, param: T) -> Self { + self.serialized_body = Some(serde_json::to_string(¶m).unwrap()); + self + } + + pub fn with_header_param(mut self, basename: String, param: String) -> Self { + self.header_params.insert(basename, param); + self + } + + pub fn with_query_param(mut self, basename: String, param: String) -> Self { + self.query_params.insert(basename, param); + self + } + + pub fn with_path_param(mut self, basename: String, param: String) -> Self { + self.path_params.insert(basename, param); + self + } + + pub fn with_form_param(mut self, basename: String, param: String) -> Self { + self.form_params.insert(basename, param); + self + } + + pub fn returns_nothing(mut self) -> Self { + self.no_return_type = true; + self + } + + pub fn with_auth(mut self, auth: Auth) -> Self { + self.auth = auth; + self + } + + pub fn execute<'a, C, U>( + self, + conf: &configuration::Configuration, + ) -> Box> + 'a> + where + C: hyper::client::Connect, + U: Sized + 'a, + for<'de> U: serde::Deserialize<'de>, + { + let mut query_string = ::url::form_urlencoded::Serializer::new("".to_owned()); + // raw_headers is for headers we don't know the proper type of (e.g. custom api key + // headers); headers is for ones we do know the type of. + let mut raw_headers = HashMap::new(); + let mut headers: hyper::header::Headers = hyper::header::Headers::new(); + + let mut path = self.path; + for (k, v) in self.path_params { + // replace {id} with the value of the id path param + path = path.replace(&format!("{{{}}}", k), &v); + } + + for (k, v) in self.header_params { + raw_headers.insert(k, v); + } + + for (key, val) in self.query_params { + query_string.append_pair(&key, &val); + } + + match self.auth { + Auth::ApiKey(apikey) => { + if let Some(ref key) = conf.api_key { + let val = apikey.key(&key.prefix, &key.key); + if apikey.in_query { + query_string.append_pair(&apikey.param_name, &val); + } + if apikey.in_header { + raw_headers.insert(apikey.param_name, val); + } + } + } + Auth::Basic => { + if let Some(ref auth_conf) = conf.basic_auth { + let auth = hyper::header::Authorization(hyper::header::Basic { + username: auth_conf.0.to_owned(), + password: auth_conf.1.to_owned(), + }); + headers.set(auth); + } + } + Auth::Oauth => { + if let Some(ref token) = conf.oauth_access_token { + let auth = hyper::header::Authorization(hyper::header::Bearer { + token: token.to_owned(), + }); + headers.set(auth); + } + } + Auth::None => {} + } + + let mut uri_str = format!("{}{}", conf.base_path, path); + + let query_string_str = query_string.finish(); + if query_string_str != "" { + uri_str += "?"; + uri_str += &query_string_str; + } + let uri: hyper::Uri = match uri_str.parse() { + Err(e) => { + return Box::new(futures::future::err(Error::UriError(e))); + } + Ok(u) => u, + }; + + let mut req = hyper::Request::new(self.method, uri); + { + let req_headers = req.headers_mut(); + if let Some(ref user_agent) = conf.user_agent { + req_headers.set(UserAgent::new(Cow::Owned(user_agent.clone()))); + } + + req_headers.extend(headers.iter()); + + for (key, val) in raw_headers { + req_headers.set_raw(key, val); + } + } + + if let Some(body) = self.serialized_body { + req.headers_mut().set(hyper::header::ContentType::json()); + req.headers_mut() + .set(hyper::header::ContentLength(body.len() as u64)); + req.set_body(body); + } + + let no_ret_type = self.no_return_type; + let res = conf.client + .request(req) + .map_err(|e| Error::from(e)) + .and_then(|resp| { + let status = resp.status(); + resp.body() + .concat2() + .and_then(move |body| Ok((status, body))) + .map_err(|e| Error::from(e)) + }) + .and_then(|(status, body)| { + if status.is_success() { + Ok(body) + } else { + Err(Error::from((status, &*body))) + } + }); + Box::new( + res + .and_then(move |body| { + let parsed: Result = if no_ret_type { + // This is a hack; if there's no_ret_type, U is (), but serde_json gives an + // error when deserializing "" into (), so deserialize 'null' into it + // instead. + // An alternate option would be to require U: Default, and then return + // U::default() here instead since () implements that, but then we'd + // need to impl default for all models. + serde_json::from_str("null") + } else { + serde_json::from_slice(&body) + }; + parsed.map_err(|e| Error::from(e)) + }) + ) + } +} diff --git a/samples/client/petstore/rust/src/apis/store_api.rs b/samples/client/petstore/rust/src/apis/store_api.rs index e6e92e8a90aa..dc05931697d6 100644 --- a/samples/client/petstore/rust/src/apis/store_api.rs +++ b/samples/client/petstore/rust/src/apis/store_api.rs @@ -10,17 +10,13 @@ use std::rc::Rc; use std::borrow::Borrow; -use std::borrow::Cow; -use std::collections::HashMap; use hyper; use serde_json; -use futures; -use futures::{Future, Stream}; - -use hyper::header::UserAgent; +use futures::Future; use super::{Error, configuration}; +use super::request as __internal_request; pub struct StoreApiClient { configuration: Rc>, @@ -44,220 +40,32 @@ pub trait StoreApi { implStoreApi for StoreApiClient { fn delete_order(&self, order_id: &str) -> Box>> { - let configuration: &configuration::Configuration = self.configuration.borrow(); - - let method = hyper::Method::Delete; - - let query_string = { - let mut query = ::url::form_urlencoded::Serializer::new(String::new()); - query.finish() - }; - let uri_str = format!("{}/store/order/{orderId}?{}", configuration.base_path, query_string, orderId=order_id); - - // TODO(farcaller): handle error - // if let Err(e) = uri { - // return Box::new(futures::future::err(e)); - // } - let mut uri: hyper::Uri = uri_str.parse().unwrap(); - - let mut req = hyper::Request::new(method, uri); - - if let Some(ref user_agent) = configuration.user_agent { - req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone()))); - } - - - - - // send request - Box::new( - configuration.client.request(req) - .map_err(|e| Error::from(e)) - .and_then(|resp| { - let status = resp.status(); - resp.body().concat2() - .and_then(move |body| Ok((status, body))) - .map_err(|e| Error::from(e)) - }) - .and_then(|(status, body)| { - if status.is_success() { - Ok(body) - } else { - Err(Error::from((status, &*body))) - } - }) - .and_then(|_| futures::future::ok(())) - ) + __internal_request::Request::new(hyper::Method::Delete, "/store/order/{orderId}".to_string()) + .with_path_param("orderId".to_string(), order_id.to_string()) + .returns_nothing() + .execute(self.configuration.borrow()) } fn get_inventory(&self, ) -> Box, Error = Error>> { - let configuration: &configuration::Configuration = self.configuration.borrow(); - - let mut auth_headers = HashMap::::new(); - let mut auth_query = HashMap::::new(); - if let Some(ref apikey) = configuration.api_key { - let key = apikey.key.clone(); - let val = match apikey.prefix { - Some(ref prefix) => format!("{} {}", prefix, key), - None => key, - }; - auth_headers.insert("api_key".to_owned(), val); - }; - let method = hyper::Method::Get; - - let query_string = { - let mut query = ::url::form_urlencoded::Serializer::new(String::new()); - for (key, val) in &auth_query { - query.append_pair(key, val); - } - query.finish() - }; - let uri_str = format!("{}/store/inventory?{}", configuration.base_path, query_string); - - // TODO(farcaller): handle error - // if let Err(e) = uri { - // return Box::new(futures::future::err(e)); - // } - let mut uri: hyper::Uri = uri_str.parse().unwrap(); - - let mut req = hyper::Request::new(method, uri); - - if let Some(ref user_agent) = configuration.user_agent { - req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone()))); - } - - - for (key, val) in auth_headers { - req.headers_mut().set_raw(key, val); - } - - - // send request - Box::new( - configuration.client.request(req) - .map_err(|e| Error::from(e)) - .and_then(|resp| { - let status = resp.status(); - resp.body().concat2() - .and_then(move |body| Ok((status, body))) - .map_err(|e| Error::from(e)) - }) - .and_then(|(status, body)| { - if status.is_success() { - Ok(body) - } else { - Err(Error::from((status, &*body))) - } - }) - .and_then(|body| { - let parsed: Result<::std::collections::HashMap, _> = serde_json::from_slice(&body); - parsed.map_err(|e| Error::from(e)) - }) - ) + __internal_request::Request::new(hyper::Method::Get, "/store/inventory".to_string()) + .with_auth(__internal_request::Auth::ApiKey(__internal_request::ApiKey{ + in_header: true, + in_query: false, + param_name: "api_key".to_owned(), + })) + .execute(self.configuration.borrow()) } fn get_order_by_id(&self, order_id: i64) -> Box>> { - let configuration: &configuration::Configuration = self.configuration.borrow(); - - let method = hyper::Method::Get; - - let query_string = { - let mut query = ::url::form_urlencoded::Serializer::new(String::new()); - query.finish() - }; - let uri_str = format!("{}/store/order/{orderId}?{}", configuration.base_path, query_string, orderId=order_id); - - // TODO(farcaller): handle error - // if let Err(e) = uri { - // return Box::new(futures::future::err(e)); - // } - let mut uri: hyper::Uri = uri_str.parse().unwrap(); - - let mut req = hyper::Request::new(method, uri); - - if let Some(ref user_agent) = configuration.user_agent { - req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone()))); - } - - - - - // send request - Box::new( - configuration.client.request(req) - .map_err(|e| Error::from(e)) - .and_then(|resp| { - let status = resp.status(); - resp.body().concat2() - .and_then(move |body| Ok((status, body))) - .map_err(|e| Error::from(e)) - }) - .and_then(|(status, body)| { - if status.is_success() { - Ok(body) - } else { - Err(Error::from((status, &*body))) - } - }) - .and_then(|body| { - let parsed: Result<::models::Order, _> = serde_json::from_slice(&body); - parsed.map_err(|e| Error::from(e)) - }) - ) + __internal_request::Request::new(hyper::Method::Get, "/store/order/{orderId}".to_string()) + .with_path_param("orderId".to_string(), order_id.to_string()) + .execute(self.configuration.borrow()) } fn place_order(&self, order: ::models::Order) -> Box>> { - let configuration: &configuration::Configuration = self.configuration.borrow(); - - let method = hyper::Method::Post; - - let query_string = { - let mut query = ::url::form_urlencoded::Serializer::new(String::new()); - query.finish() - }; - let uri_str = format!("{}/store/order?{}", configuration.base_path, query_string); - - // TODO(farcaller): handle error - // if let Err(e) = uri { - // return Box::new(futures::future::err(e)); - // } - let mut uri: hyper::Uri = uri_str.parse().unwrap(); - - let mut req = hyper::Request::new(method, uri); - - if let Some(ref user_agent) = configuration.user_agent { - req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone()))); - } - - - - let serialized = serde_json::to_string(&order).unwrap(); - req.headers_mut().set(hyper::header::ContentType::json()); - req.headers_mut().set(hyper::header::ContentLength(serialized.len() as u64)); - req.set_body(serialized); - - // send request - Box::new( - configuration.client.request(req) - .map_err(|e| Error::from(e)) - .and_then(|resp| { - let status = resp.status(); - resp.body().concat2() - .and_then(move |body| Ok((status, body))) - .map_err(|e| Error::from(e)) - }) - .and_then(|(status, body)| { - if status.is_success() { - Ok(body) - } else { - Err(Error::from((status, &*body))) - } - }) - .and_then(|body| { - let parsed: Result<::models::Order, _> = serde_json::from_slice(&body); - parsed.map_err(|e| Error::from(e)) - }) - ) + __internal_request::Request::new(hyper::Method::Post, "/store/order".to_string()) + .with_body_param(order) + .execute(self.configuration.borrow()) } } diff --git a/samples/client/petstore/rust/src/apis/user_api.rs b/samples/client/petstore/rust/src/apis/user_api.rs index 60646085a533..f0976f80ee1f 100644 --- a/samples/client/petstore/rust/src/apis/user_api.rs +++ b/samples/client/petstore/rust/src/apis/user_api.rs @@ -10,17 +10,13 @@ use std::rc::Rc; use std::borrow::Borrow; -use std::borrow::Cow; -use std::collections::HashMap; use hyper; use serde_json; -use futures; -use futures::{Future, Stream}; - -use hyper::header::UserAgent; +use futures::Future; use super::{Error, configuration}; +use super::request as __internal_request; pub struct UserApiClient { configuration: Rc>, @@ -48,403 +44,58 @@ pub trait UserApi { implUserApi for UserApiClient { fn create_user(&self, user: ::models::User) -> Box>> { - let configuration: &configuration::Configuration = self.configuration.borrow(); - - let method = hyper::Method::Post; - - let query_string = { - let mut query = ::url::form_urlencoded::Serializer::new(String::new()); - query.finish() - }; - let uri_str = format!("{}/user?{}", configuration.base_path, query_string); - - // TODO(farcaller): handle error - // if let Err(e) = uri { - // return Box::new(futures::future::err(e)); - // } - let mut uri: hyper::Uri = uri_str.parse().unwrap(); - - let mut req = hyper::Request::new(method, uri); - - if let Some(ref user_agent) = configuration.user_agent { - req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone()))); - } - - - - let serialized = serde_json::to_string(&user).unwrap(); - req.headers_mut().set(hyper::header::ContentType::json()); - req.headers_mut().set(hyper::header::ContentLength(serialized.len() as u64)); - req.set_body(serialized); - - // send request - Box::new( - configuration.client.request(req) - .map_err(|e| Error::from(e)) - .and_then(|resp| { - let status = resp.status(); - resp.body().concat2() - .and_then(move |body| Ok((status, body))) - .map_err(|e| Error::from(e)) - }) - .and_then(|(status, body)| { - if status.is_success() { - Ok(body) - } else { - Err(Error::from((status, &*body))) - } - }) - .and_then(|_| futures::future::ok(())) - ) + __internal_request::Request::new(hyper::Method::Post, "/user".to_string()) + .with_body_param(user) + .returns_nothing() + .execute(self.configuration.borrow()) } fn create_users_with_array_input(&self, user: Vec<::models::User>) -> Box>> { - let configuration: &configuration::Configuration = self.configuration.borrow(); - - let method = hyper::Method::Post; - - let query_string = { - let mut query = ::url::form_urlencoded::Serializer::new(String::new()); - query.finish() - }; - let uri_str = format!("{}/user/createWithArray?{}", configuration.base_path, query_string); - - // TODO(farcaller): handle error - // if let Err(e) = uri { - // return Box::new(futures::future::err(e)); - // } - let mut uri: hyper::Uri = uri_str.parse().unwrap(); - - let mut req = hyper::Request::new(method, uri); - - if let Some(ref user_agent) = configuration.user_agent { - req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone()))); - } - - - - let serialized = serde_json::to_string(&user).unwrap(); - req.headers_mut().set(hyper::header::ContentType::json()); - req.headers_mut().set(hyper::header::ContentLength(serialized.len() as u64)); - req.set_body(serialized); - - // send request - Box::new( - configuration.client.request(req) - .map_err(|e| Error::from(e)) - .and_then(|resp| { - let status = resp.status(); - resp.body().concat2() - .and_then(move |body| Ok((status, body))) - .map_err(|e| Error::from(e)) - }) - .and_then(|(status, body)| { - if status.is_success() { - Ok(body) - } else { - Err(Error::from((status, &*body))) - } - }) - .and_then(|_| futures::future::ok(())) - ) + __internal_request::Request::new(hyper::Method::Post, "/user/createWithArray".to_string()) + .with_body_param(user) + .returns_nothing() + .execute(self.configuration.borrow()) } fn create_users_with_list_input(&self, user: Vec<::models::User>) -> Box>> { - let configuration: &configuration::Configuration = self.configuration.borrow(); - - let method = hyper::Method::Post; - - let query_string = { - let mut query = ::url::form_urlencoded::Serializer::new(String::new()); - query.finish() - }; - let uri_str = format!("{}/user/createWithList?{}", configuration.base_path, query_string); - - // TODO(farcaller): handle error - // if let Err(e) = uri { - // return Box::new(futures::future::err(e)); - // } - let mut uri: hyper::Uri = uri_str.parse().unwrap(); - - let mut req = hyper::Request::new(method, uri); - - if let Some(ref user_agent) = configuration.user_agent { - req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone()))); - } - - - - let serialized = serde_json::to_string(&user).unwrap(); - req.headers_mut().set(hyper::header::ContentType::json()); - req.headers_mut().set(hyper::header::ContentLength(serialized.len() as u64)); - req.set_body(serialized); - - // send request - Box::new( - configuration.client.request(req) - .map_err(|e| Error::from(e)) - .and_then(|resp| { - let status = resp.status(); - resp.body().concat2() - .and_then(move |body| Ok((status, body))) - .map_err(|e| Error::from(e)) - }) - .and_then(|(status, body)| { - if status.is_success() { - Ok(body) - } else { - Err(Error::from((status, &*body))) - } - }) - .and_then(|_| futures::future::ok(())) - ) + __internal_request::Request::new(hyper::Method::Post, "/user/createWithList".to_string()) + .with_body_param(user) + .returns_nothing() + .execute(self.configuration.borrow()) } fn delete_user(&self, username: &str) -> Box>> { - let configuration: &configuration::Configuration = self.configuration.borrow(); - - let method = hyper::Method::Delete; - - let query_string = { - let mut query = ::url::form_urlencoded::Serializer::new(String::new()); - query.finish() - }; - let uri_str = format!("{}/user/{username}?{}", configuration.base_path, query_string, username=username); - - // TODO(farcaller): handle error - // if let Err(e) = uri { - // return Box::new(futures::future::err(e)); - // } - let mut uri: hyper::Uri = uri_str.parse().unwrap(); - - let mut req = hyper::Request::new(method, uri); - - if let Some(ref user_agent) = configuration.user_agent { - req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone()))); - } - - - - - // send request - Box::new( - configuration.client.request(req) - .map_err(|e| Error::from(e)) - .and_then(|resp| { - let status = resp.status(); - resp.body().concat2() - .and_then(move |body| Ok((status, body))) - .map_err(|e| Error::from(e)) - }) - .and_then(|(status, body)| { - if status.is_success() { - Ok(body) - } else { - Err(Error::from((status, &*body))) - } - }) - .and_then(|_| futures::future::ok(())) - ) + __internal_request::Request::new(hyper::Method::Delete, "/user/{username}".to_string()) + .with_path_param("username".to_string(), username.to_string()) + .returns_nothing() + .execute(self.configuration.borrow()) } fn get_user_by_name(&self, username: &str) -> Box>> { - let configuration: &configuration::Configuration = self.configuration.borrow(); - - let method = hyper::Method::Get; - - let query_string = { - let mut query = ::url::form_urlencoded::Serializer::new(String::new()); - query.finish() - }; - let uri_str = format!("{}/user/{username}?{}", configuration.base_path, query_string, username=username); - - // TODO(farcaller): handle error - // if let Err(e) = uri { - // return Box::new(futures::future::err(e)); - // } - let mut uri: hyper::Uri = uri_str.parse().unwrap(); - - let mut req = hyper::Request::new(method, uri); - - if let Some(ref user_agent) = configuration.user_agent { - req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone()))); - } - - - - - // send request - Box::new( - configuration.client.request(req) - .map_err(|e| Error::from(e)) - .and_then(|resp| { - let status = resp.status(); - resp.body().concat2() - .and_then(move |body| Ok((status, body))) - .map_err(|e| Error::from(e)) - }) - .and_then(|(status, body)| { - if status.is_success() { - Ok(body) - } else { - Err(Error::from((status, &*body))) - } - }) - .and_then(|body| { - let parsed: Result<::models::User, _> = serde_json::from_slice(&body); - parsed.map_err(|e| Error::from(e)) - }) - ) + __internal_request::Request::new(hyper::Method::Get, "/user/{username}".to_string()) + .with_path_param("username".to_string(), username.to_string()) + .execute(self.configuration.borrow()) } fn login_user(&self, username: &str, password: &str) -> Box>> { - let configuration: &configuration::Configuration = self.configuration.borrow(); - - let method = hyper::Method::Get; - - let query_string = { - let mut query = ::url::form_urlencoded::Serializer::new(String::new()); - query.append_pair("username", &username.to_string()); - query.append_pair("password", &password.to_string()); - query.finish() - }; - let uri_str = format!("{}/user/login?{}", configuration.base_path, query_string); - - // TODO(farcaller): handle error - // if let Err(e) = uri { - // return Box::new(futures::future::err(e)); - // } - let mut uri: hyper::Uri = uri_str.parse().unwrap(); - - let mut req = hyper::Request::new(method, uri); - - if let Some(ref user_agent) = configuration.user_agent { - req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone()))); - } - - - - - // send request - Box::new( - configuration.client.request(req) - .map_err(|e| Error::from(e)) - .and_then(|resp| { - let status = resp.status(); - resp.body().concat2() - .and_then(move |body| Ok((status, body))) - .map_err(|e| Error::from(e)) - }) - .and_then(|(status, body)| { - if status.is_success() { - Ok(body) - } else { - Err(Error::from((status, &*body))) - } - }) - .and_then(|body| { - let parsed: Result = serde_json::from_slice(&body); - parsed.map_err(|e| Error::from(e)) - }) - ) + __internal_request::Request::new(hyper::Method::Get, "/user/login".to_string()) + .with_query_param("username".to_string(), username.to_string()) + .with_query_param("password".to_string(), password.to_string()) + .execute(self.configuration.borrow()) } fn logout_user(&self, ) -> Box>> { - let configuration: &configuration::Configuration = self.configuration.borrow(); - - let method = hyper::Method::Get; - - let query_string = { - let mut query = ::url::form_urlencoded::Serializer::new(String::new()); - query.finish() - }; - let uri_str = format!("{}/user/logout?{}", configuration.base_path, query_string); - - // TODO(farcaller): handle error - // if let Err(e) = uri { - // return Box::new(futures::future::err(e)); - // } - let mut uri: hyper::Uri = uri_str.parse().unwrap(); - - let mut req = hyper::Request::new(method, uri); - - if let Some(ref user_agent) = configuration.user_agent { - req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone()))); - } - - - - - // send request - Box::new( - configuration.client.request(req) - .map_err(|e| Error::from(e)) - .and_then(|resp| { - let status = resp.status(); - resp.body().concat2() - .and_then(move |body| Ok((status, body))) - .map_err(|e| Error::from(e)) - }) - .and_then(|(status, body)| { - if status.is_success() { - Ok(body) - } else { - Err(Error::from((status, &*body))) - } - }) - .and_then(|_| futures::future::ok(())) - ) + __internal_request::Request::new(hyper::Method::Get, "/user/logout".to_string()) + .returns_nothing() + .execute(self.configuration.borrow()) } fn update_user(&self, username: &str, user: ::models::User) -> Box>> { - let configuration: &configuration::Configuration = self.configuration.borrow(); - - let method = hyper::Method::Put; - - let query_string = { - let mut query = ::url::form_urlencoded::Serializer::new(String::new()); - query.finish() - }; - let uri_str = format!("{}/user/{username}?{}", configuration.base_path, query_string, username=username); - - // TODO(farcaller): handle error - // if let Err(e) = uri { - // return Box::new(futures::future::err(e)); - // } - let mut uri: hyper::Uri = uri_str.parse().unwrap(); - - let mut req = hyper::Request::new(method, uri); - - if let Some(ref user_agent) = configuration.user_agent { - req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone()))); - } - - - - let serialized = serde_json::to_string(&user).unwrap(); - req.headers_mut().set(hyper::header::ContentType::json()); - req.headers_mut().set(hyper::header::ContentLength(serialized.len() as u64)); - req.set_body(serialized); - - // send request - Box::new( - configuration.client.request(req) - .map_err(|e| Error::from(e)) - .and_then(|resp| { - let status = resp.status(); - resp.body().concat2() - .and_then(move |body| Ok((status, body))) - .map_err(|e| Error::from(e)) - }) - .and_then(|(status, body)| { - if status.is_success() { - Ok(body) - } else { - Err(Error::from((status, &*body))) - } - }) - .and_then(|_| futures::future::ok(())) - ) + __internal_request::Request::new(hyper::Method::Put, "/user/{username}".to_string()) + .with_path_param("username".to_string(), username.to_string()) + .with_body_param(user) + .returns_nothing() + .execute(self.configuration.borrow()) } } From 6a31ef533123150b3b257311f77c8a8c474cad5a Mon Sep 17 00:00:00 2001 From: Euan Kemp Date: Tue, 10 Jul 2018 00:31:29 -0700 Subject: [PATCH 2/3] [Rust] Add support for non-file form params Up until now, they just weren't there at all --- .../src/main/resources/rust/api.mustache | 10 ++++++++++ .../src/main/resources/rust/request.rs | 11 +++++++++++ samples/client/petstore/rust/src/apis/pet_api.rs | 2 ++ samples/client/petstore/rust/src/apis/request.rs | 11 +++++++++++ 4 files changed, 34 insertions(+) diff --git a/modules/openapi-generator/src/main/resources/rust/api.mustache b/modules/openapi-generator/src/main/resources/rust/api.mustache index eca462527dbd..3e59a5839dbc 100644 --- a/modules/openapi-generator/src/main/resources/rust/api.mustache +++ b/modules/openapi-generator/src/main/resources/rust/api.mustache @@ -63,6 +63,16 @@ impl{{classname}} for {{classname}}Client { .with_header_param("{{baseName}}".to_string(), {{paramName}}{{#isListContainer}}.join(","){{/isListContainer}}.to_string()) {{/headerParams}} {{/hasHeaderParams}} + {{#hasFormParams}} + {{#formParams}} + {{#isFile}} + .with_form_param("{{baseName}}".to_string(), unimplemented!()) + {{/isFile}} + {{^isFile}} + .with_form_param("{{baseName}}".to_string(), {{paramName}}{{#isListContainer}}.join(","){{/isListContainer}}.to_string()) + {{/isFile}} + {{/formParams}} + {{/hasFormParams}} {{#hasBodyParam}} {{#bodyParams}} .with_body_param({{paramName}}) diff --git a/modules/openapi-generator/src/main/resources/rust/request.rs b/modules/openapi-generator/src/main/resources/rust/request.rs index 2b996d79703d..383a409542b1 100644 --- a/modules/openapi-generator/src/main/resources/rust/request.rs +++ b/modules/openapi-generator/src/main/resources/rust/request.rs @@ -38,6 +38,7 @@ pub(crate) struct Request { query_params: HashMap, no_return_type: bool, path_params: HashMap, + form_params: HashMap, header_params: HashMap, // TODO: multiple body params are possible technically, but not supported here. serialized_body: Option, @@ -51,6 +52,7 @@ impl Request { path: path, query_params: HashMap::new(), path_params: HashMap::new(), + form_params: HashMap::new(), header_params: HashMap::new(), serialized_body: None, no_return_type: false, @@ -181,6 +183,15 @@ impl Request { } } + if self.form_params.len() > 0 { + req.headers_mut().set(hyper::header::ContentType::form_url_encoded()); + let mut enc = ::url::form_urlencoded::Serializer::new("".to_owned()); + for (k, v) in self.form_params { + enc.append_pair(&k, &v); + } + req.set_body(enc.finish()); + } + if let Some(body) = self.serialized_body { req.headers_mut().set(hyper::header::ContentType::json()); req.headers_mut() diff --git a/samples/client/petstore/rust/src/apis/pet_api.rs b/samples/client/petstore/rust/src/apis/pet_api.rs index f46dccfb9e51..0e8a803c5597 100644 --- a/samples/client/petstore/rust/src/apis/pet_api.rs +++ b/samples/client/petstore/rust/src/apis/pet_api.rs @@ -107,6 +107,8 @@ implPetApi for PetApiClient { __internal_request::Request::new(hyper::Method::Post, "/pet/{petId}/uploadImage".to_string()) .with_auth(__internal_request::Auth::Oauth) .with_path_param("petId".to_string(), pet_id.to_string()) + .with_form_param("additionalMetadata".to_string(), additional_metadata.to_string()) + .with_form_param("file".to_string(), unimplemented!()) .execute(self.configuration.borrow()) } diff --git a/samples/client/petstore/rust/src/apis/request.rs b/samples/client/petstore/rust/src/apis/request.rs index 2b996d79703d..383a409542b1 100644 --- a/samples/client/petstore/rust/src/apis/request.rs +++ b/samples/client/petstore/rust/src/apis/request.rs @@ -38,6 +38,7 @@ pub(crate) struct Request { query_params: HashMap, no_return_type: bool, path_params: HashMap, + form_params: HashMap, header_params: HashMap, // TODO: multiple body params are possible technically, but not supported here. serialized_body: Option, @@ -51,6 +52,7 @@ impl Request { path: path, query_params: HashMap::new(), path_params: HashMap::new(), + form_params: HashMap::new(), header_params: HashMap::new(), serialized_body: None, no_return_type: false, @@ -181,6 +183,15 @@ impl Request { } } + if self.form_params.len() > 0 { + req.headers_mut().set(hyper::header::ContentType::form_url_encoded()); + let mut enc = ::url::form_urlencoded::Serializer::new("".to_owned()); + for (k, v) in self.form_params { + enc.append_pair(&k, &v); + } + req.set_body(enc.finish()); + } + if let Some(body) = self.serialized_body { req.headers_mut().set(hyper::header::ContentType::json()); req.headers_mut() From 546f510db023ffcabb65e3749c9c5205abf3f746 Mon Sep 17 00:00:00 2001 From: Euan Kemp Date: Tue, 10 Jul 2018 12:36:04 -0700 Subject: [PATCH 3/3] [Rust] Use more rustic terms in example --- samples/client/petstore/rust/examples/client.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/client/petstore/rust/examples/client.rs b/samples/client/petstore/rust/examples/client.rs index b406ba718845..a729ec297c50 100644 --- a/samples/client/petstore/rust/examples/client.rs +++ b/samples/client/petstore/rust/examples/client.rs @@ -20,16 +20,16 @@ fn main() { ), ); - let new_pet = petstore_client::models::Pet::new("barker".to_owned(), vec![]).with_id(1337); + let new_pet = petstore_client::models::Pet::new("ferris".to_owned(), vec![]).with_id(128149); let work = apicli .pet_api() .add_pet(new_pet) .and_then(|_| { apicli .pet_api() - .update_pet_with_form(1337, "barko", "escaped") + .update_pet_with_form(128149, "ferris", "rusted") }) - .and_then(|_| apicli.pet_api().get_pet_by_id(1337)) + .and_then(|_| apicli.pet_api().get_pet_by_id(128149)) .and_then(|pet| { println!("pet: {:?}", pet); futures::future::ok(())