From ab9be95442520135f03af1d72eaa6f14e1607531 Mon Sep 17 00:00:00 2001 From: Reinhard Pilz Date: Thu, 19 Jul 2018 17:16:15 +0200 Subject: [PATCH 01/13] Fix arrays with maxItems 2147483647 (#603) --- .../openapitools/codegen/examples/ExampleGenerator.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/examples/ExampleGenerator.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/examples/ExampleGenerator.java index 30472ba30bb..8bce5a3cd1e 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/examples/ExampleGenerator.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/examples/ExampleGenerator.java @@ -191,7 +191,13 @@ public class ExampleGenerator { Schema innerType = ((ArraySchema) property).getItems(); if (innerType != null) { int arrayLength = null == ((ArraySchema) property).getMaxItems() ? 2 : ((ArraySchema) property).getMaxItems(); - if (arrayLength > 1024) { + if (arrayLength == Integer.MAX_VALUE) { + // swagger-jersey2-jaxrs generated spec may contain maxItem = 2147483647 + // semantically this means there is no upper limit + // treating this as if the property was not present at all + LOGGER.warn("The max items allowed in property {} of {} equals Integer.MAX_VALUE. Treating this as if no max items has been specified.", property, arrayLength); + arrayLength = 2; + } else if (arrayLength > 1024) { LOGGER.warn("The max items allowed in property {} is too large ({} items), restricting it to 1024 items", property, arrayLength); arrayLength = 1024; } From c70ed678f6205971bc3a208156ffac44a75c1118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthieu=20Berthom=C3=A9?= Date: Fri, 20 Jul 2018 07:21:36 +0200 Subject: [PATCH 02/13] Add "docExtension" option to customize generated file extension for docs (#591) --- .../openapitools/codegen/CodegenConfig.java | 4 +++ .../codegen/CodegenConstants.java | 3 ++ .../openapitools/codegen/DefaultCodegen.java | 29 ++++++++++++++++++- .../codegen/DefaultGenerator.java | 3 +- 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConfig.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConfig.java index bd3f11c0eaf..e91d00d4ce3 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConfig.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConfig.java @@ -230,6 +230,10 @@ public interface CodegenConfig { String getHttpUserAgent(); + void setDocExtension(String docExtension); + + String getDocExtension(); + String getCommonTemplateDir(); void setIgnoreFilePathOverride(String ignoreFileOverride); diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java index 34676479f3d..4be60e75a51 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenConstants.java @@ -254,4 +254,7 @@ public class CodegenConstants { public static final String STRIP_PACKAGE_NAME = "stripPackageName"; public static final String STRIP_PACKAGE_NAME_DESC = "Whether to strip leading dot-separated packages from generated model classes"; + + public static final String DOCEXTENSION = "docExtension"; + public static final String DOCEXTENSION_DESC = "The extension of the generated documentation files, defaults to markdown, .md"; } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index 96102e6981d..d7a04d25312 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -114,6 +114,8 @@ public class DefaultCodegen implements CodegenConfig { // When a model is an alias for a simple type protected Map typeAliases = null; protected Boolean prependFormOrBodyParameters = false; + // The extension of the generated documentation files (defaults to markdown .md) + protected String docExtension; protected String ignoreFilePathOverride; @@ -172,6 +174,11 @@ public class DefaultCodegen implements CodegenConfig { this.setRemoveOperationIdPrefix(Boolean.valueOf(additionalProperties .get(CodegenConstants.REMOVE_OPERATION_ID_PREFIX).toString())); } + + if (additionalProperties.containsKey(CodegenConstants.DOCEXTENSION)){ + this.setDocExtension(String.valueOf(additionalProperties + .get(CodegenConstants.DOCEXTENSION).toString())); + } } // override with any special post-processing for all models @@ -3415,7 +3422,8 @@ public class DefaultCodegen implements CodegenConfig { * @return the API documentation file name with full path */ public String apiDocFilename(String templateName, String tag) { - String suffix = apiDocTemplateFiles().get(templateName); + String docExtension = getDocExtension(); + String suffix = docExtension != null ? docExtension: apiDocTemplateFiles().get(templateName); return apiDocFileFolder() + File.separator + toApiDocFilename(tag) + suffix; } @@ -3552,6 +3560,25 @@ public class DefaultCodegen implements CodegenConfig { return releaseNote; } + /** + * Documentation files extension + * + * @return Documentation files extension + */ + public String getDocExtension() { + return docExtension; + } + + /** + * Set Documentation files extension + * + * @param userDocExtension documentation files extension + */ + public void setDocExtension(String userDocExtension) { + this.docExtension = userDocExtension; + } + + /** * Set HTTP user agent. * diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java index 4ddf0d86649..056f56307bf 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java @@ -278,7 +278,8 @@ public class DefaultGenerator extends AbstractGenerator implements Generator { private void generateModelDocumentation(List files, Map models, String modelName) throws IOException { for (String templateName : config.modelDocTemplateFiles().keySet()) { - String suffix = config.modelDocTemplateFiles().get(templateName); + String docExtension = config.getDocExtension(); + String suffix = docExtension!=null ? docExtension : config.modelDocTemplateFiles().get(templateName); String filename = config.modelDocFileFolder() + File.separator + config.toModelDocFilename(modelName) + suffix; if (!config.shouldOverwrite(filename)) { LOGGER.info("Skipped overwriting " + filename); From 1b2d12286f7fcd5b90fb016d776864dfb880ccca Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 20 Jul 2018 18:45:14 +0800 Subject: [PATCH 03/13] CircleCI: run Java8, Java7 tests in parallel (#608) * run circle jobs in parallel * fix circleci file * disable parallel run * fix build type * fix circleci config parse error * move mvn install to circle.yml * revise circleci tests * trigger test failures * remove failure trigger --- CI/circle_parallel.sh | 19 +++++++++++++++++++ CI/pom.xml.circleci | 2 ++ CI/pom.xml.circleci.java7 | 3 --- circle.yml | 28 ++++++++-------------------- 4 files changed, 29 insertions(+), 23 deletions(-) create mode 100755 CI/circle_parallel.sh diff --git a/CI/circle_parallel.sh b/CI/circle_parallel.sh new file mode 100755 index 00000000000..3487a09bf6e --- /dev/null +++ b/CI/circle_parallel.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +NODE_INDEX=${CIRCLE_NODE_INDEX:-0} + + +if [ "$NODE_INDEX" = "1" ]; then + echo "Running node $NODE_INDEX to test CI/pom.xml.circleci ..." + cp CI/pom.xml.circleci pom.xml + java -version + mvn --quiet verify -Psamples +else + echo "Running node $NODE_INDEX to test CI/pom.xml.circleci.java7 ..." + sudo update-java-alternatives -s java-1.7.0-openjdk-amd64 + java -version + cp CI/pom.xml.circleci.java7 pom.xml + mvn --quiet verify -Psamples +fi + + diff --git a/CI/pom.xml.circleci b/CI/pom.xml.circleci index 77cdcd5f79d..7c65c920d66 100644 --- a/CI/pom.xml.circleci +++ b/CI/pom.xml.circleci @@ -844,10 +844,12 @@ samples/client/petstore/java/feign samples/client/petstore/java/jersey1 samples/client/petstore/java/jersey2 + samples/client/petstore/java/jersey2-java8 samples/client/petstore/java/okhttp-gson samples/client/petstore/java/retrofit samples/client/petstore/java/retrofit2 samples/client/petstore/java/retrofit2rx + samples/client/petstore/java/retrofit2-play25 samples/client/petstore/jaxrs-cxf-client samples/client/petstore/java/resttemplate samples/client/petstore/java/resttemplate-withXml diff --git a/CI/pom.xml.circleci.java7 b/CI/pom.xml.circleci.java7 index e3820742065..b1ca8600cc5 100644 --- a/CI/pom.xml.circleci.java7 +++ b/CI/pom.xml.circleci.java7 @@ -852,9 +852,6 @@ samples/client/petstore/java/resteasy samples/client/petstore/java/google-api-client samples/client/petstore/kotlin/ - - - samples/client/petstore/typescript-angular-v6-provided-in-root samples/server/petstore/java-vertx/rx samples/server/petstore/java-vertx/async diff --git a/circle.yml b/circle.yml index 844fa6a2710..bfbe40bcedd 100644 --- a/circle.yml +++ b/circle.yml @@ -1,10 +1,16 @@ version: 2 jobs: build: + # docker: + # #- image: openapitools/openapi-generator + # - image: swaggerapi/petstore + # environment: + # SWAGGER_HOST=http://petstore.swagger.io + # SWAGGER_BASE_PATH=/v2 machine: docker_layer_caching: true working_directory: ~/OpenAPITools/openapi-generator - parallelism: 1 + parallelism: 2 shell: /bin/bash --login environment: CIRCLE_ARTIFACTS: /tmp/circleci-artifacts @@ -37,12 +43,6 @@ jobs: printf '127.0.0.1 petstore.swagger.io ' | sudo tee -a /etc/hosts # Dependencies - # This would typically go in either a build or a build-and-test job when using workflows - # This is based on your 1.0 configuration file or project settings - - run: sudo add-apt-repository ppa:duggan/bats --yes - - run: sudo apt-get update -qq - - run: sudo apt-get install -qq bats - - run: sudo apt-get install -qq curl # Install latest stable node for angular 6 - run: name: Install node@stable (for angular 6) @@ -65,21 +65,9 @@ jobs: - run: docker ps -a - run: sleep 30 - run: cat /etc/hosts - # This is based on your 1.0 configuration file or project settings - - run: cp CI/pom.xml.circleci pom.xml # Test - # This would typically be a build job when using workflows, possibly combined with build - # This is based on your 1.0 configuration file or project settings - #- run: java -version - run: mvn --quiet clean install - - run: mvn --quiet verify -Psamples - - run: if [ $? -ne 0 ]; then exit 1; fi - - run: sudo update-java-alternatives -s java-1.7.0-openjdk-amd64 - - run: java -version - - run: cp CI/pom.xml.circleci.java7 pom.xml - - run: mvn --quiet clean install - - run: mvn --quiet verify -Psamples - - run: if [ $? -ne 0 ]; then exit 1; fi + - run: ./CI/circle_parallel.sh # Save dependency cache - save_cache: key: source-v1-{{ .Branch }}-{{ .Revision }} From 97d6b7146096537fc24dd1ed935523fc5298f08b Mon Sep 17 00:00:00 2001 From: sunn <33183834+etherealjoy@users.noreply.github.com> Date: Fri, 20 Jul 2018 16:04:25 +0200 Subject: [PATCH 04/13] [cpp-pistache] Fix compilation of petstore for Pistache (#497) * Fix compilation of petstore for Pistache Add Map support * Add support for ByteArray * Add Support for ByteArray in cpprest * Implement TODOs --- .../languages/CppPistacheServerCodegen.java | 12 +++ .../languages/CppRestSdkClientCodegen.java | 1 + .../cpp-pistache-server/api-source.mustache | 8 +- .../cpp-pistache-server/cmake.mustache | 2 +- .../cpp-pistache-server/model-source.mustache | 14 +-- .../modelbase-header.mustache | 99 ++++++++++++++++++- .../modelbase-source.mustache | 2 +- .../cpp-rest-sdk-client/model-source.mustache | 40 ++++---- .../petstore/cpp-pistache/CMakeLists.txt | 2 +- .../petstore/cpp-pistache/api/PetApi.cpp | 6 ++ .../server/petstore/cpp-pistache/api/PetApi.h | 4 +- .../petstore/cpp-pistache/api/StoreApi.cpp | 3 + .../petstore/cpp-pistache/api/StoreApi.h | 2 +- .../petstore/cpp-pistache/api/UserApi.cpp | 14 ++- .../petstore/cpp-pistache/api/UserApi.h | 4 +- .../petstore/cpp-pistache/impl/PetApiImpl.cpp | 4 +- .../petstore/cpp-pistache/impl/PetApiImpl.h | 4 +- .../cpp-pistache/impl/StoreApiImpl.cpp | 2 +- .../petstore/cpp-pistache/impl/StoreApiImpl.h | 2 +- .../cpp-pistache/impl/UserApiImpl.cpp | 4 +- .../petstore/cpp-pistache/impl/UserApiImpl.h | 4 +- .../cpp-pistache/model/ApiResponse.cpp | 2 - .../petstore/cpp-pistache/model/Category.cpp | 1 - .../petstore/cpp-pistache/model/ModelBase.cpp | 2 +- .../petstore/cpp-pistache/model/ModelBase.h | 99 ++++++++++++++++++- .../petstore/cpp-pistache/model/Order.cpp | 1 - .../petstore/cpp-pistache/model/Pet.cpp | 7 +- .../petstore/cpp-pistache/model/Tag.cpp | 1 - .../petstore/cpp-pistache/model/User.cpp | 6 -- 29 files changed, 284 insertions(+), 68 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppPistacheServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppPistacheServerCodegen.java index be50b3356a7..0516d237def 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppPistacheServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppPistacheServerCodegen.java @@ -102,6 +102,7 @@ public class CppPistacheServerCodegen extends AbstractCppCodegen { typeMapping.put("binary", "std::string"); typeMapping.put("number", "double"); typeMapping.put("UUID", "std::string"); + typeMapping.put("ByteArray", "std::string"); super.importMapping = new HashMap(); importMapping.put("std::vector", "#include "); @@ -292,6 +293,9 @@ public class CppPistacheServerCodegen extends AbstractCppCodegen { Schema inner = (Schema) p.getAdditionalProperties(); return getSchemaType(p) + ""; } + else if (ModelUtils.isByteArraySchema(p)) { + return "std::string"; + } if (ModelUtils.isStringSchema(p) || ModelUtils.isDateSchema(p) || ModelUtils.isDateTimeSchema(p) || ModelUtils.isFileSchema(p) @@ -320,6 +324,9 @@ public class CppPistacheServerCodegen extends AbstractCppCodegen { return "0L"; } return "0"; + } + else if (ModelUtils.isByteArraySchema(p)) { + return ""; } else if (ModelUtils.isMapSchema(p)) { String inner = getSchemaType((Schema) p.getAdditionalProperties()); return "std::map()"; @@ -403,4 +410,9 @@ public class CppPistacheServerCodegen extends AbstractCppCodegen { public String escapeUnsafeCharacters(String input) { return input.replace("*/", "*_/").replace("/*", "/_*"); } + + @Override + public String getTypeDeclaration(String str) { + return toModelName(str); + } } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestSdkClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestSdkClientCodegen.java index 4212923bc4d..0f6872b162e 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestSdkClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestSdkClientCodegen.java @@ -153,6 +153,7 @@ public class CppRestSdkClientCodegen extends AbstractCppCodegen { typeMapping.put("binary", "std::string"); typeMapping.put("number", "double"); typeMapping.put("UUID", "utility::string_t"); + typeMapping.put("ByteArray", "utility::string_t"); super.importMapping = new HashMap(); importMapping.put("std::vector", "#include "); diff --git a/modules/openapi-generator/src/main/resources/cpp-pistache-server/api-source.mustache b/modules/openapi-generator/src/main/resources/cpp-pistache-server/api-source.mustache index d815ce10ab7..b9e97395e41 100644 --- a/modules/openapi-generator/src/main/resources/cpp-pistache-server/api-source.mustache +++ b/modules/openapi-generator/src/main/resources/cpp-pistache-server/api-source.mustache @@ -52,8 +52,8 @@ void {{classname}}::{{operationIdSnakeCase}}_handler(const Pistache::Rest::Reque {{/hasPathParams}}{{#hasBodyParam}} // Getting the body param {{#bodyParam}} - {{^isPrimitiveType}} - {{baseType}} {{paramName}};{{/isPrimitiveType}} + {{^isPrimitiveType}}{{^isContainer}} + {{baseType}} {{paramName}};{{/isContainer}}{{#isListContainer}}std::vector<{{items.baseType}}> {{paramName}};{{/isListContainer}}{{#isMapContainer}}std::map {{paramName}};{{/isMapContainer}}{{/isPrimitiveType}} {{#isPrimitiveType}} {{dataType}} {{paramName}}; {{/isPrimitiveType}} @@ -74,9 +74,9 @@ void {{classname}}::{{operationIdSnakeCase}}_handler(const Pistache::Rest::Reque {{#hasBodyParam}} {{#bodyParam}} nlohmann::json request_body = nlohmann::json::parse(request.body()); - {{^isPrimitiveType}} + {{^isPrimitiveType}}{{^isContainer}} {{paramName}}.fromJson(request_body); - {{/isPrimitiveType}} + {{/isContainer}}{{/isPrimitiveType}}{{#isContainer}} {{paramName}} = {{#isListContainer}} ModelArrayHelper{{/isListContainer}}{{#isMapContainer}} ModelMapHelper{{/isMapContainer}}::fromJson<{{items.baseType}}>(request_body);{{/isContainer}} {{#isPrimitiveType}} // The conversion is done automatically by the json library {{paramName}} = request_body; diff --git a/modules/openapi-generator/src/main/resources/cpp-pistache-server/cmake.mustache b/modules/openapi-generator/src/main/resources/cpp-pistache-server/cmake.mustache index 12b066f22b7..0a6f820d30d 100644 --- a/modules/openapi-generator/src/main/resources/cpp-pistache-server/cmake.mustache +++ b/modules/openapi-generator/src/main/resources/cpp-pistache-server/cmake.mustache @@ -2,7 +2,7 @@ cmake_minimum_required (VERSION 3.2) project(server) -set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -std=c++11) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pg -g3" ) link_directories(/usr/local/lib/) diff --git a/modules/openapi-generator/src/main/resources/cpp-pistache-server/model-source.mustache b/modules/openapi-generator/src/main/resources/cpp-pistache-server/model-source.mustache index b2434df4670..7a36c378903 100644 --- a/modules/openapi-generator/src/main/resources/cpp-pistache-server/model-source.mustache +++ b/modules/openapi-generator/src/main/resources/cpp-pistache-server/model-source.mustache @@ -79,11 +79,11 @@ void {{classname}}::fromJson(nlohmann::json& val) {{/items.isDateTime}}{{^items.isDateTime}} if(item.is_null()) { - m_{{name}}.push_back( {{{items.datatype}}}(nullptr) ); + m_{{name}}.push_back( {{{items.datatype}}}() ); } else { - {{{items.datatype}}} newItem({{{items.defaultValue}}}); + {{{items.datatype}}} newItem; newItem.fromJson(item); m_{{name}}.push_back( newItem ); } @@ -95,15 +95,15 @@ void {{classname}}::fromJson(nlohmann::json& val) } {{/isListContainer}}{{^isListContainer}}{{^isPrimitiveType}}{{^required}}if(val.find("{{baseName}}") != val.end()) { - {{#isString}}{{setter}}(val.at("{{baseName}}")); - {{/isString}}{{^isString}}{{#isDateTime}}{{setter}}(val.at("{{baseName}}")); - {{/isDateTime}}{{^isDateTime}}if(!val["{{baseName}}"].is_null()) + {{#isString}}{{setter}}(val.at("{{baseName}}"));{{/isString}}{{#isByteArray}}{{setter}}(val.at("{{baseName}}")); + {{/isByteArray}}{{^isString}}{{#isDateTime}}{{setter}}(val.at("{{baseName}}")); + {{/isDateTime}}{{^isDateTime}}{{^isByteArray}}if(!val["{{baseName}}"].is_null()) { - {{{dataType}}} newItem({{{defaultValue}}}); + {{{dataType}}} newItem; newItem.fromJson(val["{{baseName}}"]); {{setter}}( newItem ); } - {{/isDateTime}}{{/isString}} + {{/isByteArray}}{{/isDateTime}}{{/isString}} } {{/required}}{{#required}}{{#isString}}{{setter}}(val.at("{{baseName}}")); {{/isString}}{{^isString}}{{#isDateTime}}{{setter}}(val.at("{{baseName}}")); diff --git a/modules/openapi-generator/src/main/resources/cpp-pistache-server/modelbase-header.mustache b/modules/openapi-generator/src/main/resources/cpp-pistache-server/modelbase-header.mustache index 2e43bb7b853..1cb28f0d988 100644 --- a/modules/openapi-generator/src/main/resources/cpp-pistache-server/modelbase-header.mustache +++ b/modules/openapi-generator/src/main/resources/cpp-pistache-server/modelbase-header.mustache @@ -12,6 +12,8 @@ #include "json.hpp" #include #include +#include +#include {{#modelNamespaceDeclarations}} namespace {{this}} { @@ -34,8 +36,103 @@ public: static int64_t toJson( int64_t const value ); static double toJson( double const value ); static bool toJson( bool const value ); - static nlohmann::json toJson(ModelBase const& content ); + static nlohmann::json toJson(ModelBase const& content ); +}; +class ModelArrayHelper { +public: + template + static std::vector fromJson(nlohmann::json& json) { + T *ptrTest; + std::vector val; + if (dynamic_cast(ptrTest) != nullptr) { + if (!json.empty()) { + for (auto &item : json.items()) { + T entry; + entry.fromJson(item.value()); + val.push_back(entry); + } + } + } + return val; + } + template + static nlohmann::json toJson(std::vector val) { + nlohmann::json json; + for(auto item : val){ + json.push_back(item.toJson()); + } + return json; + } +}; + +class ArrayHelper { +public: + template + static std::vector fromJson(nlohmann::json& json) { + std::vector val; + nlohmann::from_json(json, val); + return val; + } + template + static nlohmann::json toJson(std::vector val) { + nlohmann::json json; + nlohmann::to_json(json, val); + return json; + } +}; + +class ModelMapHelper { +public: + template + static std::map & fromJson(nlohmann::json& json) { + T *ptrTest; + std::map val; + if (dynamic_cast(ptrTest) != nullptr) { + if (!json.empty()) { + for (auto &item : json.items()) { + T entry; + entry.fromJson(item.value()); + val.insert(val.end(), + std::pair(item.key(), entry)); + } + } + } + return val; + } + template + static nlohmann::json toJson(std::map val) { + nlohmann::json json; + for (auto const& item : val) { + json[item.first] = item.second.toJson(); + } + return json; + } +}; + +class MapHelper { +public: + template + static std::map & fromJson(nlohmann::json& json) { + std::map val; + if (!json.empty()) { + for (auto &item : json.items()) { + T entry = item.value(); + val.insert(val.end(), + std::pair(item.key(), entry)); + } + } + return val; + } + template + static nlohmann::json toJson(std::map val) { + nlohmann::json json; + for (auto const& item : val) { + nlohmann::json jitem = item.second; + json[item.first] = jitem; + } + return json; + } }; {{#modelNamespaceDeclarations}} diff --git a/modules/openapi-generator/src/main/resources/cpp-pistache-server/modelbase-source.mustache b/modules/openapi-generator/src/main/resources/cpp-pistache-server/modelbase-source.mustache index a5ec9406c42..3bc4c644e42 100644 --- a/modules/openapi-generator/src/main/resources/cpp-pistache-server/modelbase-source.mustache +++ b/modules/openapi-generator/src/main/resources/cpp-pistache-server/modelbase-source.mustache @@ -44,7 +44,7 @@ bool ModelBase::toJson( bool const value ) return value; } -nlohmann::json ModelBase::toJson(ModelBase content ) +nlohmann::json ModelBase::toJson(ModelBase const& content ) { return content.toJson(); } diff --git a/modules/openapi-generator/src/main/resources/cpp-rest-sdk-client/model-source.mustache b/modules/openapi-generator/src/main/resources/cpp-rest-sdk-client/model-source.mustache index f650cc94f0a..e7f3cbeffc7 100644 --- a/modules/openapi-generator/src/main/resources/cpp-rest-sdk-client/model-source.mustache +++ b/modules/openapi-generator/src/main/resources/cpp-rest-sdk-client/model-source.mustache @@ -245,26 +245,29 @@ void {{classname}}::fromJson(web::json::value& val) {{#isString}} {{setter}}(ModelBase::stringFromJson(val[utility::conversions::to_string_t("{{baseName}}")])); {{/isString}} + {{#isByteArray}}{{setter}}(ModelBase::stringFromJson(val[utility::conversions::to_string_t("{{baseName}}")]));{{/isByteArray}} {{^isString}} {{#isDateTime}} {{setter}}(ModelBase::dateFromJson(val[utility::conversions::to_string_t("{{baseName}}")])); {{/isDateTime}} - {{^isDateTime}} + {{^isDateTime}}{{^isByteArray}} if(!val[utility::conversions::to_string_t("{{baseName}}")].is_null()) { {{{dataType}}} newItem({{{defaultValue}}}); newItem->fromJson(val[utility::conversions::to_string_t("{{baseName}}")]); {{setter}}( newItem ); } - {{/isDateTime}} + {{/isByteArray}}{{/isDateTime}} {{/isString}} } {{/required}} {{#required}} {{#isString}} {{setter}}(ModelBase::stringFromJson(val[utility::conversions::to_string_t("{{baseName}}")])); - {{/isString}} - {{^isString}} + {{/isString}}{{#isByteArray}} + {{setter}}(ModelBase::stringFromJson(val[utility::conversions::to_string_t("{{baseName}}")])); + {{/isByteArray}} + {{^isString}}{{^isByteArray}} {{#isDateTime}} {{setter}} (ModelBase::dateFromJson(val[utility::conversions::to_string_t("{{baseName}}")])); @@ -279,7 +282,7 @@ void {{classname}}::fromJson(web::json::value& val) {{setter}}( new{{name}} ); {{/vendorExtensions.x-codegen-file}} {{/isDateTime}} - {{/isString}} + {{/isByteArray}}{{/isString}} {{/required}} {{/isPrimitiveType}} {{/isMapContainer}} @@ -353,31 +356,33 @@ void {{classname}}::toMultipart(std::shared_ptr multipart, co {{^required}} if(m_{{name}}IsSet) { - {{#isString}}multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t("{{baseName}}"), m_{{name}})); - {{/isString}}{{^isString}}{{#isDateTime}}multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t("{{baseName}}"), m_{{name}})); - {{/isDateTime}}{{^isDateTime}}if (m_{{name}}.get()) + {{#isString}}multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t("{{baseName}}"), m_{{name}}));{{/isString}}{{#isByteArray}}multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t("{{baseName}}"), m_{{name}})); + {{/isByteArray}}{{^isString}}{{#isDateTime}}multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t("{{baseName}}"), m_{{name}})); + {{/isDateTime}}{{^isDateTime}}{{^isByteArray}}if (m_{{name}}.get()) { m_{{name}}->toMultipart(multipart, utility::conversions::to_string_t("{{baseName}}.")); } - {{/isDateTime}}{{/isString}} + {{/isByteArray}}{{/isDateTime}}{{/isString}} } {{/required}} {{#required}} {{#isString}} multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t("{{baseName}}"), m_{{name}})); - {{/isString}} + {{/isString}}{{#isByteArray}} + multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t("{{baseName}}"), m_{{name}})); + {{/isByteArray}} {{^isString}} {{#isDateTime}} multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t("{{baseName}}"), m_{{name}})); {{/isDateTime}} - {{^isDateTime}} + {{^isDateTime}}{{^isByteArray}} {{#vendorExtensions.x-codegen-file}} multipart->add(ModelBase::toHttpContent(namePrefix + utility::conversions::to_string_t("{{baseName}}"), m_{{name}})); {{/vendorExtensions.x-codegen-file}} {{^vendorExtensions.x-codegen-file}} m_{{name}}->toMultipart(multipart, utility::conversions::to_string_t("{{baseName}}.")); {{/vendorExtensions.x-codegen-file}} - {{/isDateTime}} + {{/isByteArray}}{{/isDateTime}} {{/isString}} {{/required}} {{/isPrimitiveType}} @@ -508,7 +513,8 @@ void {{classname}}::fromMultiPart(std::shared_ptr multipart, {{#isString}} {{setter}}(ModelBase::stringFromHttpContent(multipart->getContent(utility::conversions::to_string_t("{{baseName}}")))); {{/isString}} - {{^isString}} + {{#isByteArray}}{{setter}}(ModelBase::stringFromHttpContent(multipart->getContent(utility::conversions::to_string_t("{{baseName}}"))));{{/isByteArray}} + {{^isString}}{{^isByteArray}} {{#isDateTime}} {{setter}}(ModelBase::dateFromHttpContent(multipart->getContent(utility::conversions::to_string_t("{{baseName}}")))); {{/isDateTime}} @@ -520,14 +526,14 @@ void {{classname}}::fromMultiPart(std::shared_ptr multipart, {{setter}}( newItem ); } {{/isDateTime}} - {{/isString}} + {{/isByteArray}}{{/isString}} } {{/required}} {{#required}} {{#isString}} {{setter}}(ModelBase::stringFromHttpContent(multipart->getContent(utility::conversions::to_string_t("{{baseName}}")))); - {{/isString}} - {{^isString}} + {{/isString}}{{#isByteArray}}{{setter}}(ModelBase::stringFromHttpContent(multipart->getContent(utility::conversions::to_string_t("{{baseName}}"))));{{/isByteArray}} + {{^isString}}{{^isByteArray}} {{#isDateTime}} {{setter}}(ModelBase::dateFromHttpContent(multipart->getContent(utility::conversions::to_string_t("{{baseName}}")))); {{/isDateTime}} @@ -541,7 +547,7 @@ void {{classname}}::fromMultiPart(std::shared_ptr multipart, {{setter}}( new{{name}} ); {{/vendorExtensions.x-codegen-file}} {{/isDateTime}} - {{/isString}} + {{/isByteArray}}{{/isString}} {{/required}} {{/isPrimitiveType}} {{/isMapContainer}} diff --git a/samples/server/petstore/cpp-pistache/CMakeLists.txt b/samples/server/petstore/cpp-pistache/CMakeLists.txt index a68be02e008..1b8eaf68c57 100644 --- a/samples/server/petstore/cpp-pistache/CMakeLists.txt +++ b/samples/server/petstore/cpp-pistache/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required (VERSION 3.2) project(server) -set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -std=c++11) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pg -g3" ) link_directories(/usr/local/lib/) diff --git a/samples/server/petstore/cpp-pistache/api/PetApi.cpp b/samples/server/petstore/cpp-pistache/api/PetApi.cpp index c06c5fb1870..5aa08b532fc 100644 --- a/samples/server/petstore/cpp-pistache/api/PetApi.cpp +++ b/samples/server/petstore/cpp-pistache/api/PetApi.cpp @@ -59,11 +59,14 @@ void PetApi::setupRoutes() { void PetApi::add_pet_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) { // Getting the body param + Pet pet; try { nlohmann::json request_body = nlohmann::json::parse(request.body()); + pet.fromJson(request_body); + this->add_pet(pet, response); } catch (std::runtime_error & e) { //send a 400 error @@ -132,11 +135,14 @@ void PetApi::get_pet_by_id_handler(const Pistache::Rest::Request &request, Pista void PetApi::update_pet_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) { // Getting the body param + Pet pet; try { nlohmann::json request_body = nlohmann::json::parse(request.body()); + pet.fromJson(request_body); + this->update_pet(pet, response); } catch (std::runtime_error & e) { //send a 400 error diff --git a/samples/server/petstore/cpp-pistache/api/PetApi.h b/samples/server/petstore/cpp-pistache/api/PetApi.h index 4300dec560c..1e688417ee9 100644 --- a/samples/server/petstore/cpp-pistache/api/PetApi.h +++ b/samples/server/petstore/cpp-pistache/api/PetApi.h @@ -71,7 +71,7 @@ private: /// /// /// Pet object that needs to be added to the store - virtual void add_pet(const std::shared_ptr &pet, Pistache::Http::ResponseWriter &response) = 0; + virtual void add_pet(const Pet &pet, Pistache::Http::ResponseWriter &response) = 0; /// /// Deletes a pet @@ -117,7 +117,7 @@ private: /// /// /// Pet object that needs to be added to the store - virtual void update_pet(const std::shared_ptr &pet, Pistache::Http::ResponseWriter &response) = 0; + virtual void update_pet(const Pet &pet, Pistache::Http::ResponseWriter &response) = 0; /// /// Updates a pet in the store with form data diff --git a/samples/server/petstore/cpp-pistache/api/StoreApi.cpp b/samples/server/petstore/cpp-pistache/api/StoreApi.cpp index eea7fe58ea9..fb17690e38f 100644 --- a/samples/server/petstore/cpp-pistache/api/StoreApi.cpp +++ b/samples/server/petstore/cpp-pistache/api/StoreApi.cpp @@ -92,11 +92,14 @@ void StoreApi::get_order_by_id_handler(const Pistache::Rest::Request &request, P void StoreApi::place_order_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) { // Getting the body param + Order order; try { nlohmann::json request_body = nlohmann::json::parse(request.body()); + order.fromJson(request_body); + this->place_order(order, response); } catch (std::runtime_error & e) { //send a 400 error diff --git a/samples/server/petstore/cpp-pistache/api/StoreApi.h b/samples/server/petstore/cpp-pistache/api/StoreApi.h index 7068fcde620..e4491a771b4 100644 --- a/samples/server/petstore/cpp-pistache/api/StoreApi.h +++ b/samples/server/petstore/cpp-pistache/api/StoreApi.h @@ -93,7 +93,7 @@ private: /// /// /// order placed for purchasing the pet - virtual void place_order(const std::shared_ptr &order, Pistache::Http::ResponseWriter &response) = 0; + virtual void place_order(const Order &order, Pistache::Http::ResponseWriter &response) = 0; }; diff --git a/samples/server/petstore/cpp-pistache/api/UserApi.cpp b/samples/server/petstore/cpp-pistache/api/UserApi.cpp index eade7bdf8b7..45720407e08 100644 --- a/samples/server/petstore/cpp-pistache/api/UserApi.cpp +++ b/samples/server/petstore/cpp-pistache/api/UserApi.cpp @@ -59,11 +59,14 @@ void UserApi::setupRoutes() { void UserApi::create_user_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) { // Getting the body param + User user; try { nlohmann::json request_body = nlohmann::json::parse(request.body()); + user.fromJson(request_body); + this->create_user(user, response); } catch (std::runtime_error & e) { //send a 400 error @@ -75,11 +78,11 @@ void UserApi::create_user_handler(const Pistache::Rest::Request &request, Pistac void UserApi::create_users_with_array_input_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) { // Getting the body param - std::vector user; + std::vector user; try { nlohmann::json request_body = nlohmann::json::parse(request.body()); - user.fromJson(request_body); + user = ModelArrayHelper::fromJson(request_body); this->create_users_with_array_input(user, response); } catch (std::runtime_error & e) { //send a 400 error @@ -91,11 +94,11 @@ void UserApi::create_users_with_array_input_handler(const Pistache::Rest::Reques void UserApi::create_users_with_list_input_handler(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) { // Getting the body param - std::vector user; + std::vector user; try { nlohmann::json request_body = nlohmann::json::parse(request.body()); - user.fromJson(request_body); + user = ModelArrayHelper::fromJson(request_body); this->create_users_with_list_input(user, response); } catch (std::runtime_error & e) { //send a 400 error @@ -161,11 +164,14 @@ void UserApi::update_user_handler(const Pistache::Rest::Request &request, Pistac auto username = request.param(":username").as(); // Getting the body param + User user; try { nlohmann::json request_body = nlohmann::json::parse(request.body()); + user.fromJson(request_body); + this->update_user(username, user, response); } catch (std::runtime_error & e) { //send a 400 error diff --git a/samples/server/petstore/cpp-pistache/api/UserApi.h b/samples/server/petstore/cpp-pistache/api/UserApi.h index 08739d309ba..5cb7fb0a35a 100644 --- a/samples/server/petstore/cpp-pistache/api/UserApi.h +++ b/samples/server/petstore/cpp-pistache/api/UserApi.h @@ -71,7 +71,7 @@ private: /// This can only be done by the logged in user. /// /// Created user object - virtual void create_user(const std::shared_ptr &user, Pistache::Http::ResponseWriter &response) = 0; + virtual void create_user(const User &user, Pistache::Http::ResponseWriter &response) = 0; /// /// Creates list of users with given input array @@ -135,7 +135,7 @@ private: /// /// name that need to be deleted /// Updated user object - virtual void update_user(const std::string &username, const std::shared_ptr &user, Pistache::Http::ResponseWriter &response) = 0; + virtual void update_user(const std::string &username, const User &user, Pistache::Http::ResponseWriter &response) = 0; }; diff --git a/samples/server/petstore/cpp-pistache/impl/PetApiImpl.cpp b/samples/server/petstore/cpp-pistache/impl/PetApiImpl.cpp index e987ecf2371..a180ed772c5 100644 --- a/samples/server/petstore/cpp-pistache/impl/PetApiImpl.cpp +++ b/samples/server/petstore/cpp-pistache/impl/PetApiImpl.cpp @@ -23,7 +23,7 @@ PetApiImpl::PetApiImpl(Pistache::Address addr) : PetApi(addr) { } -void PetApiImpl::add_pet(const std::shared_ptr &pet, Pistache::Http::ResponseWriter &response) { +void PetApiImpl::add_pet(const Pet &pet, Pistache::Http::ResponseWriter &response) { response.send(Pistache::Http::Code::Ok, "Do some magic\n"); } void PetApiImpl::delete_pet(const int64_t &petId, const Pistache::Optional &apiKey, Pistache::Http::ResponseWriter &response) { @@ -38,7 +38,7 @@ void PetApiImpl::find_pets_by_tags(const Pistache::Optional &tags, void PetApiImpl::get_pet_by_id(const int64_t &petId, Pistache::Http::ResponseWriter &response) { response.send(Pistache::Http::Code::Ok, "Do some magic\n"); } -void PetApiImpl::update_pet(const std::shared_ptr &pet, Pistache::Http::ResponseWriter &response) { +void PetApiImpl::update_pet(const Pet &pet, Pistache::Http::ResponseWriter &response) { response.send(Pistache::Http::Code::Ok, "Do some magic\n"); } void PetApiImpl::update_pet_with_form(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter &response){ diff --git a/samples/server/petstore/cpp-pistache/impl/PetApiImpl.h b/samples/server/petstore/cpp-pistache/impl/PetApiImpl.h index b83c14efb27..d903d0b6132 100644 --- a/samples/server/petstore/cpp-pistache/impl/PetApiImpl.h +++ b/samples/server/petstore/cpp-pistache/impl/PetApiImpl.h @@ -45,12 +45,12 @@ public: PetApiImpl(Pistache::Address addr); ~PetApiImpl() { }; - void add_pet(const std::shared_ptr &pet, Pistache::Http::ResponseWriter &response); + void add_pet(const Pet &pet, Pistache::Http::ResponseWriter &response); void delete_pet(const int64_t &petId, const Pistache::Optional &apiKey, Pistache::Http::ResponseWriter &response); void find_pets_by_status(const Pistache::Optional &status, Pistache::Http::ResponseWriter &response); void find_pets_by_tags(const Pistache::Optional &tags, Pistache::Http::ResponseWriter &response); void get_pet_by_id(const int64_t &petId, Pistache::Http::ResponseWriter &response); - void update_pet(const std::shared_ptr &pet, Pistache::Http::ResponseWriter &response); + void update_pet(const Pet &pet, Pistache::Http::ResponseWriter &response); void update_pet_with_form(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter &response); void upload_file(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter &response); diff --git a/samples/server/petstore/cpp-pistache/impl/StoreApiImpl.cpp b/samples/server/petstore/cpp-pistache/impl/StoreApiImpl.cpp index 8b2742f7495..ffe74b62f2e 100644 --- a/samples/server/petstore/cpp-pistache/impl/StoreApiImpl.cpp +++ b/samples/server/petstore/cpp-pistache/impl/StoreApiImpl.cpp @@ -32,7 +32,7 @@ void StoreApiImpl::get_inventory(Pistache::Http::ResponseWriter &response) { void StoreApiImpl::get_order_by_id(const int64_t &orderId, Pistache::Http::ResponseWriter &response) { response.send(Pistache::Http::Code::Ok, "Do some magic\n"); } -void StoreApiImpl::place_order(const std::shared_ptr &order, Pistache::Http::ResponseWriter &response) { +void StoreApiImpl::place_order(const Order &order, Pistache::Http::ResponseWriter &response) { response.send(Pistache::Http::Code::Ok, "Do some magic\n"); } diff --git a/samples/server/petstore/cpp-pistache/impl/StoreApiImpl.h b/samples/server/petstore/cpp-pistache/impl/StoreApiImpl.h index 97574ec3ea0..8c18fff0027 100644 --- a/samples/server/petstore/cpp-pistache/impl/StoreApiImpl.h +++ b/samples/server/petstore/cpp-pistache/impl/StoreApiImpl.h @@ -48,7 +48,7 @@ public: void delete_order(const std::string &orderId, Pistache::Http::ResponseWriter &response); void get_inventory(Pistache::Http::ResponseWriter &response); void get_order_by_id(const int64_t &orderId, Pistache::Http::ResponseWriter &response); - void place_order(const std::shared_ptr &order, Pistache::Http::ResponseWriter &response); + void place_order(const Order &order, Pistache::Http::ResponseWriter &response); }; diff --git a/samples/server/petstore/cpp-pistache/impl/UserApiImpl.cpp b/samples/server/petstore/cpp-pistache/impl/UserApiImpl.cpp index 6d5ce9c5aaf..4dc0d57e407 100644 --- a/samples/server/petstore/cpp-pistache/impl/UserApiImpl.cpp +++ b/samples/server/petstore/cpp-pistache/impl/UserApiImpl.cpp @@ -23,7 +23,7 @@ UserApiImpl::UserApiImpl(Pistache::Address addr) : UserApi(addr) { } -void UserApiImpl::create_user(const std::shared_ptr &user, Pistache::Http::ResponseWriter &response) { +void UserApiImpl::create_user(const User &user, Pistache::Http::ResponseWriter &response) { response.send(Pistache::Http::Code::Ok, "Do some magic\n"); } void UserApiImpl::create_users_with_array_input(const std::vector &user, Pistache::Http::ResponseWriter &response) { @@ -44,7 +44,7 @@ void UserApiImpl::login_user(const Pistache::Optional &username, co void UserApiImpl::logout_user(Pistache::Http::ResponseWriter &response) { response.send(Pistache::Http::Code::Ok, "Do some magic\n"); } -void UserApiImpl::update_user(const std::string &username, const std::shared_ptr &user, Pistache::Http::ResponseWriter &response) { +void UserApiImpl::update_user(const std::string &username, const User &user, Pistache::Http::ResponseWriter &response) { response.send(Pistache::Http::Code::Ok, "Do some magic\n"); } diff --git a/samples/server/petstore/cpp-pistache/impl/UserApiImpl.h b/samples/server/petstore/cpp-pistache/impl/UserApiImpl.h index e719edba141..8da0e1277af 100644 --- a/samples/server/petstore/cpp-pistache/impl/UserApiImpl.h +++ b/samples/server/petstore/cpp-pistache/impl/UserApiImpl.h @@ -45,14 +45,14 @@ public: UserApiImpl(Pistache::Address addr); ~UserApiImpl() { }; - void create_user(const std::shared_ptr &user, Pistache::Http::ResponseWriter &response); + void create_user(const User &user, Pistache::Http::ResponseWriter &response); void create_users_with_array_input(const std::vector &user, Pistache::Http::ResponseWriter &response); void create_users_with_list_input(const std::vector &user, Pistache::Http::ResponseWriter &response); void delete_user(const std::string &username, Pistache::Http::ResponseWriter &response); void get_user_by_name(const std::string &username, Pistache::Http::ResponseWriter &response); void login_user(const Pistache::Optional &username, const Pistache::Optional &password, Pistache::Http::ResponseWriter &response); void logout_user(Pistache::Http::ResponseWriter &response); - void update_user(const std::string &username, const std::shared_ptr &user, Pistache::Http::ResponseWriter &response); + void update_user(const std::string &username, const User &user, Pistache::Http::ResponseWriter &response); }; diff --git a/samples/server/petstore/cpp-pistache/model/ApiResponse.cpp b/samples/server/petstore/cpp-pistache/model/ApiResponse.cpp index bb07343a1b4..b565e4b2675 100644 --- a/samples/server/petstore/cpp-pistache/model/ApiResponse.cpp +++ b/samples/server/petstore/cpp-pistache/model/ApiResponse.cpp @@ -68,12 +68,10 @@ void ApiResponse::fromJson(nlohmann::json& val) if(val.find("type") != val.end()) { setType(val.at("type")); - } if(val.find("message") != val.end()) { setMessage(val.at("message")); - } } diff --git a/samples/server/petstore/cpp-pistache/model/Category.cpp b/samples/server/petstore/cpp-pistache/model/Category.cpp index a1d24fdab57..a5a67cba1b8 100644 --- a/samples/server/petstore/cpp-pistache/model/Category.cpp +++ b/samples/server/petstore/cpp-pistache/model/Category.cpp @@ -62,7 +62,6 @@ void Category::fromJson(nlohmann::json& val) if(val.find("name") != val.end()) { setName(val.at("name")); - } } diff --git a/samples/server/petstore/cpp-pistache/model/ModelBase.cpp b/samples/server/petstore/cpp-pistache/model/ModelBase.cpp index d8c2437c6ff..19910b9d601 100644 --- a/samples/server/petstore/cpp-pistache/model/ModelBase.cpp +++ b/samples/server/petstore/cpp-pistache/model/ModelBase.cpp @@ -55,7 +55,7 @@ bool ModelBase::toJson( bool const value ) return value; } -nlohmann::json ModelBase::toJson(ModelBase content ) +nlohmann::json ModelBase::toJson(ModelBase const& content ) { return content.toJson(); } diff --git a/samples/server/petstore/cpp-pistache/model/ModelBase.h b/samples/server/petstore/cpp-pistache/model/ModelBase.h index 6b5589472f0..98afcd48d78 100644 --- a/samples/server/petstore/cpp-pistache/model/ModelBase.h +++ b/samples/server/petstore/cpp-pistache/model/ModelBase.h @@ -22,6 +22,8 @@ #include "json.hpp" #include #include +#include +#include namespace org { namespace openapitools { @@ -45,8 +47,103 @@ public: static int64_t toJson( int64_t const value ); static double toJson( double const value ); static bool toJson( bool const value ); - static nlohmann::json toJson(ModelBase const& content ); + static nlohmann::json toJson(ModelBase const& content ); +}; +class ModelArrayHelper { +public: + template + static std::vector fromJson(nlohmann::json& json) { + T *ptrTest; + std::vector val; + if (dynamic_cast(ptrTest) != nullptr) { + if (!json.empty()) { + for (auto &item : json.items()) { + T entry; + entry.fromJson(item.value()); + val.push_back(entry); + } + } + } + return val; + } + template + static nlohmann::json toJson(std::vector val) { + nlohmann::json json; + for(auto item : val){ + json.push_back(item.toJson()); + } + return json; + } +}; + +class ArrayHelper { +public: + template + static std::vector fromJson(nlohmann::json& json) { + std::vector val; + nlohmann::from_json(json, val); + return val; + } + template + static nlohmann::json toJson(std::vector val) { + nlohmann::json json; + nlohmann::to_json(json, val); + return json; + } +}; + +class ModelMapHelper { +public: + template + static std::map & fromJson(nlohmann::json& json) { + T *ptrTest; + std::map val; + if (dynamic_cast(ptrTest) != nullptr) { + if (!json.empty()) { + for (auto &item : json.items()) { + T entry; + entry.fromJson(item.value()); + val.insert(val.end(), + std::pair(item.key(), entry)); + } + } + } + return val; + } + template + static nlohmann::json toJson(std::map val) { + nlohmann::json json; + for (auto const& item : val) { + json[item.first] = item.second.toJson(); + } + return json; + } +}; + +class MapHelper { +public: + template + static std::map & fromJson(nlohmann::json& json) { + std::map val; + if (!json.empty()) { + for (auto &item : json.items()) { + T entry = item.value(); + val.insert(val.end(), + std::pair(item.key(), entry)); + } + } + return val; + } + template + static nlohmann::json toJson(std::map val) { + nlohmann::json json; + for (auto const& item : val) { + nlohmann::json jitem = item.second; + json[item.first] = jitem; + } + return json; + } }; } diff --git a/samples/server/petstore/cpp-pistache/model/Order.cpp b/samples/server/petstore/cpp-pistache/model/Order.cpp index fb3fde19d3a..223fa7cfe99 100644 --- a/samples/server/petstore/cpp-pistache/model/Order.cpp +++ b/samples/server/petstore/cpp-pistache/model/Order.cpp @@ -99,7 +99,6 @@ void Order::fromJson(nlohmann::json& val) if(val.find("status") != val.end()) { setStatus(val.at("status")); - } if(val.find("complete") != val.end()) { diff --git a/samples/server/petstore/cpp-pistache/model/Pet.cpp b/samples/server/petstore/cpp-pistache/model/Pet.cpp index 2c200a8db2c..ec3738e3510 100644 --- a/samples/server/petstore/cpp-pistache/model/Pet.cpp +++ b/samples/server/petstore/cpp-pistache/model/Pet.cpp @@ -91,7 +91,7 @@ void Pet::fromJson(nlohmann::json& val) { if(!val["category"].is_null()) { - Category newItem(Category()); + Category newItem; newItem.fromJson(val["category"]); setCategory( newItem ); } @@ -117,11 +117,11 @@ void Pet::fromJson(nlohmann::json& val) if(item.is_null()) { - m_Tags.push_back( Tag(nullptr) ); + m_Tags.push_back( Tag() ); } else { - Tag newItem(Tag()); + Tag newItem; newItem.fromJson(item); m_Tags.push_back( newItem ); } @@ -132,7 +132,6 @@ void Pet::fromJson(nlohmann::json& val) if(val.find("status") != val.end()) { setStatus(val.at("status")); - } } diff --git a/samples/server/petstore/cpp-pistache/model/Tag.cpp b/samples/server/petstore/cpp-pistache/model/Tag.cpp index 1cbc344ba52..6fdab108957 100644 --- a/samples/server/petstore/cpp-pistache/model/Tag.cpp +++ b/samples/server/petstore/cpp-pistache/model/Tag.cpp @@ -62,7 +62,6 @@ void Tag::fromJson(nlohmann::json& val) if(val.find("name") != val.end()) { setName(val.at("name")); - } } diff --git a/samples/server/petstore/cpp-pistache/model/User.cpp b/samples/server/petstore/cpp-pistache/model/User.cpp index e0f4defae3e..cd93eadd64e 100644 --- a/samples/server/petstore/cpp-pistache/model/User.cpp +++ b/samples/server/petstore/cpp-pistache/model/User.cpp @@ -98,32 +98,26 @@ void User::fromJson(nlohmann::json& val) if(val.find("username") != val.end()) { setUsername(val.at("username")); - } if(val.find("firstName") != val.end()) { setFirstName(val.at("firstName")); - } if(val.find("lastName") != val.end()) { setLastName(val.at("lastName")); - } if(val.find("email") != val.end()) { setEmail(val.at("email")); - } if(val.find("password") != val.end()) { setPassword(val.at("password")); - } if(val.find("phone") != val.end()) { setPhone(val.at("phone")); - } if(val.find("userStatus") != val.end()) { From eeda132e73779b7fd76bd40d5dc7831d11412783 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 20 Jul 2018 22:12:48 +0800 Subject: [PATCH 05/13] add badge to maven store and twitter (#607) --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 000066043b1..68f27ce5e14 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,8 @@
[![Join the chat at https://gitter.im/OpenAPITools/openapi-generator](https://badges.gitter.im/OpenAPITools/openapi-generator.svg)](https://gitter.im/OpenAPITools/openapi-generator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Stable releaases in the Maven store](https://img.shields.io/maven-metadata/v/http/central.maven.org/maven2/org/openapitools/openapi-generator/maven-metadata.xml.svg)](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.openapitools%22%20AND%20a%3A%22openapi-generator%22) +[![Follow OpenAPI Generator Twitter account to get the latest update](https://img.shields.io/twitter/follow/oas_generator.svg?style=social&label=Follow)](https://twitter.com/oas_generator)
From af9d57e4b9091d5981edef3f0d9435efeb5e7627 Mon Sep 17 00:00:00 2001 From: Akihito Nakano Date: Sat, 21 Jul 2018 00:45:24 +0900 Subject: [PATCH 06/13] [PHP] Remove platform dependency from file path (#610) --- .../codegen/languages/AbstractPhpCodegen.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPhpCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPhpCodegen.java index a782f23f42d..83afd83730c 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPhpCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPhpCodegen.java @@ -228,10 +228,10 @@ public abstract class AbstractPhpCodegen extends DefaultCodegen implements Codeg additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\")); // make api and model src path available in mustache template - additionalProperties.put("apiSrcPath", "." + File.separator + toSrcPath(apiPackage, srcBasePath)); - additionalProperties.put("modelSrcPath", "." + File.separator + toSrcPath(modelPackage, srcBasePath)); - additionalProperties.put("apiTestPath", "." + File.separator + testBasePath + File.separator + apiDirName); - additionalProperties.put("modelTestPath", "." + File.separator + testBasePath + File.separator + modelDirName); + additionalProperties.put("apiSrcPath", "./" + toSrcPath(apiPackage, srcBasePath)); + additionalProperties.put("modelSrcPath", "./" + toSrcPath(modelPackage, srcBasePath)); + additionalProperties.put("apiTestPath", "./" + testBasePath + "/" + apiDirName); + additionalProperties.put("modelTestPath", "./" + testBasePath + "/" + modelDirName); // make api and model doc path available in mustache template additionalProperties.put("apiDocPath", apiDocPath); @@ -255,7 +255,7 @@ public abstract class AbstractPhpCodegen extends DefaultCodegen implements Codeg public String toSrcPath(String packageName, String basePath) { packageName = packageName.replace(invokerPackage, ""); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. if (basePath != null && basePath.length() > 0) { - basePath = basePath.replaceAll("[\\\\/]?$", "") + File.separatorChar; // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. + basePath = basePath.replaceAll("[\\\\/]?$", "") + '/'; // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. } String regFirstPathSeparator; @@ -274,7 +274,7 @@ public abstract class AbstractPhpCodegen extends DefaultCodegen implements Codeg return (basePath // Replace period, backslash, forward slash with file separator in package name - + packageName.replaceAll("[\\.\\\\/]", Matcher.quoteReplacement(File.separator)) + + packageName.replaceAll("[\\.\\\\/]", Matcher.quoteReplacement("/")) // Trim prefix file separators from package path .replaceAll(regFirstPathSeparator, "")) // Trim trailing file separators from the overall path From 0da55081c934704f24c702659e93e640fadf006c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Mart=C3=ADnez?= Date: Fri, 20 Jul 2018 17:49:12 +0200 Subject: [PATCH 07/13] [Java][Client][RestTemplate] Do not create new Object for empty body (#605) #513 Fixed error that causes exception when trying to perform HTTP requests without a body and an empty Object is used as body instead. In these cases an exception is thrown indicating that it is not possible to find a message converter for java.lang.Object and application/json. --- .../Java/libraries/resttemplate/api.mustache | 2 +- .../java/org/openapitools/client/api/FakeApi.java | 6 +++--- .../java/org/openapitools/client/api/PetApi.java | 14 +++++++------- .../java/org/openapitools/client/api/StoreApi.java | 6 +++--- .../java/org/openapitools/client/api/UserApi.java | 8 ++++---- .../java/org/openapitools/client/api/FakeApi.java | 6 +++--- .../java/org/openapitools/client/api/PetApi.java | 14 +++++++------- .../java/org/openapitools/client/api/StoreApi.java | 6 +++--- .../java/org/openapitools/client/api/UserApi.java | 8 ++++---- 9 files changed, 35 insertions(+), 35 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/api.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/api.mustache index a906a80e7a8..f48180f4381 100644 --- a/modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/api.mustache +++ b/modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/api.mustache @@ -61,7 +61,7 @@ public class {{classname}} { {{/externalDocs}} */ public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws RestClientException { - Object {{localVariablePrefix}}postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}new Object(){{/bodyParam}}; + Object {{localVariablePrefix}}postBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}; {{#allParams}}{{#required}} // verify the required parameter '{{paramName}}' is set if ({{paramName}} == null) { diff --git a/samples/client/petstore/java/resttemplate-withXml/src/main/java/org/openapitools/client/api/FakeApi.java b/samples/client/petstore/java/resttemplate-withXml/src/main/java/org/openapitools/client/api/FakeApi.java index c7adab4c3af..1a765af7da7 100644 --- a/samples/client/petstore/java/resttemplate-withXml/src/main/java/org/openapitools/client/api/FakeApi.java +++ b/samples/client/petstore/java/resttemplate-withXml/src/main/java/org/openapitools/client/api/FakeApi.java @@ -300,7 +300,7 @@ public class FakeApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public void testEndpointParameters(BigDecimal number, Double _double, String patternWithoutDelimiter, byte[] _byte, Integer integer, Integer int32, Long int64, Float _float, String string, File binary, LocalDate date, OffsetDateTime dateTime, String password, String paramCallback) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'number' is set if (number == null) { @@ -385,7 +385,7 @@ public class FakeApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public void testEnumParameters(List enumHeaderStringArray, String enumHeaderString, List enumQueryStringArray, String enumQueryString, Integer enumQueryInteger, Double enumQueryDouble, List enumFormStringArray, String enumFormString) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; String path = UriComponentsBuilder.fromPath("/fake").build().toUriString(); @@ -462,7 +462,7 @@ public class FakeApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public void testJsonFormData(String param, String param2) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'param' is set if (param == null) { diff --git a/samples/client/petstore/java/resttemplate-withXml/src/main/java/org/openapitools/client/api/PetApi.java b/samples/client/petstore/java/resttemplate-withXml/src/main/java/org/openapitools/client/api/PetApi.java index 8a9eeaa82c2..7a3897f689c 100644 --- a/samples/client/petstore/java/resttemplate-withXml/src/main/java/org/openapitools/client/api/PetApi.java +++ b/samples/client/petstore/java/resttemplate-withXml/src/main/java/org/openapitools/client/api/PetApi.java @@ -89,7 +89,7 @@ public class PetApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public void deletePet(Long petId, String apiKey) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'petId' is set if (petId == null) { @@ -128,7 +128,7 @@ public class PetApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public List findPetsByStatus(List status) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'status' is set if (status == null) { @@ -165,7 +165,7 @@ public class PetApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public List findPetsByTags(List tags) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'tags' is set if (tags == null) { @@ -203,7 +203,7 @@ public class PetApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public Pet getPetById(Long petId) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'petId' is set if (petId == null) { @@ -276,7 +276,7 @@ public class PetApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public void updatePetWithForm(Long petId, String name, String status) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'petId' is set if (petId == null) { @@ -320,7 +320,7 @@ public class PetApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public ModelApiResponse uploadFile(Long petId, String additionalMetadata, File file) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'petId' is set if (petId == null) { @@ -366,7 +366,7 @@ public class PetApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public ModelApiResponse uploadFileWithRequiredFile(Long petId, File requiredFile, String additionalMetadata) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'petId' is set if (petId == null) { diff --git a/samples/client/petstore/java/resttemplate-withXml/src/main/java/org/openapitools/client/api/StoreApi.java b/samples/client/petstore/java/resttemplate-withXml/src/main/java/org/openapitools/client/api/StoreApi.java index 2a5743dc74a..e417838bba4 100644 --- a/samples/client/petstore/java/resttemplate-withXml/src/main/java/org/openapitools/client/api/StoreApi.java +++ b/samples/client/petstore/java/resttemplate-withXml/src/main/java/org/openapitools/client/api/StoreApi.java @@ -54,7 +54,7 @@ public class StoreApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public void deleteOrder(String orderId) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'orderId' is set if (orderId == null) { @@ -88,7 +88,7 @@ public class StoreApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public Map getInventory() throws RestClientException { - Object postBody = new Object(); + Object postBody = null; String path = UriComponentsBuilder.fromPath("/store/inventory").build().toUriString(); @@ -119,7 +119,7 @@ public class StoreApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public Order getOrderById(Long orderId) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'orderId' is set if (orderId == null) { diff --git a/samples/client/petstore/java/resttemplate-withXml/src/main/java/org/openapitools/client/api/UserApi.java b/samples/client/petstore/java/resttemplate-withXml/src/main/java/org/openapitools/client/api/UserApi.java index bd89c01b8aa..2949e2f57a0 100644 --- a/samples/client/petstore/java/resttemplate-withXml/src/main/java/org/openapitools/client/api/UserApi.java +++ b/samples/client/petstore/java/resttemplate-withXml/src/main/java/org/openapitools/client/api/UserApi.java @@ -147,7 +147,7 @@ public class UserApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public void deleteUser(String username) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'username' is set if (username == null) { @@ -184,7 +184,7 @@ public class UserApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public User getUserByName(String username) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'username' is set if (username == null) { @@ -223,7 +223,7 @@ public class UserApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public String loginUser(String username, String password) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'username' is set if (username == null) { @@ -263,7 +263,7 @@ public class UserApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public void logoutUser() throws RestClientException { - Object postBody = new Object(); + Object postBody = null; String path = UriComponentsBuilder.fromPath("/user/logout").build().toUriString(); diff --git a/samples/client/petstore/java/resttemplate/src/main/java/org/openapitools/client/api/FakeApi.java b/samples/client/petstore/java/resttemplate/src/main/java/org/openapitools/client/api/FakeApi.java index c7adab4c3af..1a765af7da7 100644 --- a/samples/client/petstore/java/resttemplate/src/main/java/org/openapitools/client/api/FakeApi.java +++ b/samples/client/petstore/java/resttemplate/src/main/java/org/openapitools/client/api/FakeApi.java @@ -300,7 +300,7 @@ public class FakeApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public void testEndpointParameters(BigDecimal number, Double _double, String patternWithoutDelimiter, byte[] _byte, Integer integer, Integer int32, Long int64, Float _float, String string, File binary, LocalDate date, OffsetDateTime dateTime, String password, String paramCallback) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'number' is set if (number == null) { @@ -385,7 +385,7 @@ public class FakeApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public void testEnumParameters(List enumHeaderStringArray, String enumHeaderString, List enumQueryStringArray, String enumQueryString, Integer enumQueryInteger, Double enumQueryDouble, List enumFormStringArray, String enumFormString) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; String path = UriComponentsBuilder.fromPath("/fake").build().toUriString(); @@ -462,7 +462,7 @@ public class FakeApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public void testJsonFormData(String param, String param2) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'param' is set if (param == null) { diff --git a/samples/client/petstore/java/resttemplate/src/main/java/org/openapitools/client/api/PetApi.java b/samples/client/petstore/java/resttemplate/src/main/java/org/openapitools/client/api/PetApi.java index 8a9eeaa82c2..7a3897f689c 100644 --- a/samples/client/petstore/java/resttemplate/src/main/java/org/openapitools/client/api/PetApi.java +++ b/samples/client/petstore/java/resttemplate/src/main/java/org/openapitools/client/api/PetApi.java @@ -89,7 +89,7 @@ public class PetApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public void deletePet(Long petId, String apiKey) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'petId' is set if (petId == null) { @@ -128,7 +128,7 @@ public class PetApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public List findPetsByStatus(List status) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'status' is set if (status == null) { @@ -165,7 +165,7 @@ public class PetApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public List findPetsByTags(List tags) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'tags' is set if (tags == null) { @@ -203,7 +203,7 @@ public class PetApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public Pet getPetById(Long petId) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'petId' is set if (petId == null) { @@ -276,7 +276,7 @@ public class PetApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public void updatePetWithForm(Long petId, String name, String status) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'petId' is set if (petId == null) { @@ -320,7 +320,7 @@ public class PetApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public ModelApiResponse uploadFile(Long petId, String additionalMetadata, File file) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'petId' is set if (petId == null) { @@ -366,7 +366,7 @@ public class PetApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public ModelApiResponse uploadFileWithRequiredFile(Long petId, File requiredFile, String additionalMetadata) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'petId' is set if (petId == null) { diff --git a/samples/client/petstore/java/resttemplate/src/main/java/org/openapitools/client/api/StoreApi.java b/samples/client/petstore/java/resttemplate/src/main/java/org/openapitools/client/api/StoreApi.java index 2a5743dc74a..e417838bba4 100644 --- a/samples/client/petstore/java/resttemplate/src/main/java/org/openapitools/client/api/StoreApi.java +++ b/samples/client/petstore/java/resttemplate/src/main/java/org/openapitools/client/api/StoreApi.java @@ -54,7 +54,7 @@ public class StoreApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public void deleteOrder(String orderId) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'orderId' is set if (orderId == null) { @@ -88,7 +88,7 @@ public class StoreApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public Map getInventory() throws RestClientException { - Object postBody = new Object(); + Object postBody = null; String path = UriComponentsBuilder.fromPath("/store/inventory").build().toUriString(); @@ -119,7 +119,7 @@ public class StoreApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public Order getOrderById(Long orderId) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'orderId' is set if (orderId == null) { diff --git a/samples/client/petstore/java/resttemplate/src/main/java/org/openapitools/client/api/UserApi.java b/samples/client/petstore/java/resttemplate/src/main/java/org/openapitools/client/api/UserApi.java index bd89c01b8aa..2949e2f57a0 100644 --- a/samples/client/petstore/java/resttemplate/src/main/java/org/openapitools/client/api/UserApi.java +++ b/samples/client/petstore/java/resttemplate/src/main/java/org/openapitools/client/api/UserApi.java @@ -147,7 +147,7 @@ public class UserApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public void deleteUser(String username) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'username' is set if (username == null) { @@ -184,7 +184,7 @@ public class UserApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public User getUserByName(String username) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'username' is set if (username == null) { @@ -223,7 +223,7 @@ public class UserApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public String loginUser(String username, String password) throws RestClientException { - Object postBody = new Object(); + Object postBody = null; // verify the required parameter 'username' is set if (username == null) { @@ -263,7 +263,7 @@ public class UserApi { * @throws RestClientException if an error occurs while attempting to invoke the API */ public void logoutUser() throws RestClientException { - Object postBody = new Object(); + Object postBody = null; String path = UriComponentsBuilder.fromPath("/user/logout").build().toUriString(); From 1dee3e227c8e2f52db427eb1051b9346313c3f63 Mon Sep 17 00:00:00 2001 From: sunn <33183834+etherealjoy@users.noreply.github.com> Date: Sun, 22 Jul 2018 04:46:38 +0200 Subject: [PATCH 08/13] [cpp-pistache] add the option to fetch dependencies (#495) * Add the Possibility to fetch dependencies needed by the generated code * Fix typo * Make External Libraries default to false * Add parameter string to the javadoc comment --- bin/cpp-pistache-server-petstore.sh | 2 +- bin/openapi3/cpp-pistache-server-petstore.sh | 2 +- .../languages/CppPistacheServerCodegen.java | 22 ++++++++++++++++--- .../cpp-pistache-server/cmake.mustache | 20 +++++++++++++++++ .../petstore/cpp-pistache/CMakeLists.txt | 1 + 5 files changed, 42 insertions(+), 5 deletions(-) diff --git a/bin/cpp-pistache-server-petstore.sh b/bin/cpp-pistache-server-petstore.sh index c205a732358..bf8d4151570 100755 --- a/bin/cpp-pistache-server-petstore.sh +++ b/bin/cpp-pistache-server-petstore.sh @@ -27,6 +27,6 @@ fi # if you've executed sbt assembly previously it will use that instead. export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" -ags="generate -g cpp-pistache-server -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -o samples/server/petstore/cpp-pistache $@" +ags="generate -g cpp-pistache-server -t modules/openapi-generator/src/main/resources/cpp-pistache-server -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -o samples/server/petstore/cpp-pistache $@" java $JAVA_OPTS -jar $executable $ags diff --git a/bin/openapi3/cpp-pistache-server-petstore.sh b/bin/openapi3/cpp-pistache-server-petstore.sh index 5f7dd337691..e2240ea2047 100755 --- a/bin/openapi3/cpp-pistache-server-petstore.sh +++ b/bin/openapi3/cpp-pistache-server-petstore.sh @@ -27,6 +27,6 @@ fi # if you've executed sbt assembly previously it will use that instead. export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" -ags="generate -g cpp-pistache-server -i modules/openapi-generator/src/test/resources/3_0/petstore.yaml -o samples/server/petstore/cpp-pistache $@" +ags="generate -g cpp-pistache-server -t modules/openapi-generator/src/main/resources/cpp-pistache-server -i modules/openapi-generator/src/test/resources/3_0/petstore.yaml -o samples/server/petstore/cpp-pistache $@" java $JAVA_OPTS -jar $executable $ags diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppPistacheServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppPistacheServerCodegen.java index 0516d237def..69832171cb2 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppPistacheServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppPistacheServerCodegen.java @@ -43,7 +43,9 @@ import java.util.Set; public class CppPistacheServerCodegen extends AbstractCppCodegen { protected String implFolder = "impl"; - + protected boolean isAddExternalLibs = false; + public static final String OPTIONAL_EXTERNAL_LIB = "addExternalLibs"; + public static final String OPTIONAL_EXTERNAL_LIB_DESC = "Add the Possibility to fetch and compile external Libraries needed by this Framework."; @Override public CodegenType getTag() { return CodegenType.SERVER; @@ -77,6 +79,7 @@ public class CppPistacheServerCodegen extends AbstractCppCodegen { embeddedTemplateDir = templateDir = "cpp-pistache-server"; cliOptions.clear(); + addSwitch(OPTIONAL_EXTERNAL_LIB, OPTIONAL_EXTERNAL_LIB_DESC, this.isAddExternalLibs); reservedWords = new HashSet<>(); @@ -118,7 +121,12 @@ public class CppPistacheServerCodegen extends AbstractCppCodegen { additionalProperties.put("modelNamespaceDeclarations", modelPackage.split("\\.")); additionalProperties.put("modelNamespace", modelPackage.replaceAll("\\.", "::")); additionalProperties.put("apiNamespaceDeclarations", apiPackage.split("\\.")); - additionalProperties.put("apiNamespace", apiPackage.replaceAll("\\.", "::")); + additionalProperties.put("apiNamespace", apiPackage.replaceAll("\\.", "::")); + if (additionalProperties.containsKey(OPTIONAL_EXTERNAL_LIB)) { + setAddExternalLibs(convertPropertyToBooleanAndWriteBack(OPTIONAL_EXTERNAL_LIB)); + } else { + additionalProperties.put(OPTIONAL_EXTERNAL_LIB, isAddExternalLibs); + } } /** @@ -410,9 +418,17 @@ public class CppPistacheServerCodegen extends AbstractCppCodegen { public String escapeUnsafeCharacters(String input) { return input.replace("*/", "*_/").replace("/*", "/_*"); } - + @Override public String getTypeDeclaration(String str) { return toModelName(str); } + + /** + * Specify whether external libraries will be added during the generation + * @param value the value to be set + */ + public void setAddExternalLibs(boolean value){ + isAddExternalLibs = value; + } } diff --git a/modules/openapi-generator/src/main/resources/cpp-pistache-server/cmake.mustache b/modules/openapi-generator/src/main/resources/cpp-pistache-server/cmake.mustache index 0a6f820d30d..bec55299241 100644 --- a/modules/openapi-generator/src/main/resources/cpp-pistache-server/cmake.mustache +++ b/modules/openapi-generator/src/main/resources/cpp-pistache-server/cmake.mustache @@ -4,6 +4,26 @@ project(server) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pg -g3" ) +{{#addExternalLibs}} +include(ExternalProject) + +set(EXTERNAL_INSTALL_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/external) + +ExternalProject_Add(PISTACHE + GIT_REPOSITORY https://github.com/oktal/pistache.git + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTERNAL_INSTALL_LOCATION} +) + +ExternalProject_Add(NLOHMANN + GIT_REPOSITORY https://github.com/nlohmann/json.git + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTERNAL_INSTALL_LOCATION} + +) +include_directories(${EXTERNAL_INSTALL_LOCATION}/include) +include_directories(${EXTERNAL_INSTALL_LOCATION}/include/nlohmann) +link_directories(${EXTERNAL_INSTALL_LOCATION}/lib) +{{/addExternalLibs}} + link_directories(/usr/local/lib/) aux_source_directory(model MODEL_SOURCES) diff --git a/samples/server/petstore/cpp-pistache/CMakeLists.txt b/samples/server/petstore/cpp-pistache/CMakeLists.txt index 1b8eaf68c57..b4a53b92012 100644 --- a/samples/server/petstore/cpp-pistache/CMakeLists.txt +++ b/samples/server/petstore/cpp-pistache/CMakeLists.txt @@ -4,6 +4,7 @@ project(server) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pg -g3" ) + link_directories(/usr/local/lib/) aux_source_directory(model MODEL_SOURCES) From 5328f103da9265e3bdb96d395d924275500e2283 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Sun, 22 Jul 2018 16:41:20 +0800 Subject: [PATCH 09/13] Add C++ Pistache petstore server to Travis CI (#616) * test cpp pistache petstore in travis * make build_petstore executable * add submodule update init * use addExternalLibs option * update samples * update gcc version to 5 * fix addon, env * restore cargo path * trigger build failure, add cache * undo build failure change --- .travis.yml | 17 ++++-- bin/cpp-pistache-server-petstore.sh | 2 +- pom.xml | 1 + .../cpp-pistache/.openapi-generator/VERSION | 2 +- .../petstore/cpp-pistache/CMakeLists.txt | 17 ++++++ .../petstore/cpp-pistache/build_petstore.sh | 8 +++ .../petstore/cpp-pistache/install_pistache.sh | 13 +++++ samples/server/petstore/cpp-pistache/pom.xml | 53 +++++++++++++++++++ 8 files changed, 107 insertions(+), 6 deletions(-) create mode 100755 samples/server/petstore/cpp-pistache/build_petstore.sh create mode 100755 samples/server/petstore/cpp-pistache/install_pistache.sh create mode 100644 samples/server/petstore/cpp-pistache/pom.xml diff --git a/.travis.yml b/.travis.yml index 20819c11f25..3c6f558db80 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,12 +30,18 @@ cache: - $HOME/perl5 - $HOME/.cargo - $HOME/.stack + - $HOME/samples/server/petstore/cpp-pistache/pistache services: - docker # comment out the host table change to use the public petstore server addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-5 chrome: stable hosts: - petstore.swagger.io @@ -86,10 +92,13 @@ before_install: install: # Add Godeps dependencies to GOPATH and PATH - - eval "$(curl -sL https://raw.githubusercontent.com/travis-ci/gimme/master/gimme | GIMME_GO_VERSION=1.4 bash)" - - export GOPATH="${TRAVIS_BUILD_DIR}/Godeps/_workspace" + #- eval "$(curl -sL https://raw.githubusercontent.com/travis-ci/gimme/master/gimme | GIMME_GO_VERSION=1.4 bash)" + #- export GOPATH="${TRAVIS_BUILD_DIR}/Godeps/_workspace" - export PATH="${TRAVIS_BUILD_DIR}/Godeps/_workspace/bin:$HOME/.cargo/bin:$PATH" - - go version + #- go version + - gcc -v + - echo $CC + - echo $CXX script: # fail fast @@ -130,4 +139,4 @@ after_success: - if [ $DOCKER_HUB_USERNAME ]; then echo "$DOCKER_HUB_PASSWORD" | docker login --username=$DOCKER_HUB_USERNAME --password-stdin && docker build -t $DOCKER_CODEGEN_CLI_IMAGE_NAME ./modules/openapi-generator-cli && if [ ! -z "$TRAVIS_TAG" ]; then docker tag $DOCKER_CODEGEN_CLI_IMAGE_NAME:latest $DOCKER_CODEGEN_CLI_IMAGE_NAME:$TRAVIS_TAG; fi && if [ ! -z "$TRAVIS_TAG" ] || [ "$TRAVIS_BRANCH" = "master" ]; then docker push $DOCKER_CODEGEN_CLI_IMAGE_NAME && echo "Pushed to $DOCKER_CODEGEN_CLI_IMAGE_NAME"; fi; fi env: - - DOCKER_GENERATOR_IMAGE_NAME=openapitools/openapi-generator-online DOCKER_CODEGEN_CLI_IMAGE_NAME=openapitools/openapi-generator-cli NODE_ENV=test + - DOCKER_GENERATOR_IMAGE_NAME=openapitools/openapi-generator-online DOCKER_CODEGEN_CLI_IMAGE_NAME=openapitools/openapi-generator-cli NODE_ENV=test CC=gcc-5 CXX=g++-5 diff --git a/bin/cpp-pistache-server-petstore.sh b/bin/cpp-pistache-server-petstore.sh index bf8d4151570..0aa9488b35b 100755 --- a/bin/cpp-pistache-server-petstore.sh +++ b/bin/cpp-pistache-server-petstore.sh @@ -27,6 +27,6 @@ fi # if you've executed sbt assembly previously it will use that instead. export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" -ags="generate -g cpp-pistache-server -t modules/openapi-generator/src/main/resources/cpp-pistache-server -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -o samples/server/petstore/cpp-pistache $@" +ags="generate -g cpp-pistache-server -t modules/openapi-generator/src/main/resources/cpp-pistache-server -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml --additional-properties addExternalLibs=true -o samples/server/petstore/cpp-pistache $@" java $JAVA_OPTS -jar $executable $ags diff --git a/pom.xml b/pom.xml index e38317bbae2..a358f65748d 100644 --- a/pom.xml +++ b/pom.xml @@ -928,6 +928,7 @@ + samples/server/petstore/cpp-pistache samples/client/petstore/haskell-http-client diff --git a/samples/server/petstore/cpp-pistache/.openapi-generator/VERSION b/samples/server/petstore/cpp-pistache/.openapi-generator/VERSION index 1c00c518154..0f58aa04141 100644 --- a/samples/server/petstore/cpp-pistache/.openapi-generator/VERSION +++ b/samples/server/petstore/cpp-pistache/.openapi-generator/VERSION @@ -1 +1 @@ -3.0.2-SNAPSHOT \ No newline at end of file +3.1.2-SNAPSHOT \ No newline at end of file diff --git a/samples/server/petstore/cpp-pistache/CMakeLists.txt b/samples/server/petstore/cpp-pistache/CMakeLists.txt index b4a53b92012..0a0cf93a9f3 100644 --- a/samples/server/petstore/cpp-pistache/CMakeLists.txt +++ b/samples/server/petstore/cpp-pistache/CMakeLists.txt @@ -4,6 +4,23 @@ project(server) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pg -g3" ) +include(ExternalProject) + +set(EXTERNAL_INSTALL_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/external) + +ExternalProject_Add(PISTACHE + GIT_REPOSITORY https://github.com/oktal/pistache.git + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTERNAL_INSTALL_LOCATION} +) + +ExternalProject_Add(NLOHMANN + GIT_REPOSITORY https://github.com/nlohmann/json.git + CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTERNAL_INSTALL_LOCATION} + +) +include_directories(${EXTERNAL_INSTALL_LOCATION}/include) +include_directories(${EXTERNAL_INSTALL_LOCATION}/include/nlohmann) +link_directories(${EXTERNAL_INSTALL_LOCATION}/lib) link_directories(/usr/local/lib/) diff --git a/samples/server/petstore/cpp-pistache/build_petstore.sh b/samples/server/petstore/cpp-pistache/build_petstore.sh new file mode 100755 index 00000000000..665f09a5054 --- /dev/null +++ b/samples/server/petstore/cpp-pistache/build_petstore.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# build C++ pistache petstore +# + +mkdir build +cd build +cmake .. +make diff --git a/samples/server/petstore/cpp-pistache/install_pistache.sh b/samples/server/petstore/cpp-pistache/install_pistache.sh new file mode 100755 index 00000000000..d10e3f19b37 --- /dev/null +++ b/samples/server/petstore/cpp-pistache/install_pistache.sh @@ -0,0 +1,13 @@ +#/bin/bash +# ref: http://pistache.io/quickstart#installing-pistache +# +echo "Installing Pistache ..." + +git clone https://github.com/oktal/pistache.git || true +cd pistache +git submodule update --init +mkdir -p build +cd build +cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release .. +make +sudo make install diff --git a/samples/server/petstore/cpp-pistache/pom.xml b/samples/server/petstore/cpp-pistache/pom.xml new file mode 100644 index 00000000000..3b46ac29fc3 --- /dev/null +++ b/samples/server/petstore/cpp-pistache/pom.xml @@ -0,0 +1,53 @@ + + 4.0.0 + org.openapitools + CppPistacheServerTests + pom + 1.0-SNAPSHOT + C++ Pistache Petstore Server + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory} + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + + install-pistache + integration-test + + exec + + + ./install_pistache.sh + + + + build-pistache + integration-test + + exec + + + ./build_petstore.sh + + + + + + + From 4156bb9f01bfc1d9a9b61bcfc8fdcd9233988bb0 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Mon, 23 Jul 2018 01:01:32 +0800 Subject: [PATCH 10/13] remove cpp pistache petstore test from travis ci --- pom.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/pom.xml b/pom.xml index a358f65748d..b1de8fe151c 100644 --- a/pom.xml +++ b/pom.xml @@ -928,10 +928,8 @@ - samples/server/petstore/cpp-pistache samples/client/petstore/haskell-http-client - samples/client/petstore/elm samples/client/petstore/groovy samples/client/petstore/rust From d42ff75cebeb7d7aab80f4b48e6a77f3ac5e489a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Mon, 23 Jul 2018 06:20:41 +0200 Subject: [PATCH 11/13] Handle variables in server declaration (#614) --- .../codegen/utils/URLPathUtils.java | 43 ++++++++++++++++++- .../codegen/utils/URLPathUtilsTest.java | 39 +++++++++++++++++ 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/URLPathUtils.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/URLPathUtils.java index 4fa6ffd9c6a..91aba80d82c 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/URLPathUtils.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/URLPathUtils.java @@ -19,6 +19,8 @@ package org.openapitools.codegen.utils; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.servers.Server; +import io.swagger.v3.oas.models.servers.ServerVariable; +import io.swagger.v3.oas.models.servers.ServerVariables; import org.openapitools.codegen.CodegenConfig; import org.slf4j.Logger; @@ -26,12 +28,17 @@ import org.slf4j.LoggerFactory; import java.net.MalformedURLException; import java.net.URL; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class URLPathUtils { private static final Logger LOGGER = LoggerFactory.getLogger(URLPathUtils.class); public static final String LOCAL_HOST = "http://localhost"; + public static final Pattern VARIABLE_PATTERN = Pattern.compile("\\{([^\\}]+)\\}"); public static URL getServerURL(OpenAPI openAPI) { final List servers = openAPI.getServers(); @@ -40,8 +47,40 @@ public class URLPathUtils { return getDefaultUrl(); } // TODO need a way to obtain all server URLs - final Server server = servers.get(0); - String url = sanitizeUrl(server.getUrl()); + return getServerURL(servers.get(0)); + } + + static URL getServerURL(final Server server) { + String url = server.getUrl(); + ServerVariables variables = server.getVariables(); + if(variables == null) { + variables = new ServerVariables(); + } + Set replacedVariables = new HashSet<>(); + Matcher matcher = VARIABLE_PATTERN.matcher(url); + while(matcher.find()) { + if(!replacedVariables.contains(matcher.group())) { + ServerVariable variable = variables.get(matcher.group(1)); + String replacement; + if(variable != null) { + if(variable.getDefault() != null) { + replacement = variable.getDefault(); + } else if(variable.getEnum() != null && !variable.getEnum().isEmpty()) { + replacement = variable.getEnum().get(0); + } else { + LOGGER.warn("No value found for variable '{}' in server definition '{}', default to empty string.", matcher.group(1), server.getUrl()); + replacement = ""; + } + } else { + LOGGER.warn("No variable '{}' found in server definition '{}', default to empty string.", matcher.group(1), server.getUrl()); + replacement = ""; + } + url = url.replace(matcher.group(), replacement); + replacedVariables.add(matcher.group()); + matcher = VARIABLE_PATTERN.matcher(url); + } + } + url = sanitizeUrl(url); try { return new URL(url); diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/utils/URLPathUtilsTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/utils/URLPathUtilsTest.java index 26c42eb2e59..f6625cc427e 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/utils/URLPathUtilsTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/utils/URLPathUtilsTest.java @@ -19,11 +19,14 @@ package org.openapitools.codegen.utils; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.servers.Server; +import io.swagger.v3.oas.models.servers.ServerVariable; +import io.swagger.v3.oas.models.servers.ServerVariables; import org.testng.Assert; import org.testng.annotations.Test; import java.net.URL; +import java.util.Arrays; public class URLPathUtilsTest { @@ -75,4 +78,40 @@ public class URLPathUtilsTest { Assert.assertEquals(URLPathUtils.getServerURL(openAPI).toString(), t[1]); } } + + @Test + public void testGetServerURLWithVariables() throws Exception { + Server s1 = new Server().url("http://localhost:{port}/").variables(new ServerVariables().addServerVariable("port", new ServerVariable()._default("8080").description("the server port"))); + Assert.assertEquals(URLPathUtils.getServerURL(s1).toString(), "http://localhost:8080/"); + + Server s2 = new Server().url("http://{version}.test.me/{version}").variables(new ServerVariables().addServerVariable("version", new ServerVariable()._default("v1"))); + Assert.assertEquals(URLPathUtils.getServerURL(s2).toString(), "http://v1.test.me/v1"); + + Server s3 = new Server().url("http://localhost:{port}/{version}").variables( + new ServerVariables().addServerVariable("version", new ServerVariable()._default("v4")) + .addServerVariable("port", new ServerVariable()._default("8080")) + .addServerVariable("other", new ServerVariable()._default("something")) + ); + Assert.assertEquals(URLPathUtils.getServerURL(s3).toString(), "http://localhost:8080/v4"); + + Server s4 = new Server().url("http://91.161.147.64/{targetEnv}").variables(new ServerVariables().addServerVariable("targetEnv", new ServerVariable().description("target environment")._enum(Arrays.asList("dev", "int", "prd"))._default("prd"))); + Assert.assertEquals(URLPathUtils.getServerURL(s4).toString(), "http://91.161.147.64/prd"); + + Server s5 = new Server().url("https://api.stats.com/{country1}").variables(new ServerVariables().addServerVariable("country1", new ServerVariable()._enum(Arrays.asList("france", "germany", "italy")))); + Assert.assertEquals(URLPathUtils.getServerURL(s5).toString(), "https://api.stats.com/france"); + + Server s6 = new Server().url("https://api.example.com/{wrong}"); + Assert.assertEquals(URLPathUtils.getServerURL(s6).toString(), "https://api.example.com/"); + + Server s7 = new Server().url("https://api.example.com/{wrong}").variables(new ServerVariables()); + Assert.assertEquals(URLPathUtils.getServerURL(s7).toString(), "https://api.example.com/"); + + Server s8 = new Server().url("https://api.example.com/{wrong}").variables(new ServerVariables().addServerVariable("other", new ServerVariable()._default("something"))); + Assert.assertEquals(URLPathUtils.getServerURL(s8).toString(), "https://api.example.com/"); + + Server s9 = new Server().url("https://{user}.example.com/{version}").variables( + new ServerVariables().addServerVariable("version", new ServerVariable()._default("v1")) + .addServerVariable("user", new ServerVariable()._default("{user}"))); + Assert.assertEquals(URLPathUtils.getServerURL(s9).toString(), "https://{user}.example.com/v1"); + } } From af3ca293e4ff3defcbfd4a32b82f7d3229a29d48 Mon Sep 17 00:00:00 2001 From: John Wang Date: Mon, 23 Jul 2018 03:36:39 -0700 Subject: [PATCH 12/13] Add link to Go contribution quickstart article (#622) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 68f27ce5e14..6ad8180bc08 100644 --- a/README.md +++ b/README.md @@ -432,6 +432,7 @@ Here are some companies/projects (alphabetical order) using OpenAPI Generator in - 2018/06/08 - [Swagger Codegen is now OpenAPI Generator](https://angular.schule/blog/2018-06-swagger-codegen-is-now-openapi-generator) by [JohannesHoppe](https://github.com/JohannesHoppe) - 2018/06/21 - [Connect your JHipster apps to the world of APIs with OpenAPI and gRPC](https://fr.slideshare.net/chbornet/jhipster-conf-2018-connect-your-jhipster-apps-to-the-world-of-apis-with-openapi-and-grpc) by [Christophe Bornet](https://github.com/cbornet) at [JHipster Conf 2018](https://jhipster-conf.github.io/) - 2018/06/27 - [Lessons Learned from Leading an Open-Source Project Supporting 30+ Programming Languages](https://speakerdeck.com/wing328/lessons-learned-from-leading-an-open-source-project-supporting-30-plus-programming-languages) - [William Cheng](https://github.com/wing328) at [LinuxCon + ContainerCon + CloudOpen China 2018](https://www.lfasiallc.com/events/lc3-2018/) +- 2018/07/19 - [OpenAPI Generator Contribution Quickstart - RingCentral Go SDK](https://medium.com/ringcentral-developers/openapi-generator-for-go-contribution-quickstart-8cc72bf37b53) by [John Wang](https://github.com/grokify) ## [6 - About Us](#table-of-contents) From a9961a062a46ffc62d3310c3278345adc6623716 Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Mon, 23 Jul 2018 11:46:35 +0100 Subject: [PATCH 13/13] [rust-server] Drop `file` support (#547) * [rust-server] drop 'file' support In swagger v2, we had 'binary', 'byte', and 'file'. OpenAPI v3 only has the former two. This commit drops the old 'file' handling. This has the side-effect of removing a half-complete implementation of form parameter handling. This removes the ability to send files as streams, so will make life harder for those wishing to send large files without running out of memory. * Remove all remaining uses of `hasFile` --- .../codegen/languages/RustServerCodegen.java | 32 +- .../main/resources/rust-server/Cargo.mustache | 4 +- .../resources/rust-server/client-mod.mustache | 58 +-- .../example-server_server.mustache | 7 +- .../main/resources/rust-server/lib.mustache | 6 +- .../resources/rust-server/mimetypes.mustache | 4 +- .../resources/rust-server/server-mod.mustache | 122 +----- ...ith-fake-endpoints-models-for-testing.yaml | 91 ++--- .../server/petstore/rust-server/Cargo.toml | 4 +- .../petstore/rust-server/api/openapi.yaml | 46 +++ .../petstore/rust-server/examples/client.rs | 6 +- .../rust-server/examples/server_lib/server.rs | 16 +- .../petstore/rust-server/src/client/mod.rs | 194 ++------- .../server/petstore/rust-server/src/lib.rs | 22 +- .../petstore/rust-server/src/mimetypes.rs | 12 + .../server/petstore/rust-server/src/models.rs | 23 ++ .../petstore/rust-server/src/server/mod.rs | 379 ++---------------- 17 files changed, 238 insertions(+), 788 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 7c21c824df6..a39033a4501 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 @@ -164,8 +164,8 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig { typeMapping.put("date", "chrono::DateTime"); typeMapping.put("DateTime", "chrono::DateTime"); typeMapping.put("password", "String"); - typeMapping.put("File", "Box, Error=Error> + Send>"); - typeMapping.put("file", "Box, Error=Error> + Send>"); + typeMapping.put("File", "swagger::ByteArray"); + typeMapping.put("file", "swagger::ByteArray"); typeMapping.put("array", "Vec"); typeMapping.put("map", "HashMap"); @@ -710,8 +710,6 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig { } header.nameInCamelCase = toModelName(header.baseName); } - - additionalProperties.put("apiHasFile", true); } return objs; @@ -1069,22 +1067,11 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig { private void processParam(CodegenParameter param, CodegenOperation op) { String example = null; - if (param.isFile) { - param.vendorExtensions.put("formatString", "{:?}"); - op.vendorExtensions.put("hasFile", true); - additionalProperties.put("apiHasFile", true); - example = "Box::new(stream::once(Ok(b\"hello\".to_vec()))) as Box + Send>"; - } else if (param.isString) { - if (param.dataFormat != null && param.dataFormat.equals("byte")) { - param.vendorExtensions.put("formatString", "\\\"{:?}\\\""); - example = "swagger::ByteArray(\"" + ((param.example != null) ? param.example : "") + "\".to_string().into_bytes())"; - } else { - param.vendorExtensions.put("formatString", "\\\"{}\\\""); - example = "\"" + ((param.example != null) ? param.example : "") + "\".to_string()"; - } + if (param.isString) { + param.vendorExtensions.put("formatString", "\\\"{}\\\""); + example = "\"" + ((param.example != null) ? param.example : "") + "\".to_string()"; } else if (param.isPrimitiveType) { - if ((param.isByteArray) || - (param.isBinary)) { + if ((param.isByteArray) || (param.isBinary)) { // Binary primitive types don't implement `Display`. param.vendorExtensions.put("formatString", "{:?}"); example = "swagger::ByteArray(Vec::from(\"" + ((param.example != null) ? param.example : "") + "\"))"; @@ -1119,12 +1106,7 @@ public class RustServerCodegen extends DefaultCodegen implements CodegenConfig { } else { // Not required, so override the format string and example param.vendorExtensions.put("formatString", "{:?}"); - if (param.isFile) { - // Optional file types are wrapped in a future - param.vendorExtensions.put("example", (example != null) ? "Box::new(future::ok(Some(" + example + "))) as Box + Send>" : "None"); - } else { - param.vendorExtensions.put("example", (example != null) ? "Some(" + example + ")" : "None"); - } + param.vendorExtensions.put("example", (example != null) ? "Some(" + example + ")" : "None"); } } } diff --git a/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache b/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache index f3496ed3856..7f3190a4c7c 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache @@ -9,8 +9,8 @@ license = "Unlicense" [features] default = ["client", "server"] -client = ["serde_json", {{#usesUrlEncodedForm}}"serde_urlencoded", {{/usesUrlEncodedForm}} {{#usesXml}}"serde-xml-rs", {{/usesXml}}"serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url", "uuid"{{#apiHasFile}}, "multipart"{{/apiHasFile}}] -server = ["serde_json", {{#usesXml}}"serde-xml-rs", {{/usesXml}}"serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url", "uuid"{{#apiHasFile}}, "multipart"{{/apiHasFile}}] +client = ["serde_json", {{#usesUrlEncodedForm}}"serde_urlencoded", {{/usesUrlEncodedForm}} {{#usesXml}}"serde-xml-rs", {{/usesXml}}"serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url", "uuid"] +server = ["serde_json", {{#usesXml}}"serde-xml-rs", {{/usesXml}}"serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url", "uuid"] [dependencies] # Required by example server. 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 0e78e327394..5326545bf5f 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 @@ -6,11 +6,9 @@ extern crate openssl; extern crate mime; extern crate chrono; extern crate url; -{{#apiHasFile}}extern crate multipart;{{/apiHasFile}} {{#usesUrlEncodedForm}}extern crate serde_urlencoded;{{/usesUrlEncodedForm}} {{#apiUsesUuid}}use uuid;{{/apiUsesUuid}} -{{#apiHasFile}}use self::multipart::client::lazy::Multipart;{{/apiHasFile}} use hyper; use hyper::header::{Headers, ContentType}; use hyper::Uri; @@ -239,7 +237,7 @@ impl Api for Client where F: Future + 'static, C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}}{ {{#apiInfo}}{{#apis}}{{#operations}}{{#operation}} - fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, param_{{paramName}}: {{^required}}{{#isFile}}Box{{#isFile}}, Error=Error> + Send>{{/isFile}}{{/required}}{{/allParams}}, context: &C) -> Box> { + fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, param_{{paramName}}: {{^required}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{/required}}{{/allParams}}, context: &C) -> Box> { {{#queryParams}}{{#-first}} // Query parameters {{/-first}}{{#required}} let query_{{paramName}} = format!("{{baseName}}={{=<% %>=}}{<% paramName %>}<%={{ }}=%>&", {{paramName}}=param_{{paramName}}{{#isListContainer}}.join(","){{/isListContainer}}{{^isListContainer}}.to_string(){{/isListContainer}}); @@ -259,47 +257,13 @@ impl Api for Client where let mut request = hyper::Request::new(hyper::Method::{{#vendorExtensions}}{{HttpMethod}}{{/vendorExtensions}}, uri); -{{#vendorExtensions}}{{#hasFile}} // Form data body - let mut multipart = Multipart::new(); - - // Helper function to convert a Stream into a String. The String can then be used to build the HTTP body. - fn convert_stream_to_string(stream: Box, Error=Error> + Send>) -> Result { - - stream.concat2() - .wait() - .map_err(|e| ApiError(format!("Unable to collect stream: {}", e))) - .and_then(|body| String::from_utf8(body) - .map_err(|e| ApiError(format!("Failed to convert utf8 stream to String: {}", e)))) - }{{/hasFile}}{{/vendorExtensions}}{{#formParams}}{{#isFile}} - -{{^required}} if let Ok(Some(param_{{paramName}})) = param_{{paramName}}.wait() { {{/required}} -{{^required}} {{/required}} match convert_stream_to_string(param_{{paramName}}) { -{{^required}} {{/required}} Ok(param_{{paramName}}) => { - // Add file to multipart form. - multipart.add_text("{{paramName}}", param_{{paramName}}); - }, -{{^required}} {{/required}} Err(err) => return Box::new(futures::done(Err(err))), -{{^required}} {{/required}} } - {{^required}}}{{/required}}{{/isFile}}{{/formParams}}{{#vendorExtensions}}{{#hasFile}} - - let mut fields = match multipart.prepare() { - Ok(fields) => fields, - Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to build request: {}", err))))), - }; - - let mut body_string = String::new(); - let body = fields.to_body().read_to_string(&mut body_string); - let boundary = fields.boundary(); - let multipart_header = match mime::Mime::from_str(&format!("multipart/form-data;boundary={}", boundary)) { - Ok(multipart_header) => multipart_header, - Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to build multipart header: {:?}", err))))), - };{{/hasFile}}{{^hasFile}}{{#formParams}}{{#-first}} let params = &[{{/-first}} +{{#vendorExtensions}}{{#formParams}}{{#-first}} let params = &[{{/-first}} ("{{baseName}}", {{#vendorExtensions}}{{#required}}Some({{#isString}}param_{{paramName}}{{/isString}}{{^isString}}format!("{:?}", param_{{paramName}}){{/isString}}){{/required}}{{^required}}{{#isString}}param_{{paramName}}{{/isString}}{{^isString}}param_{{paramName}}.map(|param| format!("{:?}", param)){{/isString}}{{/required}}),{{/vendorExtensions}}{{#-last}} ]; let body = serde_urlencoded::to_string(params).expect("impossible to fail to serialize"); request.headers_mut().set(ContentType(mimetypes::requests::{{#vendorExtensions}}{{uppercase_operation_id}}{{/vendorExtensions}}.clone())); - request.set_body(body.into_bytes());{{/-last}}{{/formParams}}{{/hasFile}}{{/vendorExtensions}}{{#bodyParam}}{{#-first}} + request.set_body(body.into_bytes());{{/-last}}{{/formParams}}{{/vendorExtensions}}{{#bodyParam}}{{#-first}} // Body parameter {{/-first}}{{#vendorExtensions}}{{#required}}{{#consumesPlainText}} let body = param_{{paramName}};{{/consumesPlainText}}{{#consumesXml}} {{^has_namespace}} let body = serde_xml_rs::to_string(¶m_{{paramName}}).expect("impossible to fail to serialize");{{/has_namespace}}{{#has_namespace}} @@ -340,11 +304,6 @@ impl Api for Client where {{/required}}{{/isMapContainer}}{{#isMapContainer}} let param_{{paramName}}: Option<{{{dataType}}}> = None; {{/isMapContainer}}{{/headerParams}} -{{#vendorExtensions}}{{#hasFile}} - request.headers_mut().set(ContentType(multipart_header)); - request.set_body(body_string.into_bytes()); -{{/hasFile}}{{/vendorExtensions}} - Box::new(self.client_service.call(request) .map_err(|e| ApiError(format!("No response received: {}", e))) .and_then(|mut response| { @@ -357,13 +316,9 @@ impl Api for Client where None => return Box::new(future::err(ApiError(String::from("Required response header {{baseName}} for response {{code}} was not found.")))) as Box>, }; {{/headers}} - {{^isFile}}let body = response.body();{{/isFile}}{{#isFile}}let body = Box::new(response.body() - .map(|chunk| chunk.to_vec()) - .map_err(|_| - Error::new(ErrorKind::Other, "Received error reading response.") - ));{{/isFile}} + let body = response.body(); Box::new( -{{#dataType}}{{^isFile}} +{{#dataType}} body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) @@ -383,9 +338,6 @@ impl Api for Client where {{/producesPlainText}}{{/vendorExtensions}} )) .map(move |body| -{{/isFile}}{{#isFile}} - future::ok( -{{/isFile}} {{operationId}}Response::{{#vendorExtensions}}{{x-responseId}}{{/vendorExtensions}}{{^headers}}(body){{/headers}}{{#headers}}{{#-first}}{ body: body, {{/-first}}{{name}}: response_{{name}}{{^-last}}, {{/-last}}{{#-last}} }{{/-last}}{{/headers}} ) {{/dataType}}{{^dataType}} diff --git a/modules/openapi-generator/src/main/resources/rust-server/example-server_server.mustache b/modules/openapi-generator/src/main/resources/rust-server/example-server_server.mustache index c5122fcefac..ec7bfcab484 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/example-server_server.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/example-server_server.mustache @@ -4,9 +4,7 @@ use futures::{self, Future}; use chrono; -{{#apiHasFile}}use futures::Stream;{{/apiHasFile}} use std::collections::HashMap; -{{#apiHasFile}}use std::io::Error;{{/apiHasFile}} use std::marker::PhantomData; {{#apiUsesUuid}}use uuid;{{/apiUsesUuid}} use swagger; @@ -31,10 +29,9 @@ impl Server { impl Api for Server where C: Has{ {{#apiInfo}}{{#apis}}{{#operations}}{{#operation}} {{#summary}} /// {{{summary}}}{{/summary}} - fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, {{paramName}}: {{^required}}{{#isFile}}Box{{#isFile}}, Error=Error> + Send>{{/isFile}}{{/required}}{{/allParams}}, context: &C) -> Box> { + fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, {{paramName}}: {{^required}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{/required}}{{/allParams}}, context: &C) -> Box> { let context = context.clone(); - println!("{{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}({{#allParams}}{{^isFile}}{{#vendorExtensions}}{{{formatString}}}{{/vendorExtensions}}{{#hasMore}}, {{/hasMore}}{{/isFile}}{{/allParams}}) - X-Span-ID: {:?}"{{#allParams}}{{^isFile}}, {{paramName}}{{/isFile}}{{/allParams}}, context.get().0.clone());{{#allParams}}{{#isFile}} - let _ = {{paramName}}; //Suppresses unused param warning{{/isFile}}{{/allParams}} + println!("{{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}({{#allParams}}{{#vendorExtensions}}{{{formatString}}}{{/vendorExtensions}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) - X-Span-ID: {:?}"{{#allParams}}, {{paramName}}{{/allParams}}, context.get().0.clone());{{#allParams}}{{/allParams}} Box::new(futures::failed("Generic failure".into())) } {{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} diff --git a/modules/openapi-generator/src/main/resources/rust-server/lib.mustache b/modules/openapi-generator/src/main/resources/rust-server/lib.mustache index 7066a7b41ea..48318f52c6a 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/lib.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/lib.mustache @@ -51,7 +51,7 @@ pub enum {{operationId}}Response { pub trait Api { {{#apiInfo}}{{#apis}}{{#operations}}{{#operation}} {{#summary}} /// {{{summary}}}{{/summary}} - fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, {{paramName}}: {{^required}}{{#isFile}}Box{{#isFile}}, Error=Error> + Send>{{/isFile}}{{/required}}{{/allParams}}, context: &C) -> Box>; + fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, {{paramName}}: {{^required}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{/required}}{{/allParams}}, context: &C) -> Box>; {{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} } @@ -59,7 +59,7 @@ pub trait Api { pub trait ApiNoContext { {{#apiInfo}}{{#apis}}{{#operations}}{{#operation}} {{#summary}} /// {{{summary}}}{{/summary}} - fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, {{paramName}}: {{^required}}{{#isFile}}Box{{#isFile}}, Error=Error> + Send>{{/isFile}}{{/required}}{{/allParams}}) -> Box>; + fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, {{paramName}}: {{^required}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{/required}}{{/allParams}}) -> Box>; {{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} } @@ -78,7 +78,7 @@ impl<'a, T: Api + Sized, C> ContextWrapperExt<'a, C> for T { impl<'a, T: Api, C> ApiNoContext for ContextWrapper<'a, T, C> { {{#apiInfo}}{{#apis}}{{#operations}}{{#operation}} {{#summary}} /// {{{summary}}}{{/summary}} - fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, {{paramName}}: {{^required}}{{#isFile}}Box{{#isFile}}, Error=Error> + Send>{{/isFile}}{{/required}}{{/allParams}}) -> Box> { + fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, {{paramName}}: {{^required}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{/required}}{{/allParams}}) -> Box> { self.api().{{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}({{#allParams}}{{paramName}}, {{/allParams}}&self.context()) } {{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} diff --git a/modules/openapi-generator/src/main/resources/rust-server/mimetypes.mustache b/modules/openapi-generator/src/main/resources/rust-server/mimetypes.mustache index 047c7c7fbbc..eae9743e2d4 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/mimetypes.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/mimetypes.mustache @@ -17,9 +17,9 @@ pub mod requests { lazy_static! { pub static ref {{#vendorExtensions}}{{uppercase_operation_id}}{{/vendorExtensions}}: Mime = "{{#consumes}}{{#-first}}{{{mediaType}}}{{/-first}}{{/consumes}}{{^consumes}}application/json{{/consumes}}".parse().unwrap(); } -{{/bodyParam}}{{^bodyParam}}{{#vendorExtensions}}{{#formParams}}{{#-first}}{{^hasFile}} /// Create Mime objects for the request content types for {{operationId}} +{{/bodyParam}}{{^bodyParam}}{{#vendorExtensions}}{{#formParams}}{{#-first}} /// Create Mime objects for the request content types for {{operationId}} lazy_static! { pub static ref {{#vendorExtensions}}{{uppercase_operation_id}}{{/vendorExtensions}}: Mime = "{{#consumes}}{{#-first}}{{{mediaType}}}{{/-first}}{{/consumes}}{{^consumes}}application/x-www-form-urlencoded{{/consumes}}".parse().unwrap(); } -{{/hasFile}}{{/-first}}{{/formParams}}{{/vendorExtensions}}{{/bodyParam}}{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} +{{/-first}}{{/formParams}}{{/vendorExtensions}}{{/bodyParam}}{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} } 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 a32d7031e0f..8d20ed82a6f 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 @@ -7,7 +7,6 @@ extern crate openssl; extern crate mime; {{^apiUsesUuid}}extern crate uuid;{{/apiUsesUuid}} extern crate chrono; -{{#apiHasFile}}extern crate multipart;{{/apiHasFile}} extern crate percent_encoding; extern crate url; @@ -20,8 +19,6 @@ use hyper::{Request, Response, Error, StatusCode}; use hyper::header::{Headers, ContentType}; use self::url::form_urlencoded; use mimetypes; -{{#apiHasFile}}use self::multipart::server::Multipart; -use self::multipart::server::save::SaveResult;{{/apiHasFile}} use serde_json; {{#usesXml}}use serde_xml_rs;{{/usesXml}} @@ -277,51 +274,7 @@ where }; {{/required}} {{/-first}}{{/bodyParams}} -{{^bodyParams}}{{#vendorExtensions}}{{#hasFile}} - let boundary = match multipart_boundary(&headers) { - Some(boundary) => boundary.to_string(), - None => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body("Couldn't find valid multipart body"))), - }; - - Box::new(body.concat2() - .then(move |result| -> Box> { - match result { - Ok(body) => { - let mut entries = match Multipart::with_body(&body.to_vec()[..], boundary).save().temp() { - SaveResult::Full(entries) => { - entries - }, - _ => { - return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Unable to process all message parts")))) - }, - }; -{{#formParams}}{{#-first}} - // Form parameters -{{/-first}} - let param_{{paramName}} = entries.fields.remove("{{paramName}}"); - let param_{{paramName}} = match param_{{paramName}} { - Some(entry) => -{{#isFile}} - {{^required}}Some({{/required}}Box::new(stream::once(Ok(entry.as_bytes().to_vec()))) as Box, Error=io::Error> + Send>{{^required}}){{/required}}, -{{/isFile}}{{^isFile}} - match entry.parse::<{{{dataType}}}>() { - Ok(entry) => {{^required}}Some({{/required}}entry{{^required}}){{/required}}, -{{#required}} - Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse form parameter {{baseName}} - doesn't match schema: {}", e)))), -{{/required}}{{^required}} - Err(_) => None, -{{/required}} - }, -{{/isFile}} -{{#required}} - None => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Missing required form parameter {{paramName}}")))), -{{/required}}{{^required}} - None => None, -{{/required}} - }; -{{^required}}{{#isFile}} let param_{{paramName}} = Box::new(future::ok(param_{{paramName}}));{{/isFile}}{{/required}} -{{/formParams}} -{{/hasFile}}{{^hasFile}} +{{^bodyParams}}{{#vendorExtensions}} Box::new({ {{ {{#formParams}}{{#-first}} @@ -329,7 +282,7 @@ where {{/-first}} let param_{{paramName}} = {{^isContainer}}{{#vendorExtensions}}{{{example}}};{{/vendorExtensions}}{{/isContainer}}{{#isListContainer}}{{#required}}Vec::new();{{/required}}{{^required}}None;{{/required}}{{/isListContainer}}{{#isMapContainer}}None;{{/isMapContainer}} {{/formParams}} -{{/hasFile}}{{/vendorExtensions}}{{/bodyParams}} +{{/vendorExtensions}}{{/bodyParams}} Box::new(api_impl.{{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}({{#allParams}}param_{{paramName}}{{#isListContainer}}.as_ref(){{/isListContainer}}, {{/allParams}}&context) .then(move |result| { let mut response = Response::new(); @@ -364,7 +317,7 @@ where {{/-last}} {{/headers}}{{/dataType}} => { -{{^isFile}} response.set_status(StatusCode::try_from({{code}}).unwrap()); + response.set_status(StatusCode::try_from({{code}}).unwrap()); {{#headers}} header! { (Response{{nameInCamelCase}}, "{{baseName}}") => [{{{dataType}}}] } response.headers_mut().set(Response{{nameInCamelCase}}({{name}})); @@ -384,34 +337,7 @@ where let body = serde_json::to_string(&body).expect("impossible to fail to serialize"); {{/producesJson}}{{/vendorExtensions}} response.set_body(body); -{{/dataType}}{{/isFile}}{{#isFile}} - let body = body.fold(Vec::new(), | mut body, chunk| { - body.extend(chunk.iter()); - future::ok::, io::Error>(body) - }) - // Block whilst waiting for the stream to complete - .wait(); - - match body { - // If no error occurred then create successful hyper response - Ok(vec) => { - response.set_status(StatusCode::try_from({{code}}).unwrap()); - -{{#headers}} - header! { (Response{{nameInCamelCase}}, "{{baseName}}") => [{{{dataType}}}] } - response.headers_mut().set(Response{{nameInCamelCase}}({{name}})); -{{/headers}}{{#produces}}{{#-first}}{{#dataType}} - response.headers_mut().set(ContentType(mimetypes::responses::{{#vendorExtensions}}{{uppercase_operation_id}}_{{x-uppercaseResponseId}}{{/vendorExtensions}}.clone())); -{{/dataType}}{{/-first}}{{/produces}} - response.set_body(vec); - }, - // It's possible that errors were received in the stream, if this is the case then we can't return a success response to the client and instead must return an internal error. - Err(e) => { - response.set_status(StatusCode::InternalServerError); - response.set_body("An internal error occurred"); - } - } -{{/isFile}} +{{/dataType}} }, {{/responses}} }, @@ -426,17 +352,10 @@ where future::ok(response) } )) -{{^bodyParams}}{{#vendorExtensions}}{{^hasFile}} +{{^bodyParams}}{{#vendorExtensions}} }} }) as Box> -{{/hasFile}}{{#hasFile}} - as Box> - }, - Err(e) => Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't read multipart body")))), - } - }) - ) -{{/hasFile}}{{/vendorExtensions}}{{/bodyParams}} +{{/vendorExtensions}}{{/bodyParams}} {{#bodyParams}}{{#-first}} }, Err(e) => Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't read body parameter {{baseName}}: {}", e)))), @@ -451,32 +370,3 @@ where } } } - -{{#apiHasFile}} -/// Utility function to get the multipart boundary marker (if any) from the Headers. -fn multipart_boundary<'a>(headers: &'a Headers) -> Option<&'a str> { - headers.get::().and_then(|content_type| { - let ContentType(ref mime) = *content_type; - if mime.type_() == mime::MULTIPART && mime.subtype() == mime::FORM_DATA { - mime.get_param(mime::BOUNDARY).map(|x| x.as_str()) - } else { - None - } - }) -} -{{/apiHasFile}} - -/// Request parser for `Api`. -pub struct ApiRequestParser; - -impl RequestParser for ApiRequestParser { - fn parse_operation_id(request: &Request) -> Result<&'static str, ()> { - let path = paths::GLOBAL_REGEX_SET.matches(request.uri().path()); - match request.method() { -{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}} - // {{operationId}} - {{httpMethod}} {{path}} - &hyper::Method::{{vendorExtensions.HttpMethod}} if path.matched(paths::ID_{{vendorExtensions.PATH_ID}}) => Ok("{{operationId}}"), -{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} _ => Err(()), - } - } -} diff --git a/modules/openapi-generator/src/test/resources/2_0/rust-server/petstore-with-fake-endpoints-models-for-testing.yaml b/modules/openapi-generator/src/test/resources/2_0/rust-server/petstore-with-fake-endpoints-models-for-testing.yaml index 0df5dc18cfa..18ccb6b5d76 100644 --- a/modules/openapi-generator/src/test/resources/2_0/rust-server/petstore-with-fake-endpoints-models-for-testing.yaml +++ b/modules/openapi-generator/src/test/resources/2_0/rust-server/petstore-with-fake-endpoints-models-for-testing.yaml @@ -608,6 +608,7 @@ paths: consumes: - "application/x-www-form-urlencoded" parameters: + # See https://github.com/OpenAPITools/openapi-generator/issues/545 # - name: enum_form_string_array # type: array # items: @@ -618,15 +619,15 @@ paths: # - '$' # in: formData # description: Form parameter enum test (string array) - # - name: enum_form_string - # type: string - # default: '-efg' - # enum: - # - _abc - # - '-efg' - # - (xyz) - # in: formData - # description: Form parameter enum test (string) + - name: enum_form_string + type: string + default: '-efg' + enum: + - _abc + - '-efg' + - (xyz) + in: formData + description: Form parameter enum test (string) - name: enum_header_string_array type: array items: @@ -753,12 +754,12 @@ paths: in: formData description: None required: true - # - name: byte - # type: string - # format: byte - # in: formData - # description: None - # required: true + - name: byte + type: string + format: byte + in: formData + description: None + required: true - name: binary type: string format: binary @@ -1204,9 +1205,9 @@ definitions: byte: type: string format: byte - # binary: - # type: string - # format: binary + binary: + type: string + format: binary date: type: string format: date @@ -1338,16 +1339,15 @@ definitions: type: object additionalProperties: type: string - # comment out the following (map of map of enum) as many language not yet support this - #map_map_of_enum: - # type: object - # additionalProperties: - # type: object - # additionalProperties: - # type: string - # enum: - # - UPPER - # - lower + map_map_of_enum: + type: object + additionalProperties: + type: object + additionalProperties: + type: string + enum: + - UPPER + - lower map_of_enum_string: type: object additionalProperties: @@ -1375,15 +1375,13 @@ definitions: type: array items: $ref: '#/definitions/ReadOnlyFirst' - # commented out the below test case for array of enum for the time being - # as not all language can handle it - #array_of_enum: - # type: array - # items: - # type: string - # enum: - # - UPPER - # - lower + array_of_enum: + type: array + items: + type: string + enum: + - UPPER + - lower NumberOnly: type: object properties: @@ -1420,16 +1418,15 @@ definitions: enum: - fish - crab - # comment out the following as 2d array of enum is not supported at the moment - #array_array_enum: - # type: array - # items: - # type: array - # items: - # type: string - # enum: - # - Cat - # - Dog + array_array_enum: + type: array + items: + type: array + items: + type: string + enum: + - Cat + - Dog OuterEnum: type: "string" enum: diff --git a/samples/server/petstore/rust-server/Cargo.toml b/samples/server/petstore/rust-server/Cargo.toml index ce79b9f32b6..5e6be7d7a41 100644 --- a/samples/server/petstore/rust-server/Cargo.toml +++ b/samples/server/petstore/rust-server/Cargo.toml @@ -7,8 +7,8 @@ license = "Unlicense" [features] default = ["client", "server"] -client = ["serde_json", "serde_urlencoded", "serde-xml-rs", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url", "uuid", "multipart"] -server = ["serde_json", "serde-xml-rs", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url", "uuid", "multipart"] +client = ["serde_json", "serde_urlencoded", "serde-xml-rs", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "url", "uuid"] +server = ["serde_json", "serde-xml-rs", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio-core", "tokio-proto", "tokio-tls", "regex", "percent-encoding", "url", "uuid"] [dependencies] # Required by example server. diff --git a/samples/server/petstore/rust-server/api/openapi.yaml b/samples/server/petstore/rust-server/api/openapi.yaml index 2747b636766..4d996d5916a 100644 --- a/samples/server/petstore/rust-server/api/openapi.yaml +++ b/samples/server/petstore/rust-server/api/openapi.yaml @@ -657,6 +657,19 @@ paths: - -1.2 format: double type: number + requestBody: + content: + application/x-www-form-urlencoded: + schema: + properties: + enum_form_string: + default: -efg + description: Form parameter enum test (string) + enum: + - _abc + - -efg + - (xyz) + type: string responses: 400: content: {} @@ -738,6 +751,10 @@ paths: description: None pattern: ^[A-Z].* type: string + byte: + description: None + format: byte + type: string binary: description: None format: binary @@ -760,6 +777,7 @@ paths: description: None type: string required: + - byte - double - number - pattern_without_delimiter @@ -1247,6 +1265,13 @@ components: $ref: '#/components/schemas/ReadOnlyFirst' type: array type: array + array_of_enum: + items: + enum: + - UPPER + - lower + type: string + type: array type: object OuterComposite: example: @@ -1297,6 +1322,9 @@ components: format: byte pattern: ^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$ type: string + binary: + format: binary + type: string date: format: date type: string @@ -1331,6 +1359,15 @@ components: - crab type: string type: array + array_array_enum: + items: + items: + enum: + - Cat + - Dog + type: string + type: array + type: array type: object OuterString: type: string @@ -1370,6 +1407,15 @@ components: type: string type: object type: object + map_map_of_enum: + additionalProperties: + additionalProperties: + enum: + - UPPER + - lower + type: string + type: object + type: object map_of_enum_string: additionalProperties: enum: diff --git a/samples/server/petstore/rust-server/examples/client.rs b/samples/server/petstore/rust-server/examples/client.rs index 3bd3a350970..d87dd25b87e 100644 --- a/samples/server/petstore/rust-server/examples/client.rs +++ b/samples/server/petstore/rust-server/examples/client.rs @@ -160,12 +160,12 @@ fn main() { // }, Some("TestEndpointParameters") => { - let result = core.run(client.test_endpoint_parameters(8.14, 1.2, "pattern_without_delimiter_example".to_string(), Some(56), Some(56), Some(789), Some(3.4), Some("string_example".to_string()), Box::new(future::ok(Some(Box::new(stream::once(Ok(b"hello".to_vec()))) as Box + Send>))) as Box + Send>, None, None, Some("password_example".to_string()), Some("callback_example".to_string()))); + let result = core.run(client.test_endpoint_parameters(8.14, 1.2, "pattern_without_delimiter_example".to_string(), swagger::ByteArray(Vec::from("BYTE_ARRAY_DATA_HERE")), Some(56), Some(56), Some(789), Some(3.4), Some("string_example".to_string()), Some(swagger::ByteArray(Vec::from("BINARY_DATA_HERE"))), None, None, Some("password_example".to_string()), Some("callback_example".to_string()))); println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &Has).get().clone()); }, Some("TestEnumParameters") => { - let result = core.run(client.test_enum_parameters(Some(&Vec::new()), Some("enum_header_string_example".to_string()), Some(&Vec::new()), Some("enum_query_string_example".to_string()), Some(56), Some(1.2))); + let result = core.run(client.test_enum_parameters(Some(&Vec::new()), Some("enum_header_string_example".to_string()), Some(&Vec::new()), Some("enum_query_string_example".to_string()), Some(56), Some(1.2), Some("enum_form_string_example".to_string()))); println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &Has).get().clone()); }, @@ -224,7 +224,7 @@ fn main() { }, Some("UploadFile") => { - let result = core.run(client.upload_file(789, Some("additional_metadata_example".to_string()), Box::new(future::ok(Some(Box::new(stream::once(Ok(b"hello".to_vec()))) as Box + Send>))) as Box + Send>)); + let result = core.run(client.upload_file(789, Some("additional_metadata_example".to_string()), Some(swagger::ByteArray(Vec::from("BINARY_DATA_HERE"))))); println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &Has).get().clone()); }, diff --git a/samples/server/petstore/rust-server/examples/server_lib/server.rs b/samples/server/petstore/rust-server/examples/server_lib/server.rs index 47b50031127..c470b7be109 100644 --- a/samples/server/petstore/rust-server/examples/server_lib/server.rs +++ b/samples/server/petstore/rust-server/examples/server_lib/server.rs @@ -4,9 +4,7 @@ use futures::{self, Future}; use chrono; -use futures::Stream; use std::collections::HashMap; -use std::io::Error; use std::marker::PhantomData; use swagger; @@ -111,17 +109,16 @@ impl Api for Server where C: Has{ } /// Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트 - fn test_endpoint_parameters(&self, number: f64, double: f64, pattern_without_delimiter: String, integer: Option, int32: Option, int64: Option, float: Option, string: Option, binary: Box, Error=Error> + Send>>, Error=Error> + Send>, date: Option>, date_time: Option>, password: Option, callback: Option, context: &C) -> Box> { + fn test_endpoint_parameters(&self, number: f64, double: f64, pattern_without_delimiter: String, byte: swagger::ByteArray, integer: Option, int32: Option, int64: Option, float: Option, string: Option, binary: Option, date: Option>, date_time: Option>, password: Option, callback: Option, context: &C) -> Box> { let context = context.clone(); - println!("test_endpoint_parameters({}, {}, \"{}\", {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}) - X-Span-ID: {:?}", number, double, pattern_without_delimiter, integer, int32, int64, float, string, date, date_time, password, callback, context.get().0.clone()); - let _ = binary; //Suppresses unused param warning + println!("test_endpoint_parameters({}, {}, \"{}\", {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}) - X-Span-ID: {:?}", number, double, pattern_without_delimiter, byte, integer, int32, int64, float, string, binary, date, date_time, password, callback, context.get().0.clone()); Box::new(futures::failed("Generic failure".into())) } /// To test enum parameters - fn test_enum_parameters(&self, enum_header_string_array: Option<&Vec>, enum_header_string: Option, enum_query_string_array: Option<&Vec>, enum_query_string: Option, enum_query_integer: Option, enum_query_double: Option, context: &C) -> Box> { + fn test_enum_parameters(&self, enum_header_string_array: Option<&Vec>, enum_header_string: Option, enum_query_string_array: Option<&Vec>, enum_query_string: Option, enum_query_integer: Option, enum_query_double: Option, enum_form_string: Option, context: &C) -> Box> { let context = context.clone(); - println!("test_enum_parameters({:?}, {:?}, {:?}, {:?}, {:?}, {:?}) - X-Span-ID: {:?}", enum_header_string_array, enum_header_string, enum_query_string_array, enum_query_string, enum_query_integer, enum_query_double, context.get().0.clone()); + println!("test_enum_parameters({:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}) - X-Span-ID: {:?}", enum_header_string_array, enum_header_string, enum_query_string_array, enum_query_string, enum_query_integer, enum_query_double, enum_form_string, context.get().0.clone()); Box::new(futures::failed("Generic failure".into())) } @@ -196,10 +193,9 @@ impl Api for Server where C: Has{ } /// uploads an image - fn upload_file(&self, pet_id: i64, additional_metadata: Option, file: Box, Error=Error> + Send>>, Error=Error> + Send>, context: &C) -> Box> { + fn upload_file(&self, pet_id: i64, additional_metadata: Option, file: Option, context: &C) -> Box> { let context = context.clone(); - println!("upload_file({}, {:?}, ) - X-Span-ID: {:?}", pet_id, additional_metadata, context.get().0.clone()); - let _ = file; //Suppresses unused param warning + println!("upload_file({}, {:?}, {:?}) - X-Span-ID: {:?}", pet_id, additional_metadata, file, context.get().0.clone()); Box::new(futures::failed("Generic failure".into())) } diff --git a/samples/server/petstore/rust-server/src/client/mod.rs b/samples/server/petstore/rust-server/src/client/mod.rs index 587837a9bd1..42c2aac4b0c 100644 --- a/samples/server/petstore/rust-server/src/client/mod.rs +++ b/samples/server/petstore/rust-server/src/client/mod.rs @@ -6,11 +6,9 @@ extern crate openssl; extern crate mime; extern crate chrono; extern crate url; -extern crate multipart; extern crate serde_urlencoded; -use self::multipart::client::lazy::Multipart; use hyper; use hyper::header::{Headers, ContentType}; use hyper::Uri; @@ -298,8 +296,6 @@ impl Api for Client where 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| { @@ -307,7 +303,6 @@ impl Api for Client where 200 => { let body = response.body(); Box::new( - body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) @@ -378,8 +373,6 @@ if let Some(body) = body { 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| { @@ -387,7 +380,6 @@ if let Some(body) = body { 200 => { let body = response.body(); Box::new( - body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) @@ -456,8 +448,6 @@ if let Some(body) = body { 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| { @@ -465,7 +455,6 @@ if let Some(body) = body { 200 => { let body = response.body(); Box::new( - body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) @@ -534,8 +523,6 @@ if let Some(body) = body { 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| { @@ -543,7 +530,6 @@ if let Some(body) = body { 200 => { let body = response.body(); Box::new( - body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) @@ -612,8 +598,6 @@ if let Some(body) = body { 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| { @@ -621,7 +605,6 @@ if let Some(body) = body { 200 => { let body = response.body(); Box::new( - body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) @@ -692,8 +675,6 @@ if let Some(body) = body { 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| { @@ -757,8 +738,6 @@ if let Some(body) = body { 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| { @@ -766,7 +745,6 @@ if let Some(body) = body { 200 => { let body = response.body(); Box::new( - body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) @@ -807,7 +785,7 @@ if let Some(body) = body { } - fn test_endpoint_parameters(&self, param_number: f64, param_double: f64, param_pattern_without_delimiter: String, param_integer: Option, param_int32: Option, param_int64: Option, param_float: Option, param_string: Option, param_binary: Box, Error=Error> + Send>>, Error=Error> + Send>, param_date: Option>, param_date_time: Option>, param_password: Option, param_callback: Option, context: &C) -> Box> { + fn test_endpoint_parameters(&self, param_number: f64, param_double: f64, param_pattern_without_delimiter: String, param_byte: swagger::ByteArray, param_integer: Option, param_int32: Option, param_int64: Option, param_float: Option, param_string: Option, param_binary: Option, param_date: Option>, param_date_time: Option>, param_password: Option, param_callback: Option, context: &C) -> Box> { let uri = format!( @@ -822,41 +800,26 @@ if let Some(body) = body { let mut request = hyper::Request::new(hyper::Method::Post, uri); - // Form data body - let mut multipart = Multipart::new(); + let params = &[ + ("integer", param_integer.map(|param| format!("{:?}", param))), + ("int32", param_int32.map(|param| format!("{:?}", param))), + ("int64", param_int64.map(|param| format!("{:?}", param))), + ("number", Some(format!("{:?}", param_number))), + ("float", param_float.map(|param| format!("{:?}", param))), + ("double", Some(format!("{:?}", param_double))), + ("string", param_string), + ("pattern_without_delimiter", Some(param_pattern_without_delimiter)), + ("byte", Some(format!("{:?}", param_byte))), + ("binary", param_binary.map(|param| format!("{:?}", param))), + ("date", param_date.map(|param| format!("{:?}", param))), + ("dateTime", param_date_time.map(|param| format!("{:?}", param))), + ("password", param_password), + ("callback", param_callback), + ]; + let body = serde_urlencoded::to_string(params).expect("impossible to fail to serialize"); - // Helper function to convert a Stream into a String. The String can then be used to build the HTTP body. - fn convert_stream_to_string(stream: Box, Error=Error> + Send>) -> Result { - - stream.concat2() - .wait() - .map_err(|e| ApiError(format!("Unable to collect stream: {}", e))) - .and_then(|body| String::from_utf8(body) - .map_err(|e| ApiError(format!("Failed to convert utf8 stream to String: {}", e)))) - } - - if let Ok(Some(param_binary)) = param_binary.wait() { - match convert_stream_to_string(param_binary) { - Ok(param_binary) => { - // Add file to multipart form. - multipart.add_text("binary", param_binary); - }, - Err(err) => return Box::new(futures::done(Err(err))), - } - } - - let mut fields = match multipart.prepare() { - Ok(fields) => fields, - Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to build request: {}", err))))), - }; - - let mut body_string = String::new(); - let body = fields.to_body().read_to_string(&mut body_string); - let boundary = fields.boundary(); - let multipart_header = match mime::Mime::from_str(&format!("multipart/form-data;boundary={}", boundary)) { - Ok(multipart_header) => multipart_header, - Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to build multipart header: {:?}", err))))), - }; + request.headers_mut().set(ContentType(mimetypes::requests::TEST_ENDPOINT_PARAMETERS.clone())); + request.set_body(body.into_bytes()); request.headers_mut().set(XSpanId((context as &Has).get().0.clone())); (context as &Has>).get().as_ref().map(|auth_data| { @@ -867,11 +830,6 @@ if let Some(body) = body { } }); - - request.headers_mut().set(ContentType(multipart_header)); - request.set_body(body_string.into_bytes()); - - Box::new(self.client_service.call(request) .map_err(|e| ApiError(format!("No response received: {}", e))) .and_then(|mut response| { @@ -918,7 +876,7 @@ if let Some(body) = body { } - fn test_enum_parameters(&self, param_enum_header_string_array: Option<&Vec>, param_enum_header_string: Option, param_enum_query_string_array: Option<&Vec>, param_enum_query_string: Option, param_enum_query_integer: Option, param_enum_query_double: Option, context: &C) -> Box> { + fn test_enum_parameters(&self, param_enum_header_string_array: Option<&Vec>, param_enum_header_string: Option, param_enum_query_string_array: Option<&Vec>, param_enum_query_string: Option, param_enum_query_integer: Option, param_enum_query_double: Option, param_enum_form_string: Option, context: &C) -> Box> { // Query parameters let query_enum_query_string_array = param_enum_query_string_array.map_or_else(String::new, |query| format!("enum_query_string_array={enum_query_string_array}&", enum_query_string_array=query.join(","))); @@ -943,7 +901,13 @@ if let Some(body) = body { let mut request = hyper::Request::new(hyper::Method::Get, uri); + let params = &[ + ("enum_form_string", param_enum_form_string), + ]; + let body = serde_urlencoded::to_string(params).expect("impossible to fail to serialize"); + request.headers_mut().set(ContentType(mimetypes::requests::TEST_ENUM_PARAMETERS.clone())); + request.set_body(body.into_bytes()); request.headers_mut().set(XSpanId((context as &Has).get().0.clone())); @@ -954,8 +918,6 @@ if let Some(body) = body { param_enum_header_string.map(|header| request.headers_mut().set(RequestEnumHeaderString(header))); - - Box::new(self.client_service.call(request) .map_err(|e| ApiError(format!("No response received: {}", e))) .and_then(|mut response| { @@ -1028,8 +990,6 @@ if let Some(body) = body { 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| { @@ -1094,8 +1054,6 @@ if let Some(body) = body { 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| { @@ -1161,8 +1119,6 @@ if let Some(body) = body { 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| { @@ -1170,7 +1126,6 @@ if let Some(body) = body { 200 => { let body = response.body(); Box::new( - body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) @@ -1239,8 +1194,6 @@ if let Some(body) = body { 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| { @@ -1302,8 +1255,6 @@ if let Some(body) = body { param_api_key.map(|header| request.headers_mut().set(RequestApiKey(header))); - - Box::new(self.client_service.call(request) .map_err(|e| ApiError(format!("No response received: {}", e))) .and_then(|mut response| { @@ -1365,8 +1316,6 @@ if let Some(body) = body { 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| { @@ -1374,7 +1323,6 @@ if let Some(body) = body { 200 => { let body = response.body(); Box::new( - body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) @@ -1450,8 +1398,6 @@ if let Some(body) = body { 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| { @@ -1459,7 +1405,6 @@ if let Some(body) = body { 200 => { let body = response.body(); Box::new( - body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) @@ -1531,8 +1476,6 @@ if let Some(body) = body { 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| { @@ -1540,7 +1483,6 @@ if let Some(body) = body { 200 => { let body = response.body(); Box::new( - body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) @@ -1627,8 +1569,6 @@ if let Some(body) = body { 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| { @@ -1711,8 +1651,6 @@ if let Some(body) = body { 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| { @@ -1750,7 +1688,7 @@ if let Some(body) = body { } - fn upload_file(&self, param_pet_id: i64, param_additional_metadata: Option, param_file: Box, Error=Error> + Send>>, Error=Error> + Send>, context: &C) -> Box> { + fn upload_file(&self, param_pet_id: i64, param_additional_metadata: Option, param_file: Option, context: &C) -> Box> { let uri = format!( @@ -1765,50 +1703,18 @@ if let Some(body) = body { let mut request = hyper::Request::new(hyper::Method::Post, uri); - // Form data body - let mut multipart = Multipart::new(); + let params = &[ + ("additionalMetadata", param_additional_metadata), + ("file", param_file.map(|param| format!("{:?}", param))), + ]; + let body = serde_urlencoded::to_string(params).expect("impossible to fail to serialize"); - // Helper function to convert a Stream into a String. The String can then be used to build the HTTP body. - fn convert_stream_to_string(stream: Box, Error=Error> + Send>) -> Result { - - stream.concat2() - .wait() - .map_err(|e| ApiError(format!("Unable to collect stream: {}", e))) - .and_then(|body| String::from_utf8(body) - .map_err(|e| ApiError(format!("Failed to convert utf8 stream to String: {}", e)))) - } - - if let Ok(Some(param_file)) = param_file.wait() { - match convert_stream_to_string(param_file) { - Ok(param_file) => { - // Add file to multipart form. - multipart.add_text("file", param_file); - }, - Err(err) => return Box::new(futures::done(Err(err))), - } - } - - let mut fields = match multipart.prepare() { - Ok(fields) => fields, - Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to build request: {}", err))))), - }; - - let mut body_string = String::new(); - let body = fields.to_body().read_to_string(&mut body_string); - let boundary = fields.boundary(); - let multipart_header = match mime::Mime::from_str(&format!("multipart/form-data;boundary={}", boundary)) { - Ok(multipart_header) => multipart_header, - Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to build multipart header: {:?}", err))))), - }; + request.headers_mut().set(ContentType(mimetypes::requests::UPLOAD_FILE.clone())); + request.set_body(body.into_bytes()); request.headers_mut().set(XSpanId((context as &Has).get().0.clone())); - - request.headers_mut().set(ContentType(multipart_header)); - request.set_body(body_string.into_bytes()); - - Box::new(self.client_service.call(request) .map_err(|e| ApiError(format!("No response received: {}", e))) .and_then(|mut response| { @@ -1816,7 +1722,6 @@ if let Some(body) = body { 200 => { let body = response.body(); Box::new( - body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) @@ -1877,8 +1782,6 @@ if let Some(body) = body { 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| { @@ -1945,8 +1848,6 @@ if let Some(body) = body { 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| { @@ -1954,7 +1855,6 @@ if let Some(body) = body { 200 => { let body = response.body(); Box::new( - body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) @@ -2015,8 +1915,6 @@ if let Some(body) = body { 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| { @@ -2024,7 +1922,6 @@ if let Some(body) = body { 200 => { let body = response.body(); Box::new( - body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) @@ -2111,8 +2008,6 @@ if let Some(body) = body { 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| { @@ -2120,7 +2015,6 @@ if let Some(body) = body { 200 => { let body = response.body(); Box::new( - body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) @@ -2200,8 +2094,6 @@ if let Some(body) = body { 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| { @@ -2265,8 +2157,6 @@ if let Some(body) = body { 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| { @@ -2330,8 +2220,6 @@ if let Some(body) = body { 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| { @@ -2389,8 +2277,6 @@ if let Some(body) = body { 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| { @@ -2457,8 +2343,6 @@ if let Some(body) = body { 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| { @@ -2466,7 +2350,6 @@ if let Some(body) = body { 200 => { let body = response.body(); Box::new( - body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) @@ -2553,8 +2436,6 @@ if let Some(body) = body { 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| { @@ -2572,7 +2453,6 @@ if let Some(body) = body { }; let body = response.body(); Box::new( - body .concat2() .map_err(|e| ApiError(format!("Failed to read response: {}", e))) @@ -2644,8 +2524,6 @@ if let Some(body) = body { 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| { @@ -2709,8 +2587,6 @@ if let Some(body) = body { 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| { diff --git a/samples/server/petstore/rust-server/src/lib.rs b/samples/server/petstore/rust-server/src/lib.rs index d6534990ac3..2e3dc8744bb 100644 --- a/samples/server/petstore/rust-server/src/lib.rs +++ b/samples/server/petstore/rust-server/src/lib.rs @@ -288,10 +288,10 @@ pub trait Api { fn test_client_model(&self, client: models::Client, context: &C) -> Box>; /// Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트 - fn test_endpoint_parameters(&self, number: f64, double: f64, pattern_without_delimiter: String, integer: Option, int32: Option, int64: Option, float: Option, string: Option, binary: Box, Error=Error> + Send>>, Error=Error> + Send>, date: Option>, date_time: Option>, password: Option, callback: Option, context: &C) -> Box>; + fn test_endpoint_parameters(&self, number: f64, double: f64, pattern_without_delimiter: String, byte: swagger::ByteArray, integer: Option, int32: Option, int64: Option, float: Option, string: Option, binary: Option, date: Option>, date_time: Option>, password: Option, callback: Option, context: &C) -> Box>; /// To test enum parameters - fn test_enum_parameters(&self, enum_header_string_array: Option<&Vec>, enum_header_string: Option, enum_query_string_array: Option<&Vec>, enum_query_string: Option, enum_query_integer: Option, enum_query_double: Option, context: &C) -> Box>; + fn test_enum_parameters(&self, enum_header_string_array: Option<&Vec>, enum_header_string: Option, enum_query_string_array: Option<&Vec>, enum_query_string: Option, enum_query_integer: Option, enum_query_double: Option, enum_form_string: Option, context: &C) -> Box>; /// test inline additionalProperties fn test_inline_additional_properties(&self, request_body: HashMap, context: &C) -> Box>; @@ -324,7 +324,7 @@ pub trait Api { fn update_pet_with_form(&self, pet_id: i64, name: Option, status: Option, context: &C) -> Box>; /// uploads an image - fn upload_file(&self, pet_id: i64, additional_metadata: Option, file: Box, Error=Error> + Send>>, Error=Error> + Send>, context: &C) -> Box>; + fn upload_file(&self, pet_id: i64, additional_metadata: Option, file: Option, context: &C) -> Box>; /// Delete purchase order by ID fn delete_order(&self, order_id: String, context: &C) -> Box>; @@ -389,10 +389,10 @@ pub trait ApiNoContext { fn test_client_model(&self, client: models::Client) -> Box>; /// Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트 - fn test_endpoint_parameters(&self, number: f64, double: f64, pattern_without_delimiter: String, integer: Option, int32: Option, int64: Option, float: Option, string: Option, binary: Box, Error=Error> + Send>>, Error=Error> + Send>, date: Option>, date_time: Option>, password: Option, callback: Option) -> Box>; + fn test_endpoint_parameters(&self, number: f64, double: f64, pattern_without_delimiter: String, byte: swagger::ByteArray, integer: Option, int32: Option, int64: Option, float: Option, string: Option, binary: Option, date: Option>, date_time: Option>, password: Option, callback: Option) -> Box>; /// To test enum parameters - fn test_enum_parameters(&self, enum_header_string_array: Option<&Vec>, enum_header_string: Option, enum_query_string_array: Option<&Vec>, enum_query_string: Option, enum_query_integer: Option, enum_query_double: Option) -> Box>; + fn test_enum_parameters(&self, enum_header_string_array: Option<&Vec>, enum_header_string: Option, enum_query_string_array: Option<&Vec>, enum_query_string: Option, enum_query_integer: Option, enum_query_double: Option, enum_form_string: Option) -> Box>; /// test inline additionalProperties fn test_inline_additional_properties(&self, request_body: HashMap) -> Box>; @@ -425,7 +425,7 @@ pub trait ApiNoContext { fn update_pet_with_form(&self, pet_id: i64, name: Option, status: Option) -> Box>; /// uploads an image - fn upload_file(&self, pet_id: i64, additional_metadata: Option, file: Box, Error=Error> + Send>>, Error=Error> + Send>) -> Box>; + fn upload_file(&self, pet_id: i64, additional_metadata: Option, file: Option) -> Box>; /// Delete purchase order by ID fn delete_order(&self, order_id: String) -> Box>; @@ -515,13 +515,13 @@ impl<'a, T: Api, C> ApiNoContext for ContextWrapper<'a, T, C> { } /// Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트 - fn test_endpoint_parameters(&self, number: f64, double: f64, pattern_without_delimiter: String, integer: Option, int32: Option, int64: Option, float: Option, string: Option, binary: Box, Error=Error> + Send>>, Error=Error> + Send>, date: Option>, date_time: Option>, password: Option, callback: Option) -> Box> { - self.api().test_endpoint_parameters(number, double, pattern_without_delimiter, integer, int32, int64, float, string, binary, date, date_time, password, callback, &self.context()) + fn test_endpoint_parameters(&self, number: f64, double: f64, pattern_without_delimiter: String, byte: swagger::ByteArray, integer: Option, int32: Option, int64: Option, float: Option, string: Option, binary: Option, date: Option>, date_time: Option>, password: Option, callback: Option) -> Box> { + self.api().test_endpoint_parameters(number, double, pattern_without_delimiter, byte, integer, int32, int64, float, string, binary, date, date_time, password, callback, &self.context()) } /// To test enum parameters - fn test_enum_parameters(&self, enum_header_string_array: Option<&Vec>, enum_header_string: Option, enum_query_string_array: Option<&Vec>, enum_query_string: Option, enum_query_integer: Option, enum_query_double: Option) -> Box> { - self.api().test_enum_parameters(enum_header_string_array, enum_header_string, enum_query_string_array, enum_query_string, enum_query_integer, enum_query_double, &self.context()) + fn test_enum_parameters(&self, enum_header_string_array: Option<&Vec>, enum_header_string: Option, enum_query_string_array: Option<&Vec>, enum_query_string: Option, enum_query_integer: Option, enum_query_double: Option, enum_form_string: Option) -> Box> { + self.api().test_enum_parameters(enum_header_string_array, enum_header_string, enum_query_string_array, enum_query_string, enum_query_integer, enum_query_double, enum_form_string, &self.context()) } /// test inline additionalProperties @@ -575,7 +575,7 @@ impl<'a, T: Api, C> ApiNoContext for ContextWrapper<'a, T, C> { } /// uploads an image - fn upload_file(&self, pet_id: i64, additional_metadata: Option, file: Box, Error=Error> + Send>>, Error=Error> + Send>) -> Box> { + fn upload_file(&self, pet_id: i64, additional_metadata: Option, file: Option) -> Box> { self.api().upload_file(pet_id, additional_metadata, file, &self.context()) } diff --git a/samples/server/petstore/rust-server/src/mimetypes.rs b/samples/server/petstore/rust-server/src/mimetypes.rs index 9073c213ccb..afe949238ce 100644 --- a/samples/server/petstore/rust-server/src/mimetypes.rs +++ b/samples/server/petstore/rust-server/src/mimetypes.rs @@ -101,6 +101,14 @@ pub mod requests { lazy_static! { pub static ref TEST_CLIENT_MODEL: Mime = "application/json".parse().unwrap(); } + /// Create Mime objects for the request content types for TestEndpointParameters + lazy_static! { + pub static ref TEST_ENDPOINT_PARAMETERS: Mime = "application/x-www-form-urlencoded".parse().unwrap(); + } + /// Create Mime objects for the request content types for TestEnumParameters + lazy_static! { + pub static ref TEST_ENUM_PARAMETERS: Mime = "application/x-www-form-urlencoded".parse().unwrap(); + } /// Create Mime objects for the request content types for TestInlineAdditionalProperties lazy_static! { pub static ref TEST_INLINE_ADDITIONAL_PROPERTIES: Mime = "application/json".parse().unwrap(); @@ -125,6 +133,10 @@ pub mod requests { lazy_static! { pub static ref UPDATE_PET_WITH_FORM: Mime = "application/x-www-form-urlencoded".parse().unwrap(); } + /// Create Mime objects for the request content types for UploadFile + lazy_static! { + pub static ref UPLOAD_FILE: Mime = "multipart/form-data".parse().unwrap(); + } /// Create Mime objects for the request content types for PlaceOrder lazy_static! { pub static ref PLACE_ORDER: Mime = "application/json".parse().unwrap(); diff --git a/samples/server/petstore/rust-server/src/models.rs b/samples/server/petstore/rust-server/src/models.rs index de88074b622..8e3d864a0a4 100644 --- a/samples/server/petstore/rust-server/src/models.rs +++ b/samples/server/petstore/rust-server/src/models.rs @@ -185,6 +185,11 @@ pub struct ArrayTest { #[serde(skip_serializing_if="Option::is_none")] pub array_array_of_model: Option>>, + // Note: inline enums are not fully supported by openapi-generator + #[serde(rename = "array_of_enum")] + #[serde(skip_serializing_if="Option::is_none")] + pub array_of_enum: Option>, + } impl ArrayTest { @@ -193,6 +198,7 @@ impl ArrayTest { array_of_string: None, array_array_of_integer: None, array_array_of_model: None, + array_of_enum: None, } } } @@ -356,6 +362,11 @@ pub struct EnumArrays { #[serde(skip_serializing_if="Option::is_none")] pub array_enum: Option>, + // Note: inline enums are not fully supported by openapi-generator + #[serde(rename = "array_array_enum")] + #[serde(skip_serializing_if="Option::is_none")] + pub array_array_enum: Option>>, + } impl EnumArrays { @@ -363,6 +374,7 @@ impl EnumArrays { EnumArrays { just_symbol: None, array_enum: None, + array_array_enum: None, } } } @@ -475,6 +487,10 @@ pub struct FormatTest { #[serde(rename = "byte")] pub byte: swagger::ByteArray, + #[serde(rename = "binary")] + #[serde(skip_serializing_if="Option::is_none")] + pub binary: Option, + #[serde(rename = "date")] pub date: chrono::DateTime, @@ -502,6 +518,7 @@ impl FormatTest { double: None, string: None, byte: byte, + binary: None, date: date, date_time: None, uuid: None, @@ -553,6 +570,11 @@ pub struct MapTest { #[serde(skip_serializing_if="Option::is_none")] pub map_map_of_string: Option>>, + // Note: inline enums are not fully supported by openapi-generator + #[serde(rename = "map_map_of_enum")] + #[serde(skip_serializing_if="Option::is_none")] + pub map_map_of_enum: Option>>, + // Note: inline enums are not fully supported by openapi-generator #[serde(rename = "map_of_enum_string")] #[serde(skip_serializing_if="Option::is_none")] @@ -564,6 +586,7 @@ impl MapTest { pub fn new() -> MapTest { MapTest { map_map_of_string: None, + map_map_of_enum: None, map_of_enum_string: None, } } diff --git a/samples/server/petstore/rust-server/src/server/mod.rs b/samples/server/petstore/rust-server/src/server/mod.rs index a0142c41520..b035544d69f 100644 --- a/samples/server/petstore/rust-server/src/server/mod.rs +++ b/samples/server/petstore/rust-server/src/server/mod.rs @@ -7,7 +7,6 @@ extern crate openssl; extern crate mime; extern crate uuid; extern crate chrono; -extern crate multipart; extern crate percent_encoding; extern crate url; @@ -20,8 +19,6 @@ use hyper::{Request, Response, Error, StatusCode}; use hyper::header::{Headers, ContentType}; use self::url::form_urlencoded; use mimetypes; -use self::multipart::server::Multipart; -use self::multipart::server::save::SaveResult; use serde_json; use serde_xml_rs; @@ -832,185 +829,26 @@ where - let boundary = match multipart_boundary(&headers) { - Some(boundary) => boundary.to_string(), - None => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body("Couldn't find valid multipart body"))), - }; - - Box::new(body.concat2() - .then(move |result| -> Box> { - match result { - Ok(body) => { - let mut entries = match Multipart::with_body(&body.to_vec()[..], boundary).save().temp() { - SaveResult::Full(entries) => { - entries - }, - _ => { - return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Unable to process all message parts")))) - }, - }; + Box::new({ + {{ // Form parameters - let param_integer = entries.fields.remove("integer"); - let param_integer = match param_integer { - Some(entry) => + let param_integer = Some(56); + let param_int32 = Some(56); + let param_int64 = Some(789); + let param_number = 8.14; + let param_float = Some(3.4); + let param_double = 1.2; + let param_string = Some("string_example".to_string()); + let param_pattern_without_delimiter = "pattern_without_delimiter_example".to_string(); + let param_byte = swagger::ByteArray(Vec::from("BYTE_ARRAY_DATA_HERE")); + let param_binary = Some(swagger::ByteArray(Vec::from("BINARY_DATA_HERE"))); + let param_date = None; + let param_date_time = None; + let param_password = Some("password_example".to_string()); + let param_callback = Some("callback_example".to_string()); - match entry.parse::() { - Ok(entry) => Some(entry), - - Err(_) => None, - }, - - None => None, - }; - - let param_int32 = entries.fields.remove("int32"); - let param_int32 = match param_int32 { - Some(entry) => - - match entry.parse::() { - Ok(entry) => Some(entry), - - Err(_) => None, - }, - - None => None, - }; - - let param_int64 = entries.fields.remove("int64"); - let param_int64 = match param_int64 { - Some(entry) => - - match entry.parse::() { - Ok(entry) => Some(entry), - - Err(_) => None, - }, - - None => None, - }; - - let param_number = entries.fields.remove("number"); - let param_number = match param_number { - Some(entry) => - - match entry.parse::() { - Ok(entry) => entry, - Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse form parameter number - doesn't match schema: {}", e)))), - }, - None => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Missing required form parameter number")))), - }; - - let param_float = entries.fields.remove("float"); - let param_float = match param_float { - Some(entry) => - - match entry.parse::() { - Ok(entry) => Some(entry), - - Err(_) => None, - }, - - None => None, - }; - - let param_double = entries.fields.remove("double"); - let param_double = match param_double { - Some(entry) => - - match entry.parse::() { - Ok(entry) => entry, - Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse form parameter double - doesn't match schema: {}", e)))), - }, - None => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Missing required form parameter double")))), - }; - - let param_string = entries.fields.remove("string"); - let param_string = match param_string { - Some(entry) => - - match entry.parse::() { - Ok(entry) => Some(entry), - - Err(_) => None, - }, - - None => None, - }; - - let param_pattern_without_delimiter = entries.fields.remove("pattern_without_delimiter"); - let param_pattern_without_delimiter = match param_pattern_without_delimiter { - Some(entry) => - - match entry.parse::() { - Ok(entry) => entry, - Err(e) => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't parse form parameter pattern_without_delimiter - doesn't match schema: {}", e)))), - }, - None => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Missing required form parameter pattern_without_delimiter")))), - }; - - let param_binary = entries.fields.remove("binary"); - let param_binary = match param_binary { - Some(entry) => - Some(Box::new(stream::once(Ok(entry.as_bytes().to_vec()))) as Box, Error=io::Error> + Send>), - - None => None, - }; - let param_binary = Box::new(future::ok(param_binary)); - let param_date = entries.fields.remove("date"); - let param_date = match param_date { - Some(entry) => - - match entry.parse::>() { - Ok(entry) => Some(entry), - - Err(_) => None, - }, - - None => None, - }; - - let param_date_time = entries.fields.remove("date_time"); - let param_date_time = match param_date_time { - Some(entry) => - - match entry.parse::>() { - Ok(entry) => Some(entry), - - Err(_) => None, - }, - - None => None, - }; - - let param_password = entries.fields.remove("password"); - let param_password = match param_password { - Some(entry) => - - match entry.parse::() { - Ok(entry) => Some(entry), - - Err(_) => None, - }, - - None => None, - }; - - let param_callback = entries.fields.remove("callback"); - let param_callback = match param_callback { - Some(entry) => - - match entry.parse::() { - Ok(entry) => Some(entry), - - Err(_) => None, - }, - - None => None, - }; - - - Box::new(api_impl.test_endpoint_parameters(param_number, param_double, param_pattern_without_delimiter, param_integer, param_int32, param_int64, param_float, param_string, param_binary, param_date, param_date_time, param_password, param_callback, &context) + Box::new(api_impl.test_endpoint_parameters(param_number, param_double, param_pattern_without_delimiter, param_byte, param_integer, param_int32, param_int64, param_float, param_string, param_binary, param_date, param_date_time, param_password, param_callback, &context) .then(move |result| { let mut response = Response::new(); response.headers_mut().set(XSpanId((&context as &Has).get().0.to_string())); @@ -1044,12 +882,8 @@ where } )) - as Box> - }, - Err(e) => Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't read multipart body")))), - } - }) - ) + }} + }) as Box> }, @@ -1099,7 +933,10 @@ where Box::new({ {{ - Box::new(api_impl.test_enum_parameters(param_enum_header_string_array.as_ref(), param_enum_header_string, param_enum_query_string_array.as_ref(), param_enum_query_string, param_enum_query_integer, param_enum_query_double, &context) + // Form parameters + let param_enum_form_string = Some("enum_form_string_example".to_string()); + + Box::new(api_impl.test_enum_parameters(param_enum_header_string_array.as_ref(), param_enum_header_string, param_enum_query_string_array.as_ref(), param_enum_query_string, param_enum_query_integer, param_enum_query_double, param_enum_form_string, &context) .then(move |result| { let mut response = Response::new(); response.headers_mut().set(XSpanId((&context as &Has).get().0.to_string())); @@ -2108,46 +1945,12 @@ where - let boundary = match multipart_boundary(&headers) { - Some(boundary) => boundary.to_string(), - None => return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body("Couldn't find valid multipart body"))), - }; - - Box::new(body.concat2() - .then(move |result| -> Box> { - match result { - Ok(body) => { - let mut entries = match Multipart::with_body(&body.to_vec()[..], boundary).save().temp() { - SaveResult::Full(entries) => { - entries - }, - _ => { - return Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Unable to process all message parts")))) - }, - }; + Box::new({ + {{ // Form parameters - let param_additional_metadata = entries.fields.remove("additional_metadata"); - let param_additional_metadata = match param_additional_metadata { - Some(entry) => - - match entry.parse::() { - Ok(entry) => Some(entry), - - Err(_) => None, - }, - - None => None, - }; - - let param_file = entries.fields.remove("file"); - let param_file = match param_file { - Some(entry) => - Some(Box::new(stream::once(Ok(entry.as_bytes().to_vec()))) as Box, Error=io::Error> + Send>), - - None => None, - }; - let param_file = Box::new(future::ok(param_file)); + let param_additional_metadata = Some("additional_metadata_example".to_string()); + let param_file = Some(swagger::ByteArray(Vec::from("BINARY_DATA_HERE"))); Box::new(api_impl.upload_file(param_pet_id, param_additional_metadata, param_file, &context) .then(move |result| { @@ -2184,12 +1987,8 @@ where } )) - as Box> - }, - Err(e) => Box::new(future::ok(Response::new().with_status(StatusCode::BadRequest).with_body(format!("Couldn't read multipart body")))), - } - }) - ) + }} + }) as Box> }, @@ -3140,123 +2939,3 @@ where } } } - -/// Utility function to get the multipart boundary marker (if any) from the Headers. -fn multipart_boundary<'a>(headers: &'a Headers) -> Option<&'a str> { - headers.get::().and_then(|content_type| { - let ContentType(ref mime) = *content_type; - if mime.type_() == mime::MULTIPART && mime.subtype() == mime::FORM_DATA { - mime.get_param(mime::BOUNDARY).map(|x| x.as_str()) - } else { - None - } - }) -} - -/// Request parser for `Api`. -pub struct ApiRequestParser; - -impl RequestParser for ApiRequestParser { - fn parse_operation_id(request: &Request) -> Result<&'static str, ()> { - let path = paths::GLOBAL_REGEX_SET.matches(request.uri().path()); - match request.method() { - - // TestSpecialTags - PATCH /another-fake/dummy - &hyper::Method::Patch if path.matched(paths::ID_ANOTHER_FAKE_DUMMY) => Ok("TestSpecialTags"), - - // FakeOuterBooleanSerialize - POST /fake/outer/boolean - &hyper::Method::Post if path.matched(paths::ID_FAKE_OUTER_BOOLEAN) => Ok("FakeOuterBooleanSerialize"), - - // FakeOuterCompositeSerialize - POST /fake/outer/composite - &hyper::Method::Post if path.matched(paths::ID_FAKE_OUTER_COMPOSITE) => Ok("FakeOuterCompositeSerialize"), - - // FakeOuterNumberSerialize - POST /fake/outer/number - &hyper::Method::Post if path.matched(paths::ID_FAKE_OUTER_NUMBER) => Ok("FakeOuterNumberSerialize"), - - // FakeOuterStringSerialize - POST /fake/outer/string - &hyper::Method::Post if path.matched(paths::ID_FAKE_OUTER_STRING) => Ok("FakeOuterStringSerialize"), - - // TestBodyWithQueryParams - PUT /fake/body-with-query-params - &hyper::Method::Put if path.matched(paths::ID_FAKE_BODY_WITH_QUERY_PARAMS) => Ok("TestBodyWithQueryParams"), - - // TestClientModel - PATCH /fake - &hyper::Method::Patch if path.matched(paths::ID_FAKE) => Ok("TestClientModel"), - - // TestEndpointParameters - POST /fake - &hyper::Method::Post if path.matched(paths::ID_FAKE) => Ok("TestEndpointParameters"), - - // TestEnumParameters - GET /fake - &hyper::Method::Get if path.matched(paths::ID_FAKE) => Ok("TestEnumParameters"), - - // TestInlineAdditionalProperties - POST /fake/inline-additionalProperties - &hyper::Method::Post if path.matched(paths::ID_FAKE_INLINE_ADDITIONALPROPERTIES) => Ok("TestInlineAdditionalProperties"), - - // TestJsonFormData - GET /fake/jsonFormData - &hyper::Method::Get if path.matched(paths::ID_FAKE_JSONFORMDATA) => Ok("TestJsonFormData"), - - // TestClassname - PATCH /fake_classname_test - &hyper::Method::Patch if path.matched(paths::ID_FAKE_CLASSNAME_TEST) => Ok("TestClassname"), - - // AddPet - POST /pet - &hyper::Method::Post if path.matched(paths::ID_PET) => Ok("AddPet"), - - // DeletePet - DELETE /pet/{petId} - &hyper::Method::Delete if path.matched(paths::ID_PET_PETID) => Ok("DeletePet"), - - // FindPetsByStatus - GET /pet/findByStatus - &hyper::Method::Get if path.matched(paths::ID_PET_FINDBYSTATUS) => Ok("FindPetsByStatus"), - - // FindPetsByTags - GET /pet/findByTags - &hyper::Method::Get if path.matched(paths::ID_PET_FINDBYTAGS) => Ok("FindPetsByTags"), - - // GetPetById - GET /pet/{petId} - &hyper::Method::Get if path.matched(paths::ID_PET_PETID) => Ok("GetPetById"), - - // UpdatePet - PUT /pet - &hyper::Method::Put if path.matched(paths::ID_PET) => Ok("UpdatePet"), - - // UpdatePetWithForm - POST /pet/{petId} - &hyper::Method::Post if path.matched(paths::ID_PET_PETID) => Ok("UpdatePetWithForm"), - - // UploadFile - POST /pet/{petId}/uploadImage - &hyper::Method::Post if path.matched(paths::ID_PET_PETID_UPLOADIMAGE) => Ok("UploadFile"), - - // DeleteOrder - DELETE /store/order/{order_id} - &hyper::Method::Delete if path.matched(paths::ID_STORE_ORDER_ORDER_ID) => Ok("DeleteOrder"), - - // GetInventory - GET /store/inventory - &hyper::Method::Get if path.matched(paths::ID_STORE_INVENTORY) => Ok("GetInventory"), - - // GetOrderById - GET /store/order/{order_id} - &hyper::Method::Get if path.matched(paths::ID_STORE_ORDER_ORDER_ID) => Ok("GetOrderById"), - - // PlaceOrder - POST /store/order - &hyper::Method::Post if path.matched(paths::ID_STORE_ORDER) => Ok("PlaceOrder"), - - // CreateUser - POST /user - &hyper::Method::Post if path.matched(paths::ID_USER) => Ok("CreateUser"), - - // CreateUsersWithArrayInput - POST /user/createWithArray - &hyper::Method::Post if path.matched(paths::ID_USER_CREATEWITHARRAY) => Ok("CreateUsersWithArrayInput"), - - // CreateUsersWithListInput - POST /user/createWithList - &hyper::Method::Post if path.matched(paths::ID_USER_CREATEWITHLIST) => Ok("CreateUsersWithListInput"), - - // DeleteUser - DELETE /user/{username} - &hyper::Method::Delete if path.matched(paths::ID_USER_USERNAME) => Ok("DeleteUser"), - - // GetUserByName - GET /user/{username} - &hyper::Method::Get if path.matched(paths::ID_USER_USERNAME) => Ok("GetUserByName"), - - // LoginUser - GET /user/login - &hyper::Method::Get if path.matched(paths::ID_USER_LOGIN) => Ok("LoginUser"), - - // LogoutUser - GET /user/logout - &hyper::Method::Get if path.matched(paths::ID_USER_LOGOUT) => Ok("LogoutUser"), - - // UpdateUser - PUT /user/{username} - &hyper::Method::Put if path.matched(paths::ID_USER_USERNAME) => Ok("UpdateUser"), - _ => Err(()), - } - } -}