Skip to content

Commit 8e1d20e

Browse files
bjgillwing328
authored andcommitted
Handle headers correctly (OpenAPITools#549)
We were previously relying on some incorrect behaviour of the old swagger-codegen mustache engine.
1 parent 29ce03a commit 8e1d20e

File tree

9 files changed

+109
-23
lines changed

9 files changed

+109
-23
lines changed

modules/openapi-generator/src/main/resources/rust-server/lib.mustache

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ pub const API_VERSION: &'static str = "{{appVersion}}";
4242
pub enum {{operationId}}Response {
4343
{{#responses}}
4444
{{#message}} /// {{message}}{{/message}}
45-
{{#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}},
46-
{{/responses}}
45+
{{#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}},
46+
{{/responses}}
4747
}
4848
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
4949

modules/openapi-generator/src/test/resources/2_0/rust-server/petstore-with-fake-endpoints-models-for-testing.yaml

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -450,19 +450,19 @@ paths:
450450
required: true
451451
type: string
452452
responses:
453-
# '200':
454-
# description: successful operation
455-
# schema:
456-
# type: string
457-
# headers:
458-
# X-Rate-Limit:
459-
# type: integer
460-
# format: int32
461-
# description: calls per hour allowed by the user
462-
# X-Expires-After:
463-
# type: string
464-
# format: date-time
465-
# description: date in UTC when token expires
453+
'200':
454+
description: successful operation
455+
schema:
456+
type: string
457+
headers:
458+
X-Rate-Limit:
459+
type: integer
460+
format: int32
461+
description: calls per hour allowed by the user
462+
X-Expires-After:
463+
type: string
464+
format: date-time
465+
description: date in UTC when token expires
466466
'400':
467467
description: Invalid username/password supplied
468468
/user/logout:
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.0.1-SNAPSHOT
1+
3.1.1-SNAPSHOT

samples/server/petstore/rust-server/api/openapi.yaml

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,26 @@ paths:
453453
schema:
454454
type: string
455455
responses:
456+
200:
457+
content:
458+
application/xml:
459+
schema:
460+
type: string
461+
application/json:
462+
schema:
463+
type: string
464+
description: successful operation
465+
headers:
466+
X-Rate-Limit:
467+
description: calls per hour allowed by the user
468+
schema:
469+
format: int32
470+
type: integer
471+
X-Expires-After:
472+
description: date in UTC when token expires
473+
schema:
474+
format: date-time
475+
type: string
456476
400:
457477
content: {}
458478
description: Invalid username/password supplied
@@ -1229,14 +1249,18 @@ components:
12291249
type: array
12301250
type: object
12311251
OuterComposite:
1232-
example: {}
1252+
example:
1253+
my_string: my_string
1254+
my_number: 0.80082819046101150206595775671303272247314453125
1255+
my_boolean: true
12331256
properties:
12341257
my_number:
1235-
$ref: '#/components/schemas/OuterNumber'
1258+
type: number
12361259
my_string:
1237-
$ref: '#/components/schemas/OuterString'
1260+
type: string
12381261
my_boolean:
1239-
$ref: '#/components/schemas/OuterBoolean'
1262+
type: boolean
1263+
x-codegen-body-parameter-name: boolean_post_body
12401264
type: object
12411265
format_test:
12421266
properties:

samples/server/petstore/rust-server/src/client/mod.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2526,6 +2526,38 @@ if let Some(body) = body {
25262526
.map_err(|e| ApiError(format!("No response received: {}", e)))
25272527
.and_then(|mut response| {
25282528
match response.status().as_u16() {
2529+
200 => {
2530+
header! { (ResponseXRateLimit, "X-Rate-Limit") => [i32] }
2531+
let response_x_rate_limit = match response.headers().get::<ResponseXRateLimit>() {
2532+
Some(response_x_rate_limit) => response_x_rate_limit.0.clone(),
2533+
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=_>>,
2534+
};
2535+
header! { (ResponseXExpiresAfter, "X-Expires-After") => [chrono::DateTime<chrono::Utc>] }
2536+
let response_x_expires_after = match response.headers().get::<ResponseXExpiresAfter>() {
2537+
Some(response_x_expires_after) => response_x_expires_after.0.clone(),
2538+
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=_>>,
2539+
};
2540+
let body = response.body();
2541+
Box::new(
2542+
2543+
body
2544+
.concat2()
2545+
.map_err(|e| ApiError(format!("Failed to read response: {}", e)))
2546+
.and_then(|body| str::from_utf8(&body)
2547+
.map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))
2548+
.and_then(|body|
2549+
2550+
// ToDo: this will move to swagger-rs and become a standard From conversion trait
2551+
// once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream
2552+
serde_xml_rs::from_str::<String>(body)
2553+
.map_err(|e| ApiError(format!("Response body did not match the schema: {}", e)))
2554+
2555+
))
2556+
.map(move |body|
2557+
LoginUserResponse::SuccessfulOperation{ body: body, x_rate_limit: response_x_rate_limit, x_expires_after: response_x_expires_after }
2558+
)
2559+
) as Box<Future<Item=_, Error=_>>
2560+
},
25292561
400 => {
25302562
let body = response.body();
25312563
Box::new(

samples/server/petstore/rust-server/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,8 @@ pub enum GetUserByNameResponse {
242242

243243
#[derive(Debug, PartialEq)]
244244
pub enum LoginUserResponse {
245+
/// successful operation
246+
SuccessfulOperation { body: String, x_rate_limit: i32, x_expires_after: chrono::DateTime<chrono::Utc> } ,
245247
/// Invalid username/password supplied
246248
InvalidUsername ,
247249
}

samples/server/petstore/rust-server/src/mimetypes.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ pub mod responses {
6464
lazy_static! {
6565
pub static ref GET_USER_BY_NAME_SUCCESSFUL_OPERATION: Mime = "application/json".parse().unwrap();
6666
}
67+
/// Create Mime objects for the response content types for LoginUser
68+
lazy_static! {
69+
pub static ref LOGIN_USER_SUCCESSFUL_OPERATION: Mime = "application/json".parse().unwrap();
70+
}
6771

6872
}
6973

samples/server/petstore/rust-server/src/models.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -762,15 +762,15 @@ impl ::std::ops::DerefMut for OuterBoolean {
762762
pub struct OuterComposite {
763763
#[serde(rename = "my_number")]
764764
#[serde(skip_serializing_if="Option::is_none")]
765-
pub my_number: Option<models::OuterNumber>,
765+
pub my_number: Option<f64>,
766766

767767
#[serde(rename = "my_string")]
768768
#[serde(skip_serializing_if="Option::is_none")]
769-
pub my_string: Option<models::OuterString>,
769+
pub my_string: Option<String>,
770770

771771
#[serde(rename = "my_boolean")]
772772
#[serde(skip_serializing_if="Option::is_none")]
773-
pub my_boolean: Option<models::OuterBoolean>,
773+
pub my_boolean: Option<bool>,
774774

775775
}
776776

samples/server/petstore/rust-server/src/server/mod.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2934,6 +2934,30 @@ where
29342934

29352935
match result {
29362936
Ok(rsp) => match rsp {
2937+
LoginUserResponse::SuccessfulOperation
2938+
2939+
{
2940+
body,
2941+
x_rate_limit,
2942+
2943+
x_expires_after
2944+
}
2945+
2946+
2947+
=> {
2948+
response.set_status(StatusCode::try_from(200).unwrap());
2949+
header! { (ResponseXRateLimit, "X-Rate-Limit") => [i32] }
2950+
response.headers_mut().set(ResponseXRateLimit(x_rate_limit));
2951+
header! { (ResponseXExpiresAfter, "X-Expires-After") => [chrono::DateTime<chrono::Utc>] }
2952+
response.headers_mut().set(ResponseXExpiresAfter(x_expires_after));
2953+
2954+
response.headers_mut().set(ContentType(mimetypes::responses::LOGIN_USER_SUCCESSFUL_OPERATION.clone()));
2955+
2956+
2957+
let body = serde_xml_rs::to_string(&body).expect("impossible to fail to serialize");
2958+
2959+
response.set_body(body);
2960+
},
29372961
LoginUserResponse::InvalidUsername
29382962

29392963

0 commit comments

Comments
 (0)