Skip to content

Commit

Permalink
[Rust] Implement minimal auth support (#7338)
Browse files Browse the repository at this point in the history
* [Rust] Implement minimal auth support

This is pretty much the bare minimum needed to get v2 auth working.

This is partly based on the Go implementation.

* [Rust] properly format query string

* [Rust] Improve auth formatting

* [Rust] Regenerate petstore sample
  • Loading branch information
euank authored and wing328 committed Apr 2, 2018
1 parent 6c7813e commit b443573
Show file tree
Hide file tree
Showing 7 changed files with 428 additions and 85 deletions.
80 changes: 66 additions & 14 deletions modules/swagger-codegen/src/main/resources/rust/api.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use std::rc::Rc;
use std::borrow::Borrow;
use std::borrow::Cow;
use std::collections::HashMap;

use hyper;
use serde_json;
Expand Down Expand Up @@ -39,26 +40,71 @@ impl<C: hyper::client::Connect>{{classname}} for {{classname}}Client<C> {
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>>> {
let configuration: &configuration::Configuration<C> = self.configuration.borrow();
{{#hasAuthMethods}}
let mut auth_headers = HashMap::<String, String>::new();
let mut auth_query = HashMap::<String, String>::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}};

{{^hasQueryParams}}
let uri_str = format!("{}{{{path}}}", configuration.base_path{{#pathParams}}, {{baseName}}={{paramName}}{{#isListContainer}}.join(",").as_ref(){{/isListContainer}}{{/pathParams}});
{{/hasQueryParams}}
{{#hasQueryParams}}
let query = ::url::form_urlencoded::Serializer::new(String::new())
{{#queryParams}}
.append_pair("{{baseName}}", &{{paramName}}{{#isListContainer}}.join(","){{/isListContainer}}.to_string())
{{/queryParams}}
.finish();
let uri_str = format!("{}{{{path}}}{}", configuration.base_path, query{{#pathParams}}, {{baseName}}={{paramName}}{{#isListContainer}}.join(",").as_ref(){{/isListContainer}}{{/pathParams}});
{{/hasQueryParams}}

let uri = uri_str.parse();
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 req = hyper::Request::new(method, uri.unwrap());
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())));
Expand All @@ -73,6 +119,12 @@ impl<C: hyper::client::Connect>{{classname}} for {{classname}}Client<C> {
}
{{/hasHeaderParams}}

{{#hasAuthMethods}}
for (key, val) in auth_headers {
req.headers_mut().set_raw(key, val);
}
{{/hasAuthMethods}}

{{#hasBodyParam}}
{{#bodyParams}}
let serialized = serde_json::to_string(&{{paramName}}).unwrap();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
{{>partial_header}}
use hyper;
use std::collections::HashMap;

pub struct Configuration<C: hyper::client::Connect> {
pub base_path: String,
pub user_agent: Option<String>,
pub client: hyper::client::Client<C>,
pub basic_auth: Option<BasicAuth>,
pub oauth_access_token: Option<String>,
pub api_key: Option<ApiKey>,
// TODO: take an oauth2 token source, similar to the go one
}

pub type BasicAuth = (String, Option<String>);

pub struct ApiKey {
pub prefix: Option<String>,
pub key: String,
}

impl<C: hyper::client::Connect> Configuration<C> {
Expand All @@ -13,6 +25,9 @@ impl<C: hyper::client::Connect> Configuration<C> {
base_path: "{{{basePath}}}".to_owned(),
user_agent: {{#httpUserAgent}}Some("{{{.}}}".to_owned()){{/httpUserAgent}}{{^httpUserAgent}}Some("Swagger-Codegen/{{version}}/rust".to_owned()){{/httpUserAgent}},
client: client,
basic_auth: None,
oauth_access_token: None,
api_key: None,
}
}
}
2 changes: 1 addition & 1 deletion samples/client/petstore/rust/docs/UserApi.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ Get user by user name

Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**username** | **String**| The name that needs to be fetched. Use user1 for testing. |
**username** | **String**| The name that needs to be fetched. Use user1 for testing. |

### Return type

Expand Down
15 changes: 15 additions & 0 deletions samples/client/petstore/rust/src/apis/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,23 @@
*/

use hyper;
use std::collections::HashMap;

pub struct Configuration<C: hyper::client::Connect> {
pub base_path: String,
pub user_agent: Option<String>,
pub client: hyper::client::Client<C>,
pub basic_auth: Option<BasicAuth>,
pub oauth_access_token: Option<String>,
pub api_key: Option<ApiKey>,
// TODO: take an oauth2 token source, similar to the go one
}

pub type BasicAuth = (String, Option<String>);

pub struct ApiKey {
pub prefix: Option<String>,
pub key: String,
}

impl<C: hyper::client::Connect> Configuration<C> {
Expand All @@ -22,6 +34,9 @@ impl<C: hyper::client::Connect> Configuration<C> {
base_path: "http://petstore.swagger.io/v2".to_owned(),
user_agent: Some("Swagger-Codegen/1.0.0/rust".to_owned()),
client: client,
basic_auth: None,
oauth_access_token: None,
api_key: None,
}
}
}
Loading

0 comments on commit b443573

Please sign in to comment.