Skip to content

Commit

Permalink
Handle headers correctly (OpenAPITools#549)
Browse files Browse the repository at this point in the history
We were previously relying on some incorrect behaviour of the old
swagger-codegen mustache engine.
  • Loading branch information
bjgill authored and wing328 committed Jul 12, 2018
1 parent 29ce03a commit 8e1d20e
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ pub const API_VERSION: &'static str = "{{appVersion}}";
pub enum {{operationId}}Response {
{{#responses}}
{{#message}} /// {{message}}{{/message}}
{{#vendorExtensions}}{{x-responseId}}{{/vendorExtensions}} {{#dataType}}{{^headers}}( {{{dataType}}} ) {{/headers}}{{#headers}}{{#-first}}{ body: {{{dataType}}}{{/-first}}{{/headers}}{{/dataType}}{{#headers}}{{#-first}}{{^dataType}} { {{/dataType}}{{#dataType}}, {{/dataType}}{{/-first}}{{^-first}}, {{/-first}}{{name}}: {{{dataType}}}{{#-last}} } {{/-last}}{{/headers}},
{{/responses}}
{{#vendorExtensions}}{{{x-responseId}}}{{/vendorExtensions}} {{#dataType}}{{^hasHeaders}}( {{{dataType}}} ) {{/hasHeaders}}{{#hasHeaders}}{{#-first}}{ body: {{{dataType}}}{{/-first}}{{/hasHeaders}}{{/dataType}}{{#dataType}}{{#hasHeaders}}, {{/hasHeaders}}{{/dataType}}{{^dataType}}{{#hasHeaders}} { {{/hasHeaders}}{{/dataType}}{{#headers}}{{^-first}}, {{/-first}}{{{name}}}: {{{datatype}}}{{#-last}} } {{/-last}}{{/headers}},
{{/responses}}
}
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -450,19 +450,19 @@ paths:
required: true
type: string
responses:
# '200':
# description: successful operation
# schema:
# type: string
# headers:
# X-Rate-Limit:
# type: integer
# format: int32
# description: calls per hour allowed by the user
# X-Expires-After:
# type: string
# format: date-time
# description: date in UTC when token expires
'200':
description: successful operation
schema:
type: string
headers:
X-Rate-Limit:
type: integer
format: int32
description: calls per hour allowed by the user
X-Expires-After:
type: string
format: date-time
description: date in UTC when token expires
'400':
description: Invalid username/password supplied
/user/logout:
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.0.1-SNAPSHOT
3.1.1-SNAPSHOT
32 changes: 28 additions & 4 deletions samples/server/petstore/rust-server/api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,26 @@ paths:
schema:
type: string
responses:
200:
content:
application/xml:
schema:
type: string
application/json:
schema:
type: string
description: successful operation
headers:
X-Rate-Limit:
description: calls per hour allowed by the user
schema:
format: int32
type: integer
X-Expires-After:
description: date in UTC when token expires
schema:
format: date-time
type: string
400:
content: {}
description: Invalid username/password supplied
Expand Down Expand Up @@ -1229,14 +1249,18 @@ components:
type: array
type: object
OuterComposite:
example: {}
example:
my_string: my_string
my_number: 0.80082819046101150206595775671303272247314453125
my_boolean: true
properties:
my_number:
$ref: '#/components/schemas/OuterNumber'
type: number
my_string:
$ref: '#/components/schemas/OuterString'
type: string
my_boolean:
$ref: '#/components/schemas/OuterBoolean'
type: boolean
x-codegen-body-parameter-name: boolean_post_body
type: object
format_test:
properties:
Expand Down
32 changes: 32 additions & 0 deletions samples/server/petstore/rust-server/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2526,6 +2526,38 @@ if let Some(body) = body {
.map_err(|e| ApiError(format!("No response received: {}", e)))
.and_then(|mut response| {
match response.status().as_u16() {
200 => {
header! { (ResponseXRateLimit, "X-Rate-Limit") => [i32] }
let response_x_rate_limit = match response.headers().get::<ResponseXRateLimit>() {
Some(response_x_rate_limit) => response_x_rate_limit.0.clone(),
None => return Box::new(future::err(ApiError(String::from("Required response header X-Rate-Limit for response 200 was not found.")))) as Box<Future<Item=_, Error=_>>,
};
header! { (ResponseXExpiresAfter, "X-Expires-After") => [chrono::DateTime<chrono::Utc>] }
let response_x_expires_after = match response.headers().get::<ResponseXExpiresAfter>() {
Some(response_x_expires_after) => response_x_expires_after.0.clone(),
None => return Box::new(future::err(ApiError(String::from("Required response header X-Expires-After for response 200 was not found.")))) as Box<Future<Item=_, Error=_>>,
};
let body = response.body();
Box::new(

body
.concat2()
.map_err(|e| ApiError(format!("Failed to read response: {}", e)))
.and_then(|body| str::from_utf8(&body)
.map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))
.and_then(|body|

// ToDo: this will move to swagger-rs and become a standard From conversion trait
// once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream
serde_xml_rs::from_str::<String>(body)
.map_err(|e| ApiError(format!("Response body did not match the schema: {}", e)))

))
.map(move |body|
LoginUserResponse::SuccessfulOperation{ body: body, x_rate_limit: response_x_rate_limit, x_expires_after: response_x_expires_after }
)
) as Box<Future<Item=_, Error=_>>
},
400 => {
let body = response.body();
Box::new(
Expand Down
2 changes: 2 additions & 0 deletions samples/server/petstore/rust-server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,8 @@ pub enum GetUserByNameResponse {

#[derive(Debug, PartialEq)]
pub enum LoginUserResponse {
/// successful operation
SuccessfulOperation { body: String, x_rate_limit: i32, x_expires_after: chrono::DateTime<chrono::Utc> } ,
/// Invalid username/password supplied
InvalidUsername ,
}
Expand Down
4 changes: 4 additions & 0 deletions samples/server/petstore/rust-server/src/mimetypes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ pub mod responses {
lazy_static! {
pub static ref GET_USER_BY_NAME_SUCCESSFUL_OPERATION: Mime = "application/json".parse().unwrap();
}
/// Create Mime objects for the response content types for LoginUser
lazy_static! {
pub static ref LOGIN_USER_SUCCESSFUL_OPERATION: Mime = "application/json".parse().unwrap();
}

}

Expand Down
6 changes: 3 additions & 3 deletions samples/server/petstore/rust-server/src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -762,15 +762,15 @@ impl ::std::ops::DerefMut for OuterBoolean {
pub struct OuterComposite {
#[serde(rename = "my_number")]
#[serde(skip_serializing_if="Option::is_none")]
pub my_number: Option<models::OuterNumber>,
pub my_number: Option<f64>,

#[serde(rename = "my_string")]
#[serde(skip_serializing_if="Option::is_none")]
pub my_string: Option<models::OuterString>,
pub my_string: Option<String>,

#[serde(rename = "my_boolean")]
#[serde(skip_serializing_if="Option::is_none")]
pub my_boolean: Option<models::OuterBoolean>,
pub my_boolean: Option<bool>,

}

Expand Down
24 changes: 24 additions & 0 deletions samples/server/petstore/rust-server/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2934,6 +2934,30 @@ where

match result {
Ok(rsp) => match rsp {
LoginUserResponse::SuccessfulOperation

{
body,
x_rate_limit,

x_expires_after
}


=> {
response.set_status(StatusCode::try_from(200).unwrap());
header! { (ResponseXRateLimit, "X-Rate-Limit") => [i32] }
response.headers_mut().set(ResponseXRateLimit(x_rate_limit));
header! { (ResponseXExpiresAfter, "X-Expires-After") => [chrono::DateTime<chrono::Utc>] }
response.headers_mut().set(ResponseXExpiresAfter(x_expires_after));

response.headers_mut().set(ContentType(mimetypes::responses::LOGIN_USER_SUCCESSFUL_OPERATION.clone()));


let body = serde_xml_rs::to_string(&body).expect("impossible to fail to serialize");

response.set_body(body);
},
LoginUserResponse::InvalidUsername


Expand Down

0 comments on commit 8e1d20e

Please sign in to comment.