From 31734c27176ab08a07076eaea660379c3e25535a Mon Sep 17 00:00:00 2001 From: Richard Whitehouse Date: Tue, 7 May 2019 11:45:07 +0100 Subject: [PATCH] [Rust Server] Support octet stream body param (#2725) Add support for having a required octet stream as a body parameter. --- .../codegen/languages/RustServerCodegen.java | 47 ++-- .../resources/rust-server/client-mod.mustache | 26 ++- .../resources/rust-server/models.mustache | 11 + .../resources/rust-server/server-mod.mustache | 16 +- .../resources/3_0/rust-server/openapi-v3.yaml | 16 ++ .../rust-server/output/openapi-v3/README.md | 3 + .../output/openapi-v3/api/openapi.yaml | 16 ++ .../output/openapi-v3/docs/UuidObject.md | 9 + .../output/openapi-v3/docs/default_api.md | 26 +++ .../output/openapi-v3/examples/client.rs | 7 + .../openapi-v3/examples/server_lib/server.rs | 8 + .../output/openapi-v3/src/client/mod.rs | 83 ++++++- .../rust-server/output/openapi-v3/src/lib.rs | 17 ++ .../output/openapi-v3/src/mimetypes.rs | 4 + .../output/openapi-v3/src/models.rs | 57 +++++ .../output/openapi-v3/src/server/mod.rs | 77 ++++++- .../src/client/mod.rs | 215 +++++++++++------- .../src/models.rs | 11 + .../src/server/mod.rs | 18 +- .../output/rust-server-test/src/client/mod.rs | 40 ++-- .../output/rust-server-test/src/models.rs | 2 + .../output/rust-server-test/src/server/mod.rs | 7 +- 22 files changed, 560 insertions(+), 156 deletions(-) create mode 100644 samples/server/petstore/rust-server/output/openapi-v3/docs/UuidObject.md 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 a342dee6f41..dedc8a91ef8 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 @@ -64,6 +64,9 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig { protected String externCrateName; protected Map> pathSetMap = new HashMap>(); + private static final String uuidType = "uuid::Uuid"; + private static final String bytesType = "swagger::ByteArray"; + public RustServerCodegen() { super(); @@ -150,16 +153,16 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig { typeMapping.put("float", "f32"); typeMapping.put("double", "f64"); typeMapping.put("string", "String"); - typeMapping.put("UUID", "uuid::Uuid"); + typeMapping.put("UUID", uuidType); typeMapping.put("byte", "u8"); - typeMapping.put("ByteArray", "swagger::ByteArray"); - typeMapping.put("binary", "swagger::ByteArray"); + typeMapping.put("ByteArray", bytesType); + typeMapping.put("binary", bytesType); typeMapping.put("boolean", "bool"); typeMapping.put("date", "chrono::DateTime"); typeMapping.put("DateTime", "chrono::DateTime"); typeMapping.put("password", "String"); - typeMapping.put("File", "swagger::ByteArray"); - typeMapping.put("file", "swagger::ByteArray"); + typeMapping.put("File", bytesType); + typeMapping.put("file", bytesType); typeMapping.put("array", "Vec"); typeMapping.put("map", "HashMap"); @@ -498,6 +501,18 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig { return mimetype.toLowerCase(Locale.ROOT).startsWith("application/x-www-form-urlencoded"); } + boolean isMimetypeMultipartFormData(String mimetype) { + return mimetype.toLowerCase(Locale.ROOT).startsWith("multipart/form-data"); + } + + boolean isMimetypeOctetStream(String mimetype) { + return mimetype.toLowerCase(Locale.ROOT).startsWith("application/octet-stream"); + } + + boolean isMimetypePlain(String mimetype) { + return isMimetypePlainText(mimetype) || isMimetypeHtmlText(mimetype) || isMimetypeOctetStream(mimetype); + } + @Override public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, List servers) { Map definitions = ModelUtils.getSchemas(this.openAPI); @@ -563,9 +578,7 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig { if (isMimetypeXml(mimeType)) { additionalProperties.put("usesXml", true); consumesXml = true; - } else if (isMimetypePlainText(mimeType)) { - consumesPlainText = true; - } else if (isMimetypeHtmlText(mimeType)) { + } else if (isMimetypePlain(mimeType)) { consumesPlainText = true; } else if (isMimetypeWwwFormUrlEncoded(mimeType)) { additionalProperties.put("usesUrlEncodedForm", true); @@ -591,9 +604,7 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig { if (isMimetypeXml(mimeType)) { additionalProperties.put("usesXml", true); producesXml = true; - } else if (isMimetypePlainText(mimeType)) { - producesPlainText = true; - } else if (isMimetypeHtmlText(mimeType)) { + } else if (isMimetypePlain(mimeType)) { producesPlainText = true; } @@ -606,7 +617,7 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig { for (CodegenParameter param : op.headerParams) { // If a header uses UUIDs, we need to import the UUID package. - if (param.dataType.equals("uuid::Uuid")) { + if (param.dataType.equals(uuidType)) { additionalProperties.put("apiUsesUuid", true); } processParam(param, op); @@ -634,7 +645,7 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig { // Default to producing json if nothing else is specified if (producesXml) { rsp.vendorExtensions.put("producesXml", true); - } else if (producesPlainText) { + } else if (producesPlainText && rsp.dataType.equals(bytesType)) { rsp.vendorExtensions.put("producesPlainText", true); } else { rsp.vendorExtensions.put("producesJson", true); @@ -659,14 +670,14 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig { } } for (CodegenProperty header : rsp.headers) { - if (header.dataType.equals("uuid::Uuid")) { + if (header.dataType.equals(uuidType)) { additionalProperties.put("apiUsesUuid", true); } header.nameInCamelCase = toModelName(header.baseName); } } for (CodegenProperty header : op.responseHeaders) { - if (header.dataType.equals("uuid::Uuid")) { + if (header.dataType.equals(uuidType)) { additionalProperties.put("apiUsesUuid", true); } header.nameInCamelCase = toModelName(header.baseName); @@ -693,7 +704,7 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig { if (isMimetypeXml(mediaType)) { additionalProperties.put("usesXml", true); consumesXml = true; - } else if (isMimetypePlainText(mediaType) || isMimetypeHtmlText(mediaType)) { + } else if (isMimetypePlain(mediaType)) { consumesPlainText = true; } else if (isMimetypeWwwFormUrlEncoded(mediaType)) { additionalProperties.put("usesUrlEncodedForm", true); @@ -734,7 +745,7 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig { } for (CodegenProperty header : op.responseHeaders) { - if (header.dataType.equals("uuid::Uuid")) { + if (header.dataType.equals(uuidType)) { additionalProperties.put("apiUsesUuid", true); } header.nameInCamelCase = toModelName(header.baseName); @@ -1108,6 +1119,8 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig { cm.dataType = typeMapping.get(cm.dataType); } } + + cm.vendorExtensions.put("isString", "String".equals(cm.dataType)); } return super.postProcessModelsEnum(objs); } diff --git a/modules/openapi-generator/src/main/resources/rust-server/client-mod.mustache b/modules/openapi-generator/src/main/resources/rust-server/client-mod.mustache index efa70ded2df..aea03b15c6d 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/client-mod.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/client-mod.mustache @@ -286,7 +286,12 @@ impl Api for Client where {{/-first}} {{#vendorExtensions}} {{#consumesPlainText}} + {{#isByteArray}} + let body = param_{{{paramName}}}.0; + {{/isByteArray}} + {{^isByteArray}} let body = param_{{{paramName}}}; + {{/isByteArray}} {{/consumesPlainText}} {{#required}} {{#consumesXml}} @@ -310,7 +315,7 @@ impl Api for Client where {{/bodyParam}} {{#bodyParam}}{{^required}}if let Some(body) = body { - {{/required}} request.set_body(body.into_bytes()); + {{/required}} request.set_body(body); {{^required}} }{{/required}} request.headers_mut().set(ContentType(mimetypes::requests::{{#vendorExtensions}}{{{uppercase_operation_id}}}{{/vendorExtensions}}.clone())); @@ -353,10 +358,15 @@ impl Api for Client where body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| str::from_utf8(&body) + .and_then(|body| +{{#vendorExtensions}} +{{#producesPlainText}} + Ok(swagger::ByteArray(body.to_vec())) +{{/producesPlainText}}{{^producesPlainText}} + str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) .and_then(|body| -{{#vendorExtensions}}{{#producesXml}} +{{#producesXml}} // 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::<{{{dataType}}}>(body) @@ -364,13 +374,13 @@ impl Api for Client where {{/producesXml}}{{#producesJson}} serde_json::from_str::<{{{dataType}}}>(body) .map_err(|e| e.into()) -{{/producesJson}}{{#producesPlainText}} - Ok(body.to_string()) +{{/producesJson}} + ) {{/producesPlainText}}{{/vendorExtensions}} - )) - .map(move |body| + ) + .map(move |body| { {{{operationId}}}Response::{{#vendorExtensions}}{{x-responseId}}{{/vendorExtensions}}{{^headers}}(body){{/headers}}{{#headers}}{{#-first}}{ body: body, {{/-first}}{{{name}}}: response_{{{name}}}{{^-last}}, {{/-last}}{{#-last}} }{{/-last}}{{/headers}} - ) + }) {{/dataType}}{{^dataType}} future::ok( {{{operationId}}}Response::{{#vendorExtensions}}{{x-responseId}}{{/vendorExtensions}}{{#headers}}{{#-first}}{ {{/-first}}{{^-first}}, {{/-first}}{{{name}}}: response_{{{name}}}{{#-last}} }{{/-last}}{{/headers}} diff --git a/modules/openapi-generator/src/main/resources/rust-server/models.mustache b/modules/openapi-generator/src/main/resources/rust-server/models.mustache index eb8f0892b98..2de3e517ca3 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/models.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/models.mustache @@ -15,6 +15,8 @@ use std::collections::HashMap; {{/usesXml}} use models; use swagger; +use std::string::ParseError; + {{#models}}{{#model}} {{#description}}/// {{{description}}} @@ -57,6 +59,15 @@ impl ::std::convert::From<{{{dataType}}}> for {{{classname}}} { } } +{{#vendorExtensions.isString}} +impl std::str::FromStr for {{{classname}}} { + type Err = ParseError; + fn from_str(x: &str) -> Result { + Ok({{{classname}}}(x.to_string())) + } +} +{{/vendorExtensions.isString}} + impl ::std::convert::From<{{{classname}}}> for {{{dataType}}} { fn from(x: {{{classname}}}) -> Self { x.0 diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-mod.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-mod.mustache index e33501d8483..2aea9c00ae8 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-mod.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-mod.mustache @@ -180,7 +180,7 @@ where let param_{{{paramName}}} = match percent_encoding::percent_decode(path_params["{{{baseName}}}"].as_bytes()).decode_utf8() { Ok(param_{{{paramName}}}) => match param_{{{paramName}}}.parse::<{{{dataType}}}>() { Ok(param_{{{paramName}}}) => param_{{{paramName}}}, - Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse path parameter {{{baseName}}}: {}", e)))), + Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse path parameter {{{baseName}}}: {:?}", e)))), }, Err(_) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["{{{baseName}}}"])))) }; @@ -259,10 +259,12 @@ where {{/required}} } {{/consumesPlainText}}{{#consumesPlainText}} - match String::from_utf8(body.to_vec()) { - Ok(param_{{{paramName}}}) => Some(param_{{{paramName}}}), - Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse body parameter {{{baseName}}} - not valid UTF-8: {}", e)))), - } +{{#isByteArray}} + Some(swagger::ByteArray(body.to_vec())) +{{/isByteArray}} +{{#isString}} + Some(String::from_utf8(body.to_vec()).unwrap()) +{{/isString}} {{/consumesPlainText}}{{/vendorExtensions}} } else { None @@ -335,7 +337,9 @@ where let body = serde_xml_rs::to_string_with_namespaces(&body, namespaces).expect("impossible to fail to serialize"); {{/has_namespace}}{{/producesXml}}{{#producesJson}} let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); -{{/producesJson}}{{/vendorExtensions}} +{{/producesJson}}{{#producesPlainText}} + let body = body.0; +{{/producesPlainText}}{{/vendorExtensions}} response.set_body(body); {{/dataType}} }, 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 c25db351150..677a439f041 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 @@ -76,8 +76,24 @@ paths: description: 'OK' '400': description: Bad Request + /required_octet_stream: + put: + requestBody: + required: true + content: + application/octet-stream: + schema: + type: string + format: byte + responses: + '200': + description: 'OK' components: schemas: + UuidObject: + description: Test a model containing a UUID + type: string + format: uuid xml_array: xml: name: CamelXmlArray diff --git a/samples/server/petstore/rust-server/output/openapi-v3/README.md b/samples/server/petstore/rust-server/output/openapi-v3/README.md index 25f25740576..706821945d8 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/README.md +++ b/samples/server/petstore/rust-server/output/openapi-v3/README.md @@ -55,6 +55,7 @@ cargo run --example server To run a client, follow one of the following simple steps: ``` +cargo run --example client RequiredOctetStreamPut cargo run --example client XmlExtraPost cargo run --example client XmlOtherPost cargo run --example client XmlOtherPut @@ -113,6 +114,7 @@ All URIs are relative to *http://localhost* Method | HTTP request | Description ------------- | ------------- | ------------- +[****](docs/default_api.md#) | **PUT** /required_octet_stream | [****](docs/default_api.md#) | **POST** /xml_extra | [****](docs/default_api.md#) | **POST** /xml_other | [****](docs/default_api.md#) | **PUT** /xml_other | @@ -126,6 +128,7 @@ Method | HTTP request | Description - [AnotherXmlInner](docs/AnotherXmlInner.md) - [AnotherXmlObject](docs/AnotherXmlObject.md) - [DuplicateXmlObject](docs/DuplicateXmlObject.md) + - [UuidObject](docs/UuidObject.md) - [XmlArray](docs/XmlArray.md) - [XmlInner](docs/XmlInner.md) - [XmlObject](docs/XmlObject.md) 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 56f6d12c997..f9282ee3115 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 @@ -65,8 +65,24 @@ paths: description: OK 400: description: Bad Request + /required_octet_stream: + put: + requestBody: + content: + application/octet-stream: + schema: + format: byte + type: string + required: true + responses: + 200: + description: OK components: schemas: + UuidObject: + description: Test a model containing a UUID + format: uuid + type: string xml_array: items: $ref: '#/components/schemas/xml_inner' diff --git a/samples/server/petstore/rust-server/output/openapi-v3/docs/UuidObject.md b/samples/server/petstore/rust-server/output/openapi-v3/docs/UuidObject.md new file mode 100644 index 00000000000..d308889dad4 --- /dev/null +++ b/samples/server/petstore/rust-server/output/openapi-v3/docs/UuidObject.md @@ -0,0 +1,9 @@ +# UuidObject + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + 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 baf8c265cfb..0ec3e5c9f1f 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 @@ -4,6 +4,7 @@ All URIs are relative to *http://localhost* Method | HTTP request | Description ------------- | ------------- | ------------- +****](default_api.md#) | **PUT** /required_octet_stream | ****](default_api.md#) | **POST** /xml_extra | ****](default_api.md#) | **POST** /xml_other | ****](default_api.md#) | **PUT** /xml_other | @@ -11,6 +12,31 @@ Method | HTTP request | Description ****](default_api.md#) | **PUT** /xml | +# **** +> (body) + + +### Required Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **body** | **swagger::ByteArray**| | + +### Return type + + (empty response body) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: application/octet-stream + - **Accept**: Not defined + +[[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) diff --git a/samples/server/petstore/rust-server/output/openapi-v3/examples/client.rs b/samples/server/petstore/rust-server/output/openapi-v3/examples/client.rs index 2d88c04aebe..b94f7347967 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/examples/client.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/examples/client.rs @@ -19,6 +19,7 @@ use tokio_core::reactor; #[allow(unused_imports)] use openapi_v3::{ApiNoContext, ContextWrapperExt, ApiError, + RequiredOctetStreamPutResponse, XmlExtraPostResponse, XmlOtherPostResponse, XmlOtherPutResponse, @@ -32,6 +33,7 @@ fn main() { .arg(Arg::with_name("operation") .help("Sets the operation to run") .possible_values(&[ + "RequiredOctetStreamPut", "XmlExtraPost", "XmlOtherPost", "XmlOtherPut", @@ -77,6 +79,11 @@ fn main() { match matches.value_of("operation") { + Some("RequiredOctetStreamPut") => { + let result = core.run(client.required_octet_stream_put(swagger::ByteArray(Vec::from("BYTE_ARRAY_DATA_HERE")))); + println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &Has).get().clone()); + }, + Some("XmlExtraPost") => { let result = core.run(client.xml_extra_post(None)); println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &Has).get().clone()); diff --git a/samples/server/petstore/rust-server/output/openapi-v3/examples/server_lib/server.rs b/samples/server/petstore/rust-server/output/openapi-v3/examples/server_lib/server.rs index 1a2c6ff3821..9e28fb179ab 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/examples/server_lib/server.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/examples/server_lib/server.rs @@ -11,6 +11,7 @@ use swagger; use swagger::{Has, XSpanIdString}; use openapi_v3::{Api, ApiError, + RequiredOctetStreamPutResponse, XmlExtraPostResponse, XmlOtherPostResponse, XmlOtherPutResponse, @@ -33,6 +34,13 @@ impl Server { impl Api for Server where C: Has{ + fn required_octet_stream_put(&self, body: swagger::ByteArray, context: &C) -> Box> { + let context = context.clone(); + println!("required_octet_stream_put({:?}) - X-Span-ID: {:?}", body, context.get().0.clone()); + Box::new(futures::failed("Generic failure".into())) + } + + fn xml_extra_post(&self, duplicate_xml_object: Option, context: &C) -> Box> { let context = context.clone(); println!("xml_extra_post({:?}) - X-Span-ID: {:?}", duplicate_xml_object, context.get().0.clone()); 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 653382b7d9f..855f89cfce3 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 @@ -40,6 +40,7 @@ use swagger; use swagger::{ApiError, XSpanId, XSpanIdString, Has, AuthData}; use {Api, + RequiredOctetStreamPutResponse, XmlExtraPostResponse, XmlOtherPostResponse, XmlOtherPutResponse, @@ -250,6 +251,76 @@ impl Api for Client where F: Future + 'static, C: Has { + fn required_octet_stream_put(&self, param_body: swagger::ByteArray, context: &C) -> Box> { + let mut uri = format!( + "{}/required_octet_stream", + self.base_path + ); + + let mut query_string = self::url::form_urlencoded::Serializer::new("".to_owned()); + + + let query_string_str = query_string.finish(); + if !query_string_str.is_empty() { + uri += "?"; + uri += &query_string_str; + } + + let uri = match Uri::from_str(&uri) { + Ok(uri) => uri, + Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to build URI: {}", err))))), + }; + + let mut request = hyper::Request::new(hyper::Method::Put, uri); + + + // Body parameter + let body = param_body.0; + + request.set_body(body); + + + request.headers_mut().set(ContentType(mimetypes::requests::REQUIRED_OCTET_STREAM_PUT.clone())); + request.headers_mut().set(XSpanId((context as &Has).get().0.clone())); + + + Box::new(self.client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))) + .and_then(|mut response| { + match response.status().as_u16() { + 200 => { + let body = response.body(); + Box::new( + + future::ok( + RequiredOctetStreamPutResponse::OK + ) + ) as Box> + }, + code => { + let headers = response.headers().clone(); + Box::new(response.body() + .take(100) + .concat2() + .then(move |body| + future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(ref body) => match str::from_utf8(body) { + Ok(body) => Cow::from(body), + Err(e) => Cow::from(format!("", e)), + }, + Err(e) => Cow::from(format!("", e)), + }))) + ) + ) as Box> + } + } + })) + + } + fn xml_extra_post(&self, param_duplicate_xml_object: Option, context: &C) -> Box> { let mut uri = format!( "{}/xml_extra", @@ -272,14 +343,12 @@ impl Api for Client where let mut request = hyper::Request::new(hyper::Method::Post, uri); - - // Body parameter let body = param_duplicate_xml_object.map(|ref body| { body.to_xml() }); if let Some(body) = body { - request.set_body(body.into_bytes()); + request.set_body(body); } request.headers_mut().set(ContentType(mimetypes::requests::XML_EXTRA_POST.clone())); @@ -359,7 +428,7 @@ if let Some(body) = body { }); if let Some(body) = body { - request.set_body(body.into_bytes()); + request.set_body(body); } request.headers_mut().set(ContentType(mimetypes::requests::XML_OTHER_POST.clone())); @@ -439,7 +508,7 @@ if let Some(body) = body { }); if let Some(body) = body { - request.set_body(body.into_bytes()); + request.set_body(body); } request.headers_mut().set(ContentType(mimetypes::requests::XML_OTHER_PUT.clone())); @@ -519,7 +588,7 @@ if let Some(body) = body { }); if let Some(body) = body { - request.set_body(body.into_bytes()); + request.set_body(body); } request.headers_mut().set(ContentType(mimetypes::requests::XML_POST.clone())); @@ -599,7 +668,7 @@ if let Some(body) = body { }); if let Some(body) = body { - request.set_body(body.into_bytes()); + request.set_body(body); } request.headers_mut().set(ContentType(mimetypes::requests::XML_PUT.clone())); 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 88ecd9b8b44..45731e516ac 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 @@ -39,6 +39,12 @@ pub const BASE_PATH: &'static str = ""; pub const API_VERSION: &'static str = "1.0.7"; +#[derive(Debug, PartialEq)] +pub enum RequiredOctetStreamPutResponse { + /// OK + OK , +} + #[derive(Debug, PartialEq)] pub enum XmlExtraPostResponse { /// OK @@ -84,6 +90,9 @@ pub enum XmlPutResponse { pub trait Api { + fn required_octet_stream_put(&self, body: swagger::ByteArray, context: &C) -> Box>; + + fn xml_extra_post(&self, duplicate_xml_object: Option, context: &C) -> Box>; @@ -104,6 +113,9 @@ pub trait Api { pub trait ApiNoContext { + fn required_octet_stream_put(&self, body: swagger::ByteArray) -> Box>; + + fn xml_extra_post(&self, duplicate_xml_object: Option) -> Box>; @@ -135,6 +147,11 @@ impl<'a, T: Api + Sized, C> ContextWrapperExt<'a, C> for T { impl<'a, T: Api, C> ApiNoContext for ContextWrapper<'a, T, C> { + fn required_octet_stream_put(&self, body: swagger::ByteArray) -> Box> { + self.api().required_octet_stream_put(body, &self.context()) + } + + fn xml_extra_post(&self, duplicate_xml_object: Option) -> Box> { self.api().xml_extra_post(duplicate_xml_object, &self.context()) } 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 92a7cd5812e..83396a3fa0c 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 @@ -9,6 +9,10 @@ pub mod responses { pub mod requests { use hyper::mime::*; + /// Create Mime objects for the request content types for RequiredOctetStreamPut + lazy_static! { + pub static ref REQUIRED_OCTET_STREAM_PUT: Mime = "application/octet-stream".parse().unwrap(); + } /// Create Mime objects for the request content types for XmlExtraPost lazy_static! { pub static ref XML_EXTRA_POST: Mime = "application/xml".parse().unwrap(); diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/models.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/models.rs index 144de335195..303637592d4 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/models.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/models.rs @@ -8,6 +8,8 @@ use serde::ser::Serializer; use std::collections::{HashMap, BTreeMap}; use models; use swagger; +use std::string::ParseError; + // Utility function for wrapping list elements when serializing xml @@ -100,6 +102,13 @@ impl ::std::convert::From for AnotherXmlInner { } } +impl std::str::FromStr for AnotherXmlInner { + type Err = ParseError; + fn from_str(x: &str) -> Result { + Ok(AnotherXmlInner(x.to_string())) + } +} + impl ::std::convert::From for String { fn from(x: AnotherXmlInner) -> Self { x.0 @@ -206,6 +215,47 @@ impl DuplicateXmlObject { } } +/// Test a model containing a UUID +#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)] + +pub struct UuidObject(uuid::Uuid); + +impl ::std::convert::From for UuidObject { + fn from(x: uuid::Uuid) -> Self { + UuidObject(x) + } +} + + +impl ::std::convert::From for uuid::Uuid { + fn from(x: UuidObject) -> Self { + x.0 + } +} + +impl ::std::ops::Deref for UuidObject { + type Target = uuid::Uuid; + fn deref(&self) -> &uuid::Uuid { + &self.0 + } +} + +impl ::std::ops::DerefMut for UuidObject { + fn deref_mut(&mut self) -> &mut uuid::Uuid { + &mut self.0 + } +} + + +impl UuidObject { + /// Helper function to allow us to convert this model to an XML string. + /// Will panic if serialisation fails. + #[allow(dead_code)] + pub(crate) fn to_xml(&self) -> String { + serde_xml_rs::to_string(&self).expect("impossible to fail to serialize") + } +} + // Utility function for wrapping list elements when serializing xml #[allow(non_snake_case)] fn wrap_in_camelXmlInner(item: &Vec, serializer: S) -> Result @@ -296,6 +346,13 @@ impl ::std::convert::From for XmlInner { } } +impl std::str::FromStr for XmlInner { + type Err = ParseError; + fn from_str(x: &str) -> Result { + Ok(XmlInner(x.to_string())) + } +} + impl ::std::convert::From for String { fn from(x: XmlInner) -> Self { x.0 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 f86af16049b..f96ba0a9c5d 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 @@ -37,6 +37,7 @@ use swagger::{ApiError, XSpanId, XSpanIdString, Has, RequestParser}; use swagger::auth::Scopes; use {Api, + RequiredOctetStreamPutResponse, XmlExtraPostResponse, XmlOtherPostResponse, XmlOtherPutResponse, @@ -55,14 +56,16 @@ mod paths { lazy_static! { pub static ref GLOBAL_REGEX_SET: regex::RegexSet = regex::RegexSet::new(&[ + r"^/required_octet_stream$", r"^/xml$", r"^/xml_extra$", r"^/xml_other$" ]).unwrap(); } - pub static ID_XML: usize = 0; - pub static ID_XML_EXTRA: usize = 1; - pub static ID_XML_OTHER: usize = 2; + pub static ID_REQUIRED_OCTET_STREAM: usize = 0; + pub static ID_XML: usize = 1; + pub static ID_XML_EXTRA: usize = 2; + pub static ID_XML_OTHER: usize = 3; } pub struct NewService { @@ -128,6 +131,71 @@ where // Please update both places if changing how this code is autogenerated. match &method { + // RequiredOctetStreamPut - PUT /required_octet_stream + &hyper::Method::Put if path.matched(paths::ID_REQUIRED_OCTET_STREAM) => { + + + + + + + // Body parameters (note that non-required body parameters will ignore garbage + // values, rather than causing a 400 response). Produce warning header and logs for + // any unused fields. + Box::new(body.concat2() + .then(move |result| -> Box> { + match result { + Ok(body) => { + let param_body: Option = if !body.is_empty() { + + Some(swagger::ByteArray(body.to_vec())) + + } else { + None + }; + let param_body = match param_body { + Some(param_body) => param_body, + None => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body("Missing required body parameter body"))), + }; + + + Box::new(api_impl.required_octet_stream_put(param_body, &context) + .then(move |result| { + let mut response = Response::new(); + response.headers_mut().set(XSpanId((&context as &Has).get().0.to_string())); + + match result { + Ok(rsp) => match rsp { + RequiredOctetStreamPutResponse::OK + + + => { + response.set_status(StatusCode::try_from(200).unwrap()); + + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + response.set_status(StatusCode::InternalServerError); + response.set_body("An internal error occurred"); + }, + } + + future::ok(response) + } + )) + + + }, + Err(e) => Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't read body parameter body: {}", e)))), + } + }) + ) as Box> + + }, + + // XmlExtraPost - POST /xml_extra &hyper::Method::Post if path.matched(paths::ID_XML_EXTRA) => { @@ -560,6 +628,9 @@ impl RequestParser for ApiRequestParser { let path = paths::GLOBAL_REGEX_SET.matches(request.uri().path()); match request.method() { + // RequiredOctetStreamPut - PUT /required_octet_stream + &hyper::Method::Put if path.matched(paths::ID_REQUIRED_OCTET_STREAM) => Ok("RequiredOctetStreamPut"), + // XmlExtraPost - POST /xml_extra &hyper::Method::Post if path.matched(paths::ID_XML_EXTRA) => Ok("XmlExtraPost"), diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/client/mod.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/client/mod.rs index a38838b0c6a..2ef91fd174c 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/client/mod.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/client/mod.rs @@ -303,7 +303,7 @@ impl Api for Client where // Body parameter let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); - request.set_body(body.into_bytes()); + request.set_body(body); request.headers_mut().set(ContentType(mimetypes::requests::TEST_SPECIAL_TAGS.clone())); @@ -320,17 +320,20 @@ impl Api for Client where body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| str::from_utf8(&body) + .and_then(|body| + + str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) .and_then(|body| serde_json::from_str::(body) .map_err(|e| e.into()) + ) - )) - .map(move |body| + ) + .map(move |body| { TestSpecialTagsResponse::SuccessfulOperation(body) - ) + }) ) as Box> }, code => { @@ -386,7 +389,7 @@ impl Api for Client where }); if let Some(body) = body { - request.set_body(body.into_bytes()); + request.set_body(body); } request.headers_mut().set(ContentType(mimetypes::requests::FAKE_OUTER_BOOLEAN_SERIALIZE.clone())); @@ -403,17 +406,20 @@ if let Some(body) = body { body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| str::from_utf8(&body) + .and_then(|body| + + str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) .and_then(|body| serde_json::from_str::(body) .map_err(|e| e.into()) + ) - )) - .map(move |body| + ) + .map(move |body| { FakeOuterBooleanSerializeResponse::OutputBoolean(body) - ) + }) ) as Box> }, code => { @@ -467,7 +473,7 @@ if let Some(body) = body { }); if let Some(body) = body { - request.set_body(body.into_bytes()); + request.set_body(body); } request.headers_mut().set(ContentType(mimetypes::requests::FAKE_OUTER_COMPOSITE_SERIALIZE.clone())); @@ -484,17 +490,20 @@ if let Some(body) = body { body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| str::from_utf8(&body) + .and_then(|body| + + str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) .and_then(|body| serde_json::from_str::(body) .map_err(|e| e.into()) + ) - )) - .map(move |body| + ) + .map(move |body| { FakeOuterCompositeSerializeResponse::OutputComposite(body) - ) + }) ) as Box> }, code => { @@ -548,7 +557,7 @@ if let Some(body) = body { }); if let Some(body) = body { - request.set_body(body.into_bytes()); + request.set_body(body); } request.headers_mut().set(ContentType(mimetypes::requests::FAKE_OUTER_NUMBER_SERIALIZE.clone())); @@ -565,17 +574,20 @@ if let Some(body) = body { body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| str::from_utf8(&body) + .and_then(|body| + + str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) .and_then(|body| serde_json::from_str::(body) .map_err(|e| e.into()) + ) - )) - .map(move |body| + ) + .map(move |body| { FakeOuterNumberSerializeResponse::OutputNumber(body) - ) + }) ) as Box> }, code => { @@ -629,7 +641,7 @@ if let Some(body) = body { }); if let Some(body) = body { - request.set_body(body.into_bytes()); + request.set_body(body); } request.headers_mut().set(ContentType(mimetypes::requests::FAKE_OUTER_STRING_SERIALIZE.clone())); @@ -646,17 +658,20 @@ if let Some(body) = body { body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| str::from_utf8(&body) + .and_then(|body| + + str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) .and_then(|body| serde_json::from_str::(body) .map_err(|e| e.into()) + ) - )) - .map(move |body| + ) + .map(move |body| { FakeOuterStringSerializeResponse::OutputString(body) - ) + }) ) as Box> }, code => { @@ -708,7 +723,7 @@ if let Some(body) = body { let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); - request.set_body(body.into_bytes()); + request.set_body(body); request.headers_mut().set(ContentType(mimetypes::requests::TEST_BODY_WITH_QUERY_PARAMS.clone())); @@ -776,7 +791,7 @@ if let Some(body) = body { let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); - request.set_body(body.into_bytes()); + request.set_body(body); request.headers_mut().set(ContentType(mimetypes::requests::TEST_CLIENT_MODEL.clone())); @@ -793,17 +808,20 @@ if let Some(body) = body { body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| str::from_utf8(&body) + .and_then(|body| + + str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) .and_then(|body| serde_json::from_str::(body) .map_err(|e| e.into()) + ) - )) - .map(move |body| + ) + .map(move |body| { TestClientModelResponse::SuccessfulOperation(body) - ) + }) ) as Box> }, code => { @@ -1047,7 +1065,7 @@ if let Some(body) = body { let body = serde_json::to_string(¶m_param).expect("impossible to fail to serialize"); - request.set_body(body.into_bytes()); + request.set_body(body); request.headers_mut().set(ContentType(mimetypes::requests::TEST_INLINE_ADDITIONAL_PROPERTIES.clone())); @@ -1191,7 +1209,7 @@ if let Some(body) = body { // Body parameter let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); - request.set_body(body.into_bytes()); + request.set_body(body); request.headers_mut().set(ContentType(mimetypes::requests::TEST_CLASSNAME.clone())); @@ -1208,17 +1226,20 @@ if let Some(body) = body { body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| str::from_utf8(&body) + .and_then(|body| + + str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) .and_then(|body| serde_json::from_str::(body) .map_err(|e| e.into()) + ) - )) - .map(move |body| + ) + .map(move |body| { TestClassnameResponse::SuccessfulOperation(body) - ) + }) ) as Box> }, code => { @@ -1271,7 +1292,7 @@ if let Some(body) = body { // Body parameter let body = param_body.to_xml(); - request.set_body(body.into_bytes()); + request.set_body(body); request.headers_mut().set(ContentType(mimetypes::requests::ADD_PET.clone())); @@ -1419,19 +1440,21 @@ if let Some(body) = body { body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| str::from_utf8(&body) + .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| + ) + .map(move |body| { FindPetsByStatusResponse::SuccessfulOperation(body) - ) + }) ) as Box> }, 400 => { @@ -1504,19 +1527,21 @@ if let Some(body) = body { body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| str::from_utf8(&body) + .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| + ) + .map(move |body| { FindPetsByTagsResponse::SuccessfulOperation(body) - ) + }) ) as Box> }, 400 => { @@ -1593,19 +1618,21 @@ if let Some(body) = body { body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| str::from_utf8(&body) + .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| + ) + .map(move |body| { GetPetByIdResponse::SuccessfulOperation(body) - ) + }) ) as Box> }, 400 => { @@ -1674,7 +1701,7 @@ if let Some(body) = body { let body = param_body.to_xml(); - request.set_body(body.into_bytes()); + request.set_body(body); request.headers_mut().set(ContentType(mimetypes::requests::UPDATE_PET.clone())); @@ -1849,17 +1876,20 @@ if let Some(body) = body { body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| str::from_utf8(&body) + .and_then(|body| + + str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) .and_then(|body| serde_json::from_str::(body) .map_err(|e| e.into()) + ) - )) - .map(move |body| + ) + .map(move |body| { UploadFileResponse::SuccessfulOperation(body) - ) + }) ) as Box> }, code => { @@ -1999,17 +2029,20 @@ if let Some(body) = body { body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| str::from_utf8(&body) + .and_then(|body| + + str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) .and_then(|body| serde_json::from_str::>(body) .map_err(|e| e.into()) + ) - )) - .map(move |body| + ) + .map(move |body| { GetInventoryResponse::SuccessfulOperation(body) - ) + }) ) as Box> }, code => { @@ -2072,19 +2105,21 @@ if let Some(body) = body { body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| str::from_utf8(&body) + .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| + ) + .map(move |body| { GetOrderByIdResponse::SuccessfulOperation(body) - ) + }) ) as Box> }, 400 => { @@ -2153,7 +2188,7 @@ if let Some(body) = body { let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); - request.set_body(body.into_bytes()); + request.set_body(body); request.headers_mut().set(ContentType(mimetypes::requests::PLACE_ORDER.clone())); @@ -2170,19 +2205,21 @@ if let Some(body) = body { body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| str::from_utf8(&body) + .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| + ) + .map(move |body| { PlaceOrderResponse::SuccessfulOperation(body) - ) + }) ) as Box> }, 400 => { @@ -2244,7 +2281,7 @@ if let Some(body) = body { // Body parameter let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); - request.set_body(body.into_bytes()); + request.set_body(body); request.headers_mut().set(ContentType(mimetypes::requests::CREATE_USER.clone())); @@ -2312,7 +2349,7 @@ if let Some(body) = body { let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); - request.set_body(body.into_bytes()); + request.set_body(body); request.headers_mut().set(ContentType(mimetypes::requests::CREATE_USERS_WITH_ARRAY_INPUT.clone())); @@ -2380,7 +2417,7 @@ if let Some(body) = body { let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); - request.set_body(body.into_bytes()); + request.set_body(body); request.headers_mut().set(ContentType(mimetypes::requests::CREATE_USERS_WITH_LIST_INPUT.clone())); @@ -2532,19 +2569,21 @@ if let Some(body) = body { body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| str::from_utf8(&body) + .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| + ) + .map(move |body| { GetUserByNameResponse::SuccessfulOperation(body) - ) + }) ) as Box> }, 400 => { @@ -2637,19 +2676,21 @@ if let Some(body) = body { body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| str::from_utf8(&body) + .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| + ) + .map(move |body| { LoginUserResponse::SuccessfulOperation{ body: body, x_rate_limit: response_x_rate_limit, x_expires_after: response_x_expires_after } - ) + }) ) as Box> }, 400 => { @@ -2772,7 +2813,7 @@ if let Some(body) = body { let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); - request.set_body(body.into_bytes()); + request.set_body(body); request.headers_mut().set(ContentType(mimetypes::requests::UPDATE_USER.clone())); diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/models.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/models.rs index b04e3de61b1..5abb001308f 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/models.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/models.rs @@ -8,6 +8,8 @@ use serde::ser::Serializer; use std::collections::{HashMap, BTreeMap}; use models; use swagger; +use std::string::ParseError; + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] @@ -995,6 +997,7 @@ impl ::std::convert::From for OuterBoolean { } } + impl ::std::convert::From for bool { fn from(x: OuterBoolean) -> Self { x.0 @@ -1115,6 +1118,7 @@ impl ::std::convert::From for OuterNumber { } } + impl ::std::convert::From for f64 { fn from(x: OuterNumber) -> Self { x.0 @@ -1154,6 +1158,13 @@ impl ::std::convert::From for OuterString { } } +impl std::str::FromStr for OuterString { + type Err = ParseError; + fn from_str(x: &str) -> Result { + Ok(OuterString(x.to_string())) + } +} + impl ::std::convert::From for String { fn from(x: OuterString) -> Self { x.0 diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/server/mod.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/server/mod.rs index 72694a9cef1..898516f3f25 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/server/mod.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/server/mod.rs @@ -1350,7 +1350,7 @@ where let param_pet_id = match percent_encoding::percent_decode(path_params["petId"].as_bytes()).decode_utf8() { Ok(param_pet_id) => match param_pet_id.parse::() { Ok(param_pet_id) => param_pet_id, - Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse path parameter petId: {}", e)))), + Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse path parameter petId: {:?}", e)))), }, Err(_) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["petId"])))) }; @@ -1613,7 +1613,7 @@ where let param_pet_id = match percent_encoding::percent_decode(path_params["petId"].as_bytes()).decode_utf8() { Ok(param_pet_id) => match param_pet_id.parse::() { Ok(param_pet_id) => param_pet_id, - Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse path parameter petId: {}", e)))), + Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse path parameter petId: {:?}", e)))), }, Err(_) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["petId"])))) }; @@ -1843,7 +1843,7 @@ where let param_pet_id = match percent_encoding::percent_decode(path_params["petId"].as_bytes()).decode_utf8() { Ok(param_pet_id) => match param_pet_id.parse::() { Ok(param_pet_id) => param_pet_id, - Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse path parameter petId: {}", e)))), + Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse path parameter petId: {:?}", e)))), }, Err(_) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["petId"])))) }; @@ -1936,7 +1936,7 @@ where let param_pet_id = match percent_encoding::percent_decode(path_params["petId"].as_bytes()).decode_utf8() { Ok(param_pet_id) => match param_pet_id.parse::() { Ok(param_pet_id) => param_pet_id, - Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse path parameter petId: {}", e)))), + Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse path parameter petId: {:?}", e)))), }, Err(_) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["petId"])))) }; @@ -2010,7 +2010,7 @@ where let param_order_id = match percent_encoding::percent_decode(path_params["order_id"].as_bytes()).decode_utf8() { Ok(param_order_id) => match param_order_id.parse::() { Ok(param_order_id) => param_order_id, - Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse path parameter order_id: {}", e)))), + Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse path parameter order_id: {:?}", e)))), }, Err(_) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["order_id"])))) }; @@ -2142,7 +2142,7 @@ where let param_order_id = match percent_encoding::percent_decode(path_params["order_id"].as_bytes()).decode_utf8() { Ok(param_order_id) => match param_order_id.parse::() { Ok(param_order_id) => param_order_id, - Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse path parameter order_id: {}", e)))), + Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse path parameter order_id: {:?}", e)))), }, Err(_) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["order_id"])))) }; @@ -2557,7 +2557,7 @@ where let param_username = match percent_encoding::percent_decode(path_params["username"].as_bytes()).decode_utf8() { Ok(param_username) => match param_username.parse::() { Ok(param_username) => param_username, - Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse path parameter username: {}", e)))), + Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse path parameter username: {:?}", e)))), }, Err(_) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["username"])))) }; @@ -2626,7 +2626,7 @@ where let param_username = match percent_encoding::percent_decode(path_params["username"].as_bytes()).decode_utf8() { Ok(param_username) => match param_username.parse::() { Ok(param_username) => param_username, - Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse path parameter username: {}", e)))), + Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse path parameter username: {:?}", e)))), }, Err(_) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["username"])))) }; @@ -2849,7 +2849,7 @@ where let param_username = match percent_encoding::percent_decode(path_params["username"].as_bytes()).decode_utf8() { Ok(param_username) => match param_username.parse::() { Ok(param_username) => param_username, - Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse path parameter username: {}", e)))), + Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse path parameter username: {:?}", e)))), }, Err(_) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["username"])))) }; diff --git a/samples/server/petstore/rust-server/output/rust-server-test/src/client/mod.rs b/samples/server/petstore/rust-server/output/rust-server-test/src/client/mod.rs index 31971437c07..0835b2a79c3 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/src/client/mod.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/src/client/mod.rs @@ -337,7 +337,7 @@ impl Api for Client where let body = serde_json::to_string(¶m_nested_response).expect("impossible to fail to serialize"); - request.set_body(body.into_bytes()); + request.set_body(body); request.headers_mut().set(ContentType(mimetypes::requests::DUMMY_PUT.clone())); @@ -417,17 +417,20 @@ impl Api for Client where body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| str::from_utf8(&body) + .and_then(|body| + + str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) .and_then(|body| serde_json::from_str::(body) .map_err(|e| e.into()) + ) - )) - .map(move |body| + ) + .map(move |body| { FileResponseGetResponse::Success(body) - ) + }) ) as Box> }, code => { @@ -478,7 +481,7 @@ impl Api for Client where let body = param_body; - request.set_body(body.into_bytes()); + request.set_body(body); request.headers_mut().set(ContentType(mimetypes::requests::HTML_POST.clone())); @@ -495,16 +498,20 @@ impl Api for Client where body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| str::from_utf8(&body) + .and_then(|body| + + str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) .and_then(|body| - Ok(body.to_string()) + serde_json::from_str::(body) + .map_err(|e| e.into()) + ) - )) - .map(move |body| + ) + .map(move |body| { HtmlPostResponse::Success(body) - ) + }) ) as Box> }, code => { @@ -567,17 +574,20 @@ impl Api for Client where body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| str::from_utf8(&body) + .and_then(|body| + + str::from_utf8(&body) .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) .and_then(|body| serde_json::from_str::(body) .map_err(|e| e.into()) + ) - )) - .map(move |body| + ) + .map(move |body| { RawJsonGetResponse::Success(body) - ) + }) ) as Box> }, code => { diff --git a/samples/server/petstore/rust-server/output/rust-server-test/src/models.rs b/samples/server/petstore/rust-server/output/rust-server-test/src/models.rs index 36051fd4b7a..257ce5d2694 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/src/models.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/src/models.rs @@ -7,6 +7,8 @@ use serde::ser::Serializer; use std::collections::HashMap; use models; use swagger; +use std::string::ParseError; + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] diff --git a/samples/server/petstore/rust-server/output/rust-server-test/src/server/mod.rs b/samples/server/petstore/rust-server/output/rust-server-test/src/server/mod.rs index 3a9ba4b43c9..1312c9d0183 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/src/server/mod.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/src/server/mod.rs @@ -326,10 +326,7 @@ where Ok(body) => { let param_body: Option = if !body.is_empty() { - match String::from_utf8(body.to_vec()) { - Ok(param_body) => Some(param_body), - Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse body parameter body - not valid UTF-8: {}", e)))), - } + Some(String::from_utf8(body.to_vec()).unwrap()) } else { None @@ -358,6 +355,8 @@ where response.headers_mut().set(ContentType(mimetypes::responses::HTML_POST_SUCCESS.clone())); + let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); + response.set_body(body); }, },