Skip to content

Commit 2e6bec7

Browse files
euankwing328
authored andcommitted
[Rust] Split out request logic, implement form parameters (#528)
* [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. * [Rust] Add support for non-file form params Up until now, they just weren't there at all * [Rust] Use more rustic terms in example
1 parent a9961a0 commit 2e6bec7

12 files changed

Lines changed: 636 additions & 1238 deletions

File tree

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustClientCodegen.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,9 @@ public void processOpts() {
165165
supportingFiles.add(new SupportingFile("configuration.mustache", apiFolder, "configuration.rs"));
166166
supportingFiles.add(new SupportingFile(".travis.yml", "", ".travis.yml"));
167167

168-
supportingFiles.add(new SupportingFile("client.mustache", apiFolder, "client.rs"));
169168
supportingFiles.add(new SupportingFile("api_mod.mustache", apiFolder, "mod.rs"));
169+
supportingFiles.add(new SupportingFile("client.mustache", apiFolder, "client.rs"));
170+
supportingFiles.add(new SupportingFile("request.rs", apiFolder, "request.rs"));
170171
supportingFiles.add(new SupportingFile("model_mod.mustache", modelFolder, "mod.rs"));
171172
supportingFiles.add(new SupportingFile("lib.rs", "src", "lib.rs"));
172173
supportingFiles.add(new SupportingFile("Cargo.mustache", "", "Cargo.toml"));

modules/openapi-generator/src/main/resources/rust/api.mustache

Lines changed: 44 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
11
{{>partial_header}}
22
use std::rc::Rc;
33
use std::borrow::Borrow;
4-
use std::borrow::Cow;
5-
use std::collections::HashMap;
64

75
use hyper;
86
use serde_json;
9-
use futures;
10-
use futures::{Future, Stream};
11-
12-
use hyper::header::UserAgent;
7+
use futures::Future;
138

149
use super::{Error, configuration};
10+
use super::request as __internal_request;
1511

1612
pub struct {{{classname}}}Client<C: hyper::client::Connect> {
1713
configuration: Rc<configuration::Configuration<C>>,
@@ -38,129 +34,54 @@ impl<C: hyper::client::Connect>{{classname}} for {{classname}}Client<C> {
3834
{{#operations}}
3935
{{#operation}}
4036
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<Future<Item = {{^returnType}}(){{/returnType}}{{#returnType}}{{{.}}}{{/returnType}}, Error = Error<serde_json::Value>>> {
41-
let configuration: &configuration::Configuration<C> = self.configuration.borrow();
42-
43-
{{#hasAuthMethods}}
44-
let mut auth_headers = HashMap::<String, String>::new();
45-
let mut auth_query = HashMap::<String, String>::new();
46-
{{#authMethods}}
47-
{{#isApiKey}}
48-
if let Some(ref apikey) = configuration.api_key {
49-
let key = apikey.key.clone();
50-
let val = match apikey.prefix {
51-
Some(ref prefix) => format!("{} {}", prefix, key),
52-
None => key,
53-
};
54-
{{#isKeyInHeader}}
55-
auth_headers.insert("{{keyParamName}}".to_owned(), val);
56-
{{/isKeyInHeader}}
57-
{{#isKeyInQuery}}
58-
auth_query.insert("{{keyParamName}}".to_owned(), val);
59-
{{/isKeyInQuery}}
60-
};
61-
{{/isApiKey}}
62-
{{#isBasic}}
63-
if let Some(ref auth_conf) = configuration.basic_auth {
64-
let auth = hyper::header::Authorization(
65-
hyper::header::Basic {
66-
username: auth_conf.0.to_owned(),
67-
password: auth_conf.1.to_owned(),
68-
}
69-
);
70-
auth_headers.insert("Authorization".to_owned(), auth.to_string());
71-
};
72-
{{/isBasic}}
73-
{{#isOAuth}}
74-
if let Some(ref token) = configuration.oauth_access_token {
75-
let auth = hyper::header::Authorization(
76-
hyper::header::Bearer {
77-
token: token.to_owned(),
78-
}
79-
);
80-
auth_headers.insert("Authorization".to_owned(), auth.to_string());
81-
};
82-
{{/isOAuth}}
83-
{{/authMethods}}
84-
{{/hasAuthMethods}}
85-
let method = hyper::Method::{{httpMethod}};
86-
87-
let query_string = {
88-
let mut query = ::url::form_urlencoded::Serializer::new(String::new());
89-
{{#queryParams}}
90-
query.append_pair("{{baseName}}", &{{paramName}}{{#isListContainer}}.join(","){{/isListContainer}}.to_string());
91-
{{/queryParams}}
92-
{{#hasAuthMethods}}
93-
for (key, val) in &auth_query {
94-
query.append_pair(key, val);
95-
}
96-
{{/hasAuthMethods}}
97-
query.finish()
98-
};
99-
let uri_str = format!("{}{{{path}}}?{}", configuration.base_path, query_string{{#pathParams}}, {{baseName}}={{paramName}}{{#isListContainer}}.join(",").as_ref(){{/isListContainer}}{{/pathParams}});
100-
101-
// TODO(farcaller): handle error
102-
// if let Err(e) = uri {
103-
// return Box::new(futures::future::err(e));
104-
// }
105-
let mut uri: hyper::Uri = uri_str.parse().unwrap();
106-
107-
let mut req = hyper::Request::new(method, uri);
108-
109-
if let Some(ref user_agent) = configuration.user_agent {
110-
req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone())));
111-
}
112-
113-
{{#hasHeaderParams}}
114-
{
115-
let mut headers = req.headers_mut();
116-
{{#headerParams}}
117-
headers.set_raw("{{baseName}}", {{paramName}}{{#isListContainer}}.join(",").as_ref(){{/isListContainer}});
118-
{{/headerParams}}
119-
}
120-
{{/hasHeaderParams}}
121-
37+
__internal_request::Request::new(hyper::Method::{{httpMethod}}, "{{{path}}}".to_string())
12238
{{#hasAuthMethods}}
123-
for (key, val) in auth_headers {
124-
req.headers_mut().set_raw(key, val);
125-
}
39+
{{#authMethods}}
40+
{{#isApiKey}}
41+
.with_auth(__internal_request::Auth::ApiKey(__internal_request::ApiKey{
42+
in_header: {{#isKeyInHeader}}true{{/isKeyInHeader}}{{^isKeyInHeader}}false{{/isKeyInHeader}},
43+
in_query: {{#isKeyInQuery}}true{{/isKeyInQuery}}{{^isKeyInQuery}}false{{/isKeyInQuery}},
44+
param_name: "{{{keyParamName}}}".to_owned(),
45+
}))
46+
{{/isApiKey}}
47+
{{#isBasic}}
48+
.with_auth(__internal_request::Auth::Basic)
49+
{{/isBasic}}
50+
{{#isOAuth}}
51+
.with_auth(__internal_request::Auth::Oauth)
52+
{{/isOAuth}}
53+
{{/authMethods}}
12654
{{/hasAuthMethods}}
127-
55+
{{#queryParams}}
56+
.with_query_param("{{baseName}}".to_string(), {{paramName}}{{#isListContainer}}.join(","){{/isListContainer}}.to_string())
57+
{{/queryParams}}
58+
{{#pathParams}}
59+
.with_path_param("{{baseName}}".to_string(), {{paramName}}{{#isListContainer}}.join(","){{/isListContainer}}.to_string())
60+
{{/pathParams}}
61+
{{#hasHeaderParams}}
62+
{{#headerParams}}
63+
.with_header_param("{{baseName}}".to_string(), {{paramName}}{{#isListContainer}}.join(","){{/isListContainer}}.to_string())
64+
{{/headerParams}}
65+
{{/hasHeaderParams}}
66+
{{#hasFormParams}}
67+
{{#formParams}}
68+
{{#isFile}}
69+
.with_form_param("{{baseName}}".to_string(), unimplemented!())
70+
{{/isFile}}
71+
{{^isFile}}
72+
.with_form_param("{{baseName}}".to_string(), {{paramName}}{{#isListContainer}}.join(","){{/isListContainer}}.to_string())
73+
{{/isFile}}
74+
{{/formParams}}
75+
{{/hasFormParams}}
12876
{{#hasBodyParam}}
12977
{{#bodyParams}}
130-
let serialized = serde_json::to_string(&{{paramName}}).unwrap();
131-
req.headers_mut().set(hyper::header::ContentType::json());
132-
req.headers_mut().set(hyper::header::ContentLength(serialized.len() as u64));
133-
req.set_body(serialized);
78+
.with_body_param({{paramName}})
13479
{{/bodyParams}}
13580
{{/hasBodyParam}}
136-
137-
// send request
138-
Box::new(
139-
configuration.client.request(req)
140-
.map_err(|e| Error::from(e))
141-
.and_then(|resp| {
142-
let status = resp.status();
143-
resp.body().concat2()
144-
.and_then(move |body| Ok((status, body)))
145-
.map_err(|e| Error::from(e))
146-
})
147-
.and_then(|(status, body)| {
148-
if status.is_success() {
149-
Ok(body)
150-
} else {
151-
Err(Error::from((status, &*body)))
152-
}
153-
})
154-
{{^returnType}}
155-
.and_then(|_| futures::future::ok(()))
156-
{{/returnType}}
157-
{{#returnType}}
158-
.and_then(|body| {
159-
let parsed: Result<{{{returnType}}}, _> = serde_json::from_slice(&body);
160-
parsed.map_err(|e| Error::from(e))
161-
})
162-
{{/returnType}}
163-
)
81+
{{^returnType}}
82+
.returns_nothing()
83+
{{/returnType}}
84+
.execute(self.configuration.borrow())
16485
}
16586

16687
{{/operation}}

modules/openapi-generator/src/main/resources/rust/api_mod.mustache

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use serde_json;
44

55
#[derive(Debug)]
66
pub enum Error<T> {
7+
UriError(hyper::error::UriError),
78
Hyper(hyper::Error),
89
Serde(serde_json::Error),
910
ApiError(ApiError<T>),
@@ -50,6 +51,8 @@ impl<T> From<serde_json::Error> for Error<T> {
5051
5152
use super::models::*;
5253
54+
mod request;
55+
5356
{{#apiInfo}}
5457
{{#apis}}
5558
mod {{classFilename}};

0 commit comments

Comments
 (0)