From cfe3b86d70cd038c7e4e073d57c750b9d0189376 Mon Sep 17 00:00:00 2001 From: Richard Whitehouse Date: Thu, 26 Mar 2020 17:14:13 +0000 Subject: [PATCH] [Rust Server] Handle text/xml correctly (#5660) * [Rust Server] Handle text/xml correctly Treat application/xml the same as text/xml as per RFC 7303 * [Rust Server] Add test for text/xml * Update samples --- .../codegen/languages/RustServerCodegen.java | 4 +++- .../resources/3_0/rust-server/openapi-v3.yaml | 6 +++++- .../output/openapi-v3/api/openapi.yaml | 6 +++++- .../output/openapi-v3/docs/default_api.md | 8 ++++---- .../output/openapi-v3/src/client/mod.rs | 18 +++++++++++++++--- .../rust-server/output/openapi-v3/src/lib.rs | 1 + .../output/openapi-v3/src/mimetypes.rs | 7 ++++++- .../output/openapi-v3/src/server/mod.rs | 9 +++++++++ 8 files changed, 48 insertions(+), 11 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java index 1076e3f545d..3bad2df6ed0 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustServerCodegen.java @@ -69,6 +69,7 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig { private static final String bytesType = "swagger::ByteArray"; private static final String xmlMimeType = "application/xml"; + private static final String textXmlMimeType = "text/xml"; private static final String octetMimeType = "application/octet-stream"; private static final String plainMimeType = "text/plain"; private static final String jsonMimeType = "application/json"; @@ -521,7 +522,8 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig { } private boolean isMimetypeXml(String mimetype) { - return mimetype.toLowerCase(Locale.ROOT).startsWith(xmlMimeType); + return mimetype.toLowerCase(Locale.ROOT).startsWith(xmlMimeType) || + mimetype.toLowerCase(Locale.ROOT).startsWith(textXmlMimeType); } private boolean isMimetypePlainText(String mimetype) { diff --git a/modules/openapi-generator/src/test/resources/3_0/rust-server/openapi-v3.yaml b/modules/openapi-generator/src/test/resources/3_0/rust-server/openapi-v3.yaml index 619a49d1c50..f96e1d72178 100644 --- a/modules/openapi-generator/src/test/resources/3_0/rust-server/openapi-v3.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/rust-server/openapi-v3.yaml @@ -99,12 +99,16 @@ paths: post: requestBody: content: - application/xml: + text/xml: schema: $ref: '#/components/schemas/anotherXmlObject' responses: '201': description: 'OK' + content: + text/xml: + schema: + $ref: "#/components/schemas/anotherXmlObject" '400': description: Bad Request put: diff --git a/samples/server/petstore/rust-server/output/openapi-v3/api/openapi.yaml b/samples/server/petstore/rust-server/output/openapi-v3/api/openapi.yaml index bea64a165c5..264ca21bc7e 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/api/openapi.yaml +++ b/samples/server/petstore/rust-server/output/openapi-v3/api/openapi.yaml @@ -81,11 +81,15 @@ paths: post: requestBody: content: - application/xml: + text/xml: schema: $ref: '#/components/schemas/anotherXmlObject' responses: "201": + content: + text/xml: + schema: + $ref: '#/components/schemas/anotherXmlObject' description: OK "400": description: Bad Request diff --git a/samples/server/petstore/rust-server/output/openapi-v3/docs/default_api.md b/samples/server/petstore/rust-server/output/openapi-v3/docs/default_api.md index 1322f643838..5565939f04f 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/docs/default_api.md +++ b/samples/server/petstore/rust-server/output/openapi-v3/docs/default_api.md @@ -185,7 +185,7 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) # **** -> (optional) +> models::AnotherXmlObject (optional) ### Required Parameters @@ -203,7 +203,7 @@ Name | Type | Description | Notes ### Return type - (empty response body) +[**models::AnotherXmlObject**](anotherXmlObject.md) ### Authorization @@ -211,8 +211,8 @@ No authorization required ### HTTP request headers - - **Content-Type**: application/xml - - **Accept**: Not defined + - **Content-Type**: text/xml + - **Accept**: text/xml, [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/client/mod.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/client/mod.rs index 0301284ab1a..668b3083779 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/client/mod.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/client/mod.rs @@ -936,10 +936,22 @@ impl Api for Client where 201 => { let body = response.body(); Box::new( - - future::ok( - XmlOtherPostResponse::OK + 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::(body) + .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e))) + ) ) + .map(move |body| { + XmlOtherPostResponse::OK(body) + }) ) as Box> }, 400 => { diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/lib.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/lib.rs index 17fe5ad4694..040a9308d60 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/lib.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/lib.rs @@ -137,6 +137,7 @@ pub enum XmlExtraPostResponse { pub enum XmlOtherPostResponse { /// OK OK + (models::AnotherXmlObject) , /// Bad Request BadRequest diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/mimetypes.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/mimetypes.rs index 28f79f4ed2b..0abf4777006 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/mimetypes.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/mimetypes.rs @@ -50,6 +50,11 @@ pub mod responses { pub static ref UUID_GET_DUPLICATE_RESPONSE_LONG_TEXT: Mime = "application/json".parse().unwrap(); } + lazy_static! { + /// Create Mime objects for the response content types for XmlOtherPost + pub static ref XML_OTHER_POST_OK: Mime = "text/xml".parse().unwrap(); + } + } pub mod requests { @@ -67,7 +72,7 @@ pub mod requests { lazy_static! { /// Create Mime objects for the request content types for XmlOtherPost - pub static ref XML_OTHER_POST: Mime = "application/xml".parse().unwrap(); + pub static ref XML_OTHER_POST: Mime = "text/xml".parse().unwrap(); } lazy_static! { diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/server/mod.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/server/mod.rs index 9d667a26574..834eece27b1 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/server/mod.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/server/mod.rs @@ -637,10 +637,19 @@ where Ok(rsp) => match rsp { XmlOtherPostResponse::OK + (body) + => { response.set_status(StatusCode::try_from(201).unwrap()); + response.headers_mut().set(ContentType(mimetypes::responses::XML_OTHER_POST_OK.clone())); + + let mut namespaces = BTreeMap::new(); + // An empty string is used to indicate a global namespace in xmltree. + namespaces.insert("".to_string(), models::AnotherXmlObject::NAMESPACE.to_string()); + let body = serde_xml_rs::to_string_with_namespaces(&body, namespaces).expect("impossible to fail to serialize"); + response.set_body(body); }, XmlOtherPostResponse::BadRequest