From cc59367909a9c4d7c02f43f113546ac2656ca6ad Mon Sep 17 00:00:00 2001 From: Jim Schubert Date: Fri, 29 May 2020 05:32:52 -0400 Subject: [PATCH 01/62] [csharp] Rename netstandard to netstandard1.3 (#6460) --- bin/csharp-petstore-all.sh | 2 +- bin/csharp-petstore-net-standard.json | 2 +- bin/windows/csharp-petstore-all.bat | 2 +- bin/windows/csharp-petstore-netcore-project.bat | 2 +- bin/windows/csharp-petstore-netstandard.bat | 2 +- .../codegen/languages/CSharpClientCodegen.java | 7 +------ 6 files changed, 6 insertions(+), 11 deletions(-) diff --git a/bin/csharp-petstore-all.sh b/bin/csharp-petstore-all.sh index d57231a9f6a..022d1713bbd 100755 --- a/bin/csharp-petstore-all.sh +++ b/bin/csharp-petstore-all.sh @@ -6,7 +6,7 @@ # C# Petstore API client with PropertyChanged ./bin/csharp-property-changed-petstore.sh -# C# Petstore API client (v5.0 for .net standarnd 1.3+) +# C# Petstore API client (.net standarnd 1.3+) ./bin/csharp-petstore-net-standard.sh # C# Petstore API client (.NET 4.0) diff --git a/bin/csharp-petstore-net-standard.json b/bin/csharp-petstore-net-standard.json index 874e5334bfa..d6e7bb02d93 100644 --- a/bin/csharp-petstore-net-standard.json +++ b/bin/csharp-petstore-net-standard.json @@ -1,3 +1,3 @@ { - "targetFramework": "v5.0" + "targetFramework": "netstandard1.3" } diff --git a/bin/windows/csharp-petstore-all.bat b/bin/windows/csharp-petstore-all.bat index 20808357fa5..46a7bc79165 100755 --- a/bin/windows/csharp-petstore-all.bat +++ b/bin/windows/csharp-petstore-all.bat @@ -4,7 +4,7 @@ call .\bin\windows\csharp-petstore.bat REM C# Petstore API client with PropertyChanged call .\bin\windows\csharp-property-changed-petstore.bat -REM C# Petstore API client (v5.0 for .net standarnd 1.3+) +REM C# Petstore API client (.net standarnd 1.3+) call .\bin\windows\csharp-petstore-netstandard.bat call .\bin\windows\csharp-dotnet2-petstore.bat diff --git a/bin/windows/csharp-petstore-netcore-project.bat b/bin/windows/csharp-petstore-netcore-project.bat index 5538f292b97..b192df87350 100644 --- a/bin/windows/csharp-petstore-netcore-project.bat +++ b/bin/windows/csharp-petstore-netcore-project.bat @@ -5,6 +5,6 @@ If Not Exist %executable% ( ) REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -set ags=generate -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g csharp -o samples\client\petstore\csharp\OpenApiClientNetCoreProject --additional-properties targetFramework=v5.0,packageGuid={67035b31-f8e5-41a4-9673-954035084f7d},netCoreProjectFile=true +set ags=generate -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g csharp -o samples\client\petstore\csharp\OpenApiClientNetCoreProject --additional-properties targetFramework=netstandard1.3,packageGuid={67035b31-f8e5-41a4-9673-954035084f7d},netCoreProjectFile=true java %JAVA_OPTS% -jar %executable% %ags% diff --git a/bin/windows/csharp-petstore-netstandard.bat b/bin/windows/csharp-petstore-netstandard.bat index b2abd6bfa02..3b058f902bc 100644 --- a/bin/windows/csharp-petstore-netstandard.bat +++ b/bin/windows/csharp-petstore-netstandard.bat @@ -5,6 +5,6 @@ If Not Exist %executable% ( ) REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -set ags=generate -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g csharp -o samples\client\petstore\csharp\OpenApiClientNetStandard --additional-properties targetFramework=v5.0,packageGuid={3AB1F259-1769-484B-9411-84505FCCBD55} +set ags=generate -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g csharp -o samples\client\petstore\csharp\OpenApiClientNetStandard --additional-properties targetFramework=netstandard1.3,packageGuid={3AB1F259-1769-484B-9411-84505FCCBD55} java %JAVA_OPTS% -jar %executable% %ags% diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpClientCodegen.java index 495ccf72f6b..1d47c0b4e9b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CSharpClientCodegen.java @@ -47,10 +47,7 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { private static final String NET45 = "v4.5"; private static final String NET40 = "v4.0"; private static final String NET35 = "v3.5"; - // TODO: v5.0 is PCL, not netstandard version 1.3, and not a specific .NET Framework. This needs to be updated, - // especially because it will conflict with .NET Framework 5.0 when released, and PCL 5 refers to Framework 4.0. - // We should support either NETSTANDARD, PCL, or Both… but the concepts shouldn't be mixed. - private static final String NETSTANDARD = "v5.0"; + private static final String NETSTANDARD = "netstandard1.3"; private static final String UWP = "uwp"; // Defines the sdk option for targeted frameworks, which differs from targetFramework and targetFrameworkNuget @@ -312,14 +309,12 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { setSupportsAsync(Boolean.FALSE); } else if (NETSTANDARD.equals(this.targetFramework)) { LOGGER.warn(".NET Standard 1.3 support has been DEPRECATED in this generator. Please use `csharp-netcore` generator instead."); - // TODO: NETSTANDARD here is misrepresenting a PCL v5.0 which supports .NET Framework 4.6+, .NET Core 1.0, and Windows Universal 10.0 additionalProperties.put(MCS_NET_VERSION_KEY, "4.6-api"); if (additionalProperties.containsKey("supportsUWP")) { LOGGER.warn(".NET " + NETSTANDARD + " generator does not support UWP."); additionalProperties.remove("supportsUWP"); } - // TODO: NETSTANDARD=v5.0 and targetFrameworkNuget=netstandard1.3. These need to sync. setTargetFrameworkNuget("netstandard1.3"); setSupportsAsync(Boolean.TRUE); setSupportsUWP(Boolean.FALSE); From 30caeedb98c5cbbad6869550fd0381371dad6b23 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 29 May 2020 18:16:55 +0800 Subject: [PATCH 02/62] update doc --- docs/generators/csharp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/generators/csharp.md b/docs/generators/csharp.md index 6928ef5f9e1..ebb98caaa81 100644 --- a/docs/generators/csharp.md +++ b/docs/generators/csharp.md @@ -23,7 +23,7 @@ sidebar_label: csharp |returnICollection|Return ICollection<T> instead of the concrete type.| |false| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |src| -|targetFramework|The target .NET framework version.|
**v3.5**
.NET Framework 3.5 compatible
**v4.0**
.NET Framework 4.0 compatible
**v4.5**
.NET Framework 4.5 compatible
**v4.5.2**
.NET Framework 4.5.2+ compatible
**v5.0**
.NET Standard 1.3 compatible (DEPRECATED. Please use `csharp-netcore` generator instead)
**uwp**
Universal Windows Platform (DEPRECATED. Please use `csharp-netcore` generator instead)
|v4.5| +|targetFramework|The target .NET framework version.|
**v3.5**
.NET Framework 3.5 compatible
**v4.0**
.NET Framework 4.0 compatible
**v4.5**
.NET Framework 4.5 compatible
**v4.5.2**
.NET Framework 4.5.2+ compatible
**netstandard1.3**
.NET Standard 1.3 compatible (DEPRECATED. Please use `csharp-netcore` generator instead)
**uwp**
Universal Windows Platform (DEPRECATED. Please use `csharp-netcore` generator instead)
|v4.5| |useCollection|Deserialize array types to Collection<T> instead of List<T>.| |false| |useCompareNetObjects|Use KellermanSoftware.CompareNetObjects for deep recursive object comparison. WARNING: this option incurs potential performance impact.| |false| |useDateTimeOffset|Use DateTimeOffset to model date-time properties| |false| From 83bad102ea5d22683a5d75297ce006e4f8aaaefd Mon Sep 17 00:00:00 2001 From: Yuriy Belenko Date: Fri, 29 May 2020 13:35:11 +0300 Subject: [PATCH 03/62] [php-symfony] Set required PHP version ^7.1.3 (#6181) * Set PHP 7.1.3 required version I've tried to specify ^7.0 version at first, but main package which is symfony/framework-bundle@v4.4.8 requires PHP ^7.1.3. * Bump Symfony FrameworkBundle to ^4.4.8 Current Symfony Framework stable version is v5.0.8, but I guess it requires significant codebase upgrade, so I've sticked with 4.4.8 which shouldn't cause any breaking changes. Old requirement was ^3.3|^4.1 which compatible with 4.4.8. * Bump PHPUnit version to ^7.0 PHPUnit 8.x version required PHP ^7.2, so I'm setting 7.x version to support PHP 7.1. There is new way to specify Kernel class, related PR: https://github.com/symfony/symfony/pull/22668 * Bump PHP CS Fixer version to ^2.16.3 Configuration and all renamed rules fixed. Config file renamed to .php_cs.dist as recommended in migration guide. Migration guide from 1.x to 2.x: https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/master/UPGRADE.md#config-file * Remove PHP_CodeSniffer package Second linter doesn't make sense. I think Symfony user would prefer PHP CS Fixer over PHP_CodeSniffer because first one maintained by Symfony members. * Remove satooshi/php-coveralls package from Composer This package is abandoned and Coveralls recommends to install it directly in Travis-CI task script. * Update Travic-CI config I've changed test versions to PHP 7.1.3 and 7.2. PHPUnit generates coverage report in report/logs/clover.xml file. Then PHP CS Fixer runs with --dry-run option to not override anything just to show coding style errors. * Add basic Coveralls config This is basic recommended config for a PHP based project. * Add symfony/yaml package This package was part of satooshi/php-coveralls, now it should be defined as dev dependency. * Do not commit composer.lock I think committed composer.lock can cause CI errors while tests on fresh installs are better. * Remove confusing Ruby comment --- .../languages/PhpSymfonyServerCodegen.java | 6 +++-- .../main/resources/php-symfony/.coveralls.yml | 5 ++++ .../src/main/resources/php-symfony/.gitignore | 16 +++++++++++- .../src/main/resources/php-symfony/.php_cs | 18 ------------- .../main/resources/php-symfony/.php_cs.dist | 20 ++++++++++++++ .../main/resources/php-symfony/.travis.yml | 26 +++++++++++++------ .../resources/php-symfony/ApiPass.mustache | 2 +- .../resources/php-symfony/ApiServer.mustache | 2 +- .../resources/php-symfony/Bundle.mustache | 2 +- .../resources/php-symfony/Controller.mustache | 2 +- .../resources/php-symfony/Extension.mustache | 2 +- .../resources/php-symfony/README.mustache | 2 +- .../main/resources/php-symfony/api.mustache | 2 +- .../php-symfony/api_controller.mustache | 2 +- .../resources/php-symfony/composer.mustache | 11 ++++---- .../main/resources/php-symfony/model.mustache | 2 +- .../{AppKernel.php => AppKernel.mustache} | 5 +++- .../testing/ControllerTest.mustache | 2 +- .../php-symfony/testing/api_test.mustache | 2 +- .../php-symfony/testing/model_test.mustache | 6 +++-- .../php-symfony/testing/phpunit.xml.mustache | 2 +- .../SymfonyBundle-php/.coveralls.yml | 5 ++++ .../php-symfony/SymfonyBundle-php/.gitignore | 16 +++++++++++- .../php-symfony/SymfonyBundle-php/.php_cs | 18 ------------- .../SymfonyBundle-php/.php_cs.dist | 20 ++++++++++++++ .../php-symfony/SymfonyBundle-php/.travis.yml | 26 +++++++++++++------ .../SymfonyBundle-php/Api/ApiServer.php | 2 +- .../SymfonyBundle-php/Api/PetApiInterface.php | 2 +- .../Api/StoreApiInterface.php | 2 +- .../Api/UserApiInterface.php | 2 +- .../Controller/Controller.php | 2 +- .../Controller/PetController.php | 2 +- .../Controller/StoreController.php | 2 +- .../Controller/UserController.php | 2 +- .../Compiler/OpenAPIServerApiPass.php | 2 +- .../OpenAPIServerExtension.php | 2 +- .../SymfonyBundle-php/Model/ApiResponse.php | 2 +- .../SymfonyBundle-php/Model/Category.php | 2 +- .../SymfonyBundle-php/Model/Order.php | 2 +- .../SymfonyBundle-php/Model/Pet.php | 2 +- .../SymfonyBundle-php/Model/Tag.php | 2 +- .../SymfonyBundle-php/Model/User.php | 2 +- .../SymfonyBundle-php/OpenAPIServerBundle.php | 2 +- .../php-symfony/SymfonyBundle-php/README.md | 2 +- .../Tests/Api/PetApiInterfaceTest.php | 2 +- .../Tests/Api/StoreApiInterfaceTest.php | 2 +- .../Tests/Api/UserApiInterfaceTest.php | 2 +- .../SymfonyBundle-php/Tests/AppKernel.php | 5 +++- .../Tests/Controller/ControllerTest.php | 2 +- .../Tests/Model/ApiResponseTest.php | 6 +++-- .../Tests/Model/CategoryTest.php | 6 +++-- .../Tests/Model/OrderTest.php | 6 +++-- .../SymfonyBundle-php/Tests/Model/PetTest.php | 6 +++-- .../SymfonyBundle-php/Tests/Model/TagTest.php | 6 +++-- .../Tests/Model/UserTest.php | 6 +++-- .../SymfonyBundle-php/composer.json | 11 ++++---- .../SymfonyBundle-php/phpunit.xml.dist | 2 +- 57 files changed, 201 insertions(+), 119 deletions(-) create mode 100644 modules/openapi-generator/src/main/resources/php-symfony/.coveralls.yml delete mode 100644 modules/openapi-generator/src/main/resources/php-symfony/.php_cs create mode 100644 modules/openapi-generator/src/main/resources/php-symfony/.php_cs.dist rename modules/openapi-generator/src/main/resources/php-symfony/testing/{AppKernel.php => AppKernel.mustache} (77%) create mode 100644 samples/server/petstore/php-symfony/SymfonyBundle-php/.coveralls.yml delete mode 100644 samples/server/petstore/php-symfony/SymfonyBundle-php/.php_cs create mode 100644 samples/server/petstore/php-symfony/SymfonyBundle-php/.php_cs.dist diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSymfonyServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSymfonyServerCodegen.java index 31e66bc67bf..14de1216d4c 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSymfonyServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/PhpSymfonyServerCodegen.java @@ -300,6 +300,7 @@ public class PhpSymfonyServerCodegen extends AbstractPhpCodegen implements Codeg additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\")); additionalProperties.put("controllerPackage", controllerPackage); additionalProperties.put("servicePackage", servicePackage); + additionalProperties.put("testsPackage", testsPackage); additionalProperties.put("apiTestsPackage", apiTestsPackage); additionalProperties.put("modelTestsPackage", modelTestsPackage); additionalProperties.put("controllerTestsPackage", controllerTestsPackage); @@ -349,7 +350,7 @@ public class PhpSymfonyServerCodegen extends AbstractPhpCodegen implements Codeg // Testing components supportingFiles.add(new SupportingFile("testing/phpunit.xml.mustache", "", "phpunit.xml.dist")); supportingFiles.add(new SupportingFile("testing/pom.xml", "", "pom.xml")); - supportingFiles.add(new SupportingFile("testing/AppKernel.php", toSrcPath(testsPackage, srcBasePath), "AppKernel.php")); + supportingFiles.add(new SupportingFile("testing/AppKernel.mustache", toSrcPath(testsPackage, srcBasePath), "AppKernel.php")); supportingFiles.add(new SupportingFile("testing/ControllerTest.mustache", toSrcPath(controllerTestsPackage, srcBasePath), "ControllerTest.php")); supportingFiles.add(new SupportingFile("testing/test_config.yml", toSrcPath(testsPackage, srcBasePath), "test_config.yml")); @@ -360,7 +361,8 @@ public class PhpSymfonyServerCodegen extends AbstractPhpCodegen implements Codeg supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); supportingFiles.add(new SupportingFile(".travis.yml", "", ".travis.yml")); - supportingFiles.add(new SupportingFile(".php_cs", "", ".php_cs")); + supportingFiles.add(new SupportingFile(".php_cs.dist", "", ".php_cs.dist")); + supportingFiles.add(new SupportingFile(".coveralls.yml", "", ".coveralls.yml")); supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh")); // Type-hintable primitive types diff --git a/modules/openapi-generator/src/main/resources/php-symfony/.coveralls.yml b/modules/openapi-generator/src/main/resources/php-symfony/.coveralls.yml new file mode 100644 index 00000000000..4071b53a952 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/php-symfony/.coveralls.yml @@ -0,0 +1,5 @@ +service_name: travis-ci # travis-ci or travis-pro + +# for php-coveralls +coverage_clover: report/logs/clover.xml +json_path: report/logs/coveralls-upload.json \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/php-symfony/.gitignore b/modules/openapi-generator/src/main/resources/php-symfony/.gitignore index 20b7b989760..0bac519d3e8 100644 --- a/modules/openapi-generator/src/main/resources/php-symfony/.gitignore +++ b/modules/openapi-generator/src/main/resources/php-symfony/.gitignore @@ -29,6 +29,10 @@ !bin/symfony_requirements /vendor/ +# Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control +# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file +composer.lock + # Assets and user uploads /web/bundles/ /web/uploads/ @@ -51,4 +55,14 @@ # From root gitignore /Tests/cache/ -/Tests/logs/ \ No newline at end of file +/Tests/logs/ + +# PHP Coding Standards Fixer +# https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/master/UPGRADE.md#config-file +# From now you can create new configuration file: .php_cs.dist. +# This file is used if no .php_cs file was found. +# It is recommended to create .php_cs.dist file attached in your repository and add .php_cs file to .gitignore for allowing your contributors to have theirs own configuration file. +/.php_cs + +# No reason to commit PHP CS Fixer cache files +/.php_cs.cache diff --git a/modules/openapi-generator/src/main/resources/php-symfony/.php_cs b/modules/openapi-generator/src/main/resources/php-symfony/.php_cs deleted file mode 100644 index 6b8e23c818a..00000000000 --- a/modules/openapi-generator/src/main/resources/php-symfony/.php_cs +++ /dev/null @@ -1,18 +0,0 @@ -level(Symfony\CS\FixerInterface::PSR2_LEVEL) - ->setUsingCache(true) - ->fixers( - [ - 'ordered_use', - 'phpdoc_order', - 'short_array_syntax', - 'strict', - 'strict_param' - ] - ) - ->finder( - Symfony\CS\Finder\DefaultFinder::create() - ->in(__DIR__) - ); diff --git a/modules/openapi-generator/src/main/resources/php-symfony/.php_cs.dist b/modules/openapi-generator/src/main/resources/php-symfony/.php_cs.dist new file mode 100644 index 00000000000..df19888e44f --- /dev/null +++ b/modules/openapi-generator/src/main/resources/php-symfony/.php_cs.dist @@ -0,0 +1,20 @@ +in(__DIR__) +; + +return PhpCsFixer\Config::create() + ->setUsingCache(true) + ->setRules([ + '@PSR2' => true, + 'ordered_imports' => [ + 'sort_algorithm' => 'alpha' + ], + 'phpdoc_order' => true, + 'array_syntax' => ['syntax' => 'short'], + 'strict_comparison' => true, + 'strict_param' => true + ]) + ->setFinder($finder) +; diff --git a/modules/openapi-generator/src/main/resources/php-symfony/.travis.yml b/modules/openapi-generator/src/main/resources/php-symfony/.travis.yml index d77f3825f6f..de5a983645f 100644 --- a/modules/openapi-generator/src/main/resources/php-symfony/.travis.yml +++ b/modules/openapi-generator/src/main/resources/php-symfony/.travis.yml @@ -1,10 +1,20 @@ language: php -sudo: false +dist: trusty php: - - 5.4 - - 5.5 - - 5.6 - - 7.0 - - hhvm -before_install: "composer install" -script: "vendor/bin/phpunit" + - 7.1.3 + - 7.2 + +install: + - composer install --dev --no-interaction +script: + - mkdir -p report/logs + - php vendor/bin/phpunit -c phpunit.xml.dist --coverage-clover=report/logs/clover.xml + - php vendor/bin/php-cs-fixer fix --config=.php_cs.dist -v --dry-run --stop-on-violation --using-cache=no + +before_script: + - composer require --dev php-coveralls/php-coveralls --no-interaction + +after_success: + - travis_retry php vendor/bin/php-coveralls + # or enable logging + - travis_retry php vendor/bin/php-coveralls -v diff --git a/modules/openapi-generator/src/main/resources/php-symfony/ApiPass.mustache b/modules/openapi-generator/src/main/resources/php-symfony/ApiPass.mustache index 1d71f37d97b..10bf6bea00c 100644 --- a/modules/openapi-generator/src/main/resources/php-symfony/ApiPass.mustache +++ b/modules/openapi-generator/src/main/resources/php-symfony/ApiPass.mustache @@ -2,7 +2,7 @@ /** * {{bundleName}}ApiPass * - * PHP version 5 + * PHP version 7.1.3 * * @category Class * @package {{invokerPackage}}\DependencyInjection\Compiler diff --git a/modules/openapi-generator/src/main/resources/php-symfony/ApiServer.mustache b/modules/openapi-generator/src/main/resources/php-symfony/ApiServer.mustache index bc317a145e4..1e902459ef0 100644 --- a/modules/openapi-generator/src/main/resources/php-symfony/ApiServer.mustache +++ b/modules/openapi-generator/src/main/resources/php-symfony/ApiServer.mustache @@ -2,7 +2,7 @@ /** * ApiServer * - * PHP version 5 + * PHP version 7.1.3 * * @category Class * @package {{apiPackage}} diff --git a/modules/openapi-generator/src/main/resources/php-symfony/Bundle.mustache b/modules/openapi-generator/src/main/resources/php-symfony/Bundle.mustache index 1f55e24b3b7..4bbbf5062d8 100644 --- a/modules/openapi-generator/src/main/resources/php-symfony/Bundle.mustache +++ b/modules/openapi-generator/src/main/resources/php-symfony/Bundle.mustache @@ -2,7 +2,7 @@ /** * {{bundleClassName}} * - * PHP version 5 + * PHP version 7.1.3 * * @category Class * @package {{invokerPackage}} diff --git a/modules/openapi-generator/src/main/resources/php-symfony/Controller.mustache b/modules/openapi-generator/src/main/resources/php-symfony/Controller.mustache index d7b5d5feec4..bafc3668ff3 100644 --- a/modules/openapi-generator/src/main/resources/php-symfony/Controller.mustache +++ b/modules/openapi-generator/src/main/resources/php-symfony/Controller.mustache @@ -2,7 +2,7 @@ /** * Controller * - * PHP version 5 + * PHP version 7.1.3 * * @category Class * @package {{controllerPackage}} diff --git a/modules/openapi-generator/src/main/resources/php-symfony/Extension.mustache b/modules/openapi-generator/src/main/resources/php-symfony/Extension.mustache index 9e9f541835c..4395c42aef0 100644 --- a/modules/openapi-generator/src/main/resources/php-symfony/Extension.mustache +++ b/modules/openapi-generator/src/main/resources/php-symfony/Extension.mustache @@ -2,7 +2,7 @@ /** * {{bundleExtensionName}} * - * PHP version 5 + * PHP version 7.1.3 * * @category Class * @package {{invokerPackage}}\DependencyInjection diff --git a/modules/openapi-generator/src/main/resources/php-symfony/README.mustache b/modules/openapi-generator/src/main/resources/php-symfony/README.mustache index 69fe2bebd3c..e3451ecf393 100644 --- a/modules/openapi-generator/src/main/resources/php-symfony/README.mustache +++ b/modules/openapi-generator/src/main/resources/php-symfony/README.mustache @@ -19,7 +19,7 @@ For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) ## Requirements -PHP 5.4.0 and later +PHP 7.1.3 and later ## Installation & Usage diff --git a/modules/openapi-generator/src/main/resources/php-symfony/api.mustache b/modules/openapi-generator/src/main/resources/php-symfony/api.mustache index a9ccc73e02d..81f343bb38e 100644 --- a/modules/openapi-generator/src/main/resources/php-symfony/api.mustache +++ b/modules/openapi-generator/src/main/resources/php-symfony/api.mustache @@ -1,7 +1,7 @@ =5.4", + "php": "^7.1.3", "ext-curl": "*", "ext-json": "*", "ext-mbstring": "*", "symfony/validator": "*", "jms/serializer-bundle": "^2.0", - "symfony/framework-bundle": "^3.3|^4.1" + "symfony/framework-bundle": "^4.4.8" }, "require-dev": { - "phpunit/phpunit": "~4.8", - "satooshi/php-coveralls": "~1.0", - "squizlabs/php_codesniffer": "~2.6", - "friendsofphp/php-cs-fixer": "~1.12", + "phpunit/phpunit": "^7.0", + "friendsofphp/php-cs-fixer": "^2.16.3", "symfony/browser-kit": "*", + "symfony/yaml": "^4.4.8", "hoa/regex": "~1.0" }, "autoload": { diff --git a/modules/openapi-generator/src/main/resources/php-symfony/model.mustache b/modules/openapi-generator/src/main/resources/php-symfony/model.mustache index 44c3e9d6bf1..12959e5101c 100644 --- a/modules/openapi-generator/src/main/resources/php-symfony/model.mustache +++ b/modules/openapi-generator/src/main/resources/php-symfony/model.mustache @@ -4,7 +4,7 @@ /** * {{classname}} * - * PHP version 5 + * PHP version 7.1.3 * * @category Class * @package {{modelPackage}} diff --git a/modules/openapi-generator/src/main/resources/php-symfony/testing/AppKernel.php b/modules/openapi-generator/src/main/resources/php-symfony/testing/AppKernel.mustache similarity index 77% rename from modules/openapi-generator/src/main/resources/php-symfony/testing/AppKernel.php rename to modules/openapi-generator/src/main/resources/php-symfony/testing/AppKernel.mustache index 631690bc978..617189baa7a 100644 --- a/modules/openapi-generator/src/main/resources/php-symfony/testing/AppKernel.php +++ b/modules/openapi-generator/src/main/resources/php-symfony/testing/AppKernel.mustache @@ -1,5 +1,8 @@ - + diff --git a/samples/server/petstore/php-symfony/SymfonyBundle-php/.coveralls.yml b/samples/server/petstore/php-symfony/SymfonyBundle-php/.coveralls.yml new file mode 100644 index 00000000000..4071b53a952 --- /dev/null +++ b/samples/server/petstore/php-symfony/SymfonyBundle-php/.coveralls.yml @@ -0,0 +1,5 @@ +service_name: travis-ci # travis-ci or travis-pro + +# for php-coveralls +coverage_clover: report/logs/clover.xml +json_path: report/logs/coveralls-upload.json \ No newline at end of file diff --git a/samples/server/petstore/php-symfony/SymfonyBundle-php/.gitignore b/samples/server/petstore/php-symfony/SymfonyBundle-php/.gitignore index 20b7b989760..0bac519d3e8 100644 --- a/samples/server/petstore/php-symfony/SymfonyBundle-php/.gitignore +++ b/samples/server/petstore/php-symfony/SymfonyBundle-php/.gitignore @@ -29,6 +29,10 @@ !bin/symfony_requirements /vendor/ +# Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control +# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file +composer.lock + # Assets and user uploads /web/bundles/ /web/uploads/ @@ -51,4 +55,14 @@ # From root gitignore /Tests/cache/ -/Tests/logs/ \ No newline at end of file +/Tests/logs/ + +# PHP Coding Standards Fixer +# https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/master/UPGRADE.md#config-file +# From now you can create new configuration file: .php_cs.dist. +# This file is used if no .php_cs file was found. +# It is recommended to create .php_cs.dist file attached in your repository and add .php_cs file to .gitignore for allowing your contributors to have theirs own configuration file. +/.php_cs + +# No reason to commit PHP CS Fixer cache files +/.php_cs.cache diff --git a/samples/server/petstore/php-symfony/SymfonyBundle-php/.php_cs b/samples/server/petstore/php-symfony/SymfonyBundle-php/.php_cs deleted file mode 100644 index 6b8e23c818a..00000000000 --- a/samples/server/petstore/php-symfony/SymfonyBundle-php/.php_cs +++ /dev/null @@ -1,18 +0,0 @@ -level(Symfony\CS\FixerInterface::PSR2_LEVEL) - ->setUsingCache(true) - ->fixers( - [ - 'ordered_use', - 'phpdoc_order', - 'short_array_syntax', - 'strict', - 'strict_param' - ] - ) - ->finder( - Symfony\CS\Finder\DefaultFinder::create() - ->in(__DIR__) - ); diff --git a/samples/server/petstore/php-symfony/SymfonyBundle-php/.php_cs.dist b/samples/server/petstore/php-symfony/SymfonyBundle-php/.php_cs.dist new file mode 100644 index 00000000000..df19888e44f --- /dev/null +++ b/samples/server/petstore/php-symfony/SymfonyBundle-php/.php_cs.dist @@ -0,0 +1,20 @@ +in(__DIR__) +; + +return PhpCsFixer\Config::create() + ->setUsingCache(true) + ->setRules([ + '@PSR2' => true, + 'ordered_imports' => [ + 'sort_algorithm' => 'alpha' + ], + 'phpdoc_order' => true, + 'array_syntax' => ['syntax' => 'short'], + 'strict_comparison' => true, + 'strict_param' => true + ]) + ->setFinder($finder) +; diff --git a/samples/server/petstore/php-symfony/SymfonyBundle-php/.travis.yml b/samples/server/petstore/php-symfony/SymfonyBundle-php/.travis.yml index d77f3825f6f..de5a983645f 100644 --- a/samples/server/petstore/php-symfony/SymfonyBundle-php/.travis.yml +++ b/samples/server/petstore/php-symfony/SymfonyBundle-php/.travis.yml @@ -1,10 +1,20 @@ language: php -sudo: false +dist: trusty php: - - 5.4 - - 5.5 - - 5.6 - - 7.0 - - hhvm -before_install: "composer install" -script: "vendor/bin/phpunit" + - 7.1.3 + - 7.2 + +install: + - composer install --dev --no-interaction +script: + - mkdir -p report/logs + - php vendor/bin/phpunit -c phpunit.xml.dist --coverage-clover=report/logs/clover.xml + - php vendor/bin/php-cs-fixer fix --config=.php_cs.dist -v --dry-run --stop-on-violation --using-cache=no + +before_script: + - composer require --dev php-coveralls/php-coveralls --no-interaction + +after_success: + - travis_retry php vendor/bin/php-coveralls + # or enable logging + - travis_retry php vendor/bin/php-coveralls -v diff --git a/samples/server/petstore/php-symfony/SymfonyBundle-php/Api/ApiServer.php b/samples/server/petstore/php-symfony/SymfonyBundle-php/Api/ApiServer.php index f57c47b342c..de44229b454 100644 --- a/samples/server/petstore/php-symfony/SymfonyBundle-php/Api/ApiServer.php +++ b/samples/server/petstore/php-symfony/SymfonyBundle-php/Api/ApiServer.php @@ -2,7 +2,7 @@ /** * ApiServer * - * PHP version 5 + * PHP version 7.1.3 * * @category Class * @package OpenAPI\Server\Api diff --git a/samples/server/petstore/php-symfony/SymfonyBundle-php/Api/PetApiInterface.php b/samples/server/petstore/php-symfony/SymfonyBundle-php/Api/PetApiInterface.php index 864fa5cd80f..0cf1ef82a85 100644 --- a/samples/server/petstore/php-symfony/SymfonyBundle-php/Api/PetApiInterface.php +++ b/samples/server/petstore/php-symfony/SymfonyBundle-php/Api/PetApiInterface.php @@ -1,7 +1,7 @@ =5.4", + "php": "^7.1.3", "ext-curl": "*", "ext-json": "*", "ext-mbstring": "*", "symfony/validator": "*", "jms/serializer-bundle": "^2.0", - "symfony/framework-bundle": "^3.3|^4.1" + "symfony/framework-bundle": "^4.4.8" }, "require-dev": { - "phpunit/phpunit": "~4.8", - "satooshi/php-coveralls": "~1.0", - "squizlabs/php_codesniffer": "~2.6", - "friendsofphp/php-cs-fixer": "~1.12", + "phpunit/phpunit": "^7.0", + "friendsofphp/php-cs-fixer": "^2.16.3", "symfony/browser-kit": "*", + "symfony/yaml": "^4.4.8", "hoa/regex": "~1.0" }, "autoload": { diff --git a/samples/server/petstore/php-symfony/SymfonyBundle-php/phpunit.xml.dist b/samples/server/petstore/php-symfony/SymfonyBundle-php/phpunit.xml.dist index 38a8370fec6..e754829e628 100644 --- a/samples/server/petstore/php-symfony/SymfonyBundle-php/phpunit.xml.dist +++ b/samples/server/petstore/php-symfony/SymfonyBundle-php/phpunit.xml.dist @@ -21,6 +21,6 @@ - + From c3ac84cec2198679dc58ecf02c9b1248c360dbe4 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 29 May 2020 21:18:15 +0800 Subject: [PATCH 04/62] [Rust] set supportAsync to true as the default (#6480) * set supportAsync to true * set reqwest as the default lib --- bin/rust-petstore.sh | 2 +- docs/generators/rust.md | 4 ++-- .../codegen/languages/RustClientCodegen.java | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/bin/rust-petstore.sh b/bin/rust-petstore.sh index d5aceb82af6..bee0348ca06 100755 --- a/bin/rust-petstore.sh +++ b/bin/rust-petstore.sh @@ -40,7 +40,7 @@ for spec_path in \ --input-spec $spec_path --generator-name rust --output samples/client/petstore/rust/$library/$spec - --additional-properties packageName=${spec}-${library} + --additional-properties packageName=${spec}-${library},supportAsync=false --library=$library $@" java ${JAVA_OPTS} -jar ${executable} ${args} || exit 1 done diff --git a/docs/generators/rust.md b/docs/generators/rust.md index b59b31471f0..951aa94f55a 100644 --- a/docs/generators/rust.md +++ b/docs/generators/rust.md @@ -6,10 +6,10 @@ sidebar_label: rust | Option | Description | Values | Default | | ------ | ----------- | ------ | ------- | |hideGenerationTimestamp|Hides the generation timestamp when files are generated.| |true| -|library|library template (sub-template) to use.|
**hyper**
HTTP client: Hyper.
**reqwest**
HTTP client: Reqwest.
|hyper| +|library|library template (sub-template) to use.|
**hyper**
HTTP client: Hyper.
**reqwest**
HTTP client: Reqwest.
|reqwest| |packageName|Rust package name (convention: lowercase).| |openapi| |packageVersion|Rust package version.| |1.0.0| -|supportAsync|If set, generate async function call instead| |false| +|supportAsync|If set, generate async function call instead. This option is for 'reqwest' library only| |true| |useSingleRequestParameter|Setting this property to true will generate functions with a single argument containing all API endpoint parameters instead of one argument per parameter.| |false| ## IMPORT MAPPING diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustClientCodegen.java index 3ff2bfe8569..31d4610f86c 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/RustClientCodegen.java @@ -39,7 +39,7 @@ import static org.openapitools.codegen.utils.StringUtils.underscore; public class RustClientCodegen extends DefaultCodegen implements CodegenConfig { private static final Logger LOGGER = LoggerFactory.getLogger(RustClientCodegen.class); private boolean useSingleRequestParameter = false; - private boolean supportAsync = false; + private boolean supportAsync = true; public static final String PACKAGE_NAME = "packageName"; public static final String PACKAGE_VERSION = "packageVersion"; @@ -173,18 +173,18 @@ public class RustClientCodegen extends DefaultCodegen implements CodegenConfig { .defaultValue(Boolean.TRUE.toString())); cliOptions.add(new CliOption(CodegenConstants.USE_SINGLE_REQUEST_PARAMETER, CodegenConstants.USE_SINGLE_REQUEST_PARAMETER_DESC, SchemaTypeUtil.BOOLEAN_TYPE) .defaultValue(Boolean.FALSE.toString())); - cliOptions.add(new CliOption(SUPPORT_ASYNC, "If set, generate async function call instead", SchemaTypeUtil.BOOLEAN_TYPE) - .defaultValue(Boolean.FALSE.toString())); + cliOptions.add(new CliOption(SUPPORT_ASYNC, "If set, generate async function call instead. This option is for 'reqwest' library only", SchemaTypeUtil.BOOLEAN_TYPE) + .defaultValue(Boolean.TRUE.toString())); supportedLibraries.put(HYPER_LIBRARY, "HTTP client: Hyper."); supportedLibraries.put(REQWEST_LIBRARY, "HTTP client: Reqwest."); CliOption libraryOption = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use."); libraryOption.setEnum(supportedLibraries); - // set hyper as the default - libraryOption.setDefault(HYPER_LIBRARY); + // set reqwest as the default + libraryOption.setDefault(REQWEST_LIBRARY); cliOptions.add(libraryOption); - setLibrary(HYPER_LIBRARY); + setLibrary(REQWEST_LIBRARY); } @Override From 82410ae90b94ea2e8b8aa574c274b9569dc55c31 Mon Sep 17 00:00:00 2001 From: Richard Whitehouse Date: Fri, 29 May 2020 15:18:30 +0100 Subject: [PATCH 05/62] [Rust Server] Hyper 0.13 + Async/Await support (#6244) * [Rust Server] Hyper 0.13 + Async/Await support Upgrade dependencies to Hyper 0.13 and use async/await. * [Rust Server] Add missing hyper-tls dependency * [Rust Server] Add missing models import * Update samples --- .../main/resources/rust-server/Cargo.mustache | 40 +- .../rust-server/client-imports.mustache | 49 +- .../resources/rust-server/client-mod.mustache | 174 +- .../rust-server/client-operation.mustache | 264 +- .../resources/rust-server/context.mustache | 124 +- .../rust-server/example-client-main.mustache | 43 +- .../example-client-server.mustache | 8 +- .../example-server-common.mustache | 63 +- .../rust-server/example-server-main.mustache | 5 +- .../example-server-operation.mustache | 6 +- .../example-server-server.mustache | 7 +- .../main/resources/rust-server/lib.mustache | 113 +- .../rust-server/server-callbacks.mustache | 84 +- .../rust-server/server-imports.mustache | 27 +- .../rust-server/server-make-service.mustache | 40 +- .../rust-server/server-operation.mustache | 131 +- .../server-service-footer.mustache | 18 +- .../server-service-header.mustache | 60 +- .../output/multipart-v3/Cargo.toml | 32 +- .../multipart-v3/examples/client/main.rs | 35 +- .../multipart-v3/examples/server/main.rs | 5 +- .../multipart-v3/examples/server/server.rs | 88 +- .../output/multipart-v3/src/client/mod.rs | 608 +-- .../output/multipart-v3/src/context.rs | 95 +- .../output/multipart-v3/src/lib.rs | 93 +- .../output/multipart-v3/src/server/mod.rs | 264 +- .../output/no-example-v3/Cargo.toml | 32 +- .../no-example-v3/examples/client/main.rs | 35 +- .../no-example-v3/examples/server/main.rs | 5 +- .../no-example-v3/examples/server/server.rs | 76 +- .../output/no-example-v3/src/client/mod.rs | 303 +- .../output/no-example-v3/src/context.rs | 95 +- .../output/no-example-v3/src/lib.rs | 63 +- .../output/no-example-v3/src/server/mod.rs | 171 +- .../rust-server/output/openapi-v3/Cargo.toml | 35 +- .../output/openapi-v3/examples/client/main.rs | 35 +- .../openapi-v3/examples/client/server.rs | 83 +- .../output/openapi-v3/examples/server/main.rs | 5 +- .../openapi-v3/examples/server/server.rs | 208 +- .../output/openapi-v3/src/client/callbacks.rs | 179 +- .../output/openapi-v3/src/client/mod.rs | 2838 ++++++------ .../output/openapi-v3/src/context.rs | 102 +- .../rust-server/output/openapi-v3/src/lib.rs | 458 +- .../output/openapi-v3/src/server/callbacks.rs | 301 +- .../output/openapi-v3/src/server/mod.rs | 666 ++- .../rust-server/output/ops-v3/Cargo.toml | 32 +- .../output/ops-v3/examples/client/main.rs | 35 +- .../output/ops-v3/examples/server/main.rs | 5 +- .../output/ops-v3/examples/server/server.rs | 292 +- .../output/ops-v3/src/client/mod.rs | 3325 +++++++------- .../rust-server/output/ops-v3/src/context.rs | 95 +- .../rust-server/output/ops-v3/src/lib.rs | 619 +-- .../output/ops-v3/src/server/mod.rs | 768 ++-- .../Cargo.toml | 35 +- .../examples/client/main.rs | 35 +- .../examples/server/main.rs | 5 +- .../examples/server/server.rs | 280 +- .../src/client/mod.rs | 3993 ++++++++--------- .../src/context.rs | 124 +- .../src/lib.rs | 573 +-- .../src/server/mod.rs | 1160 ++--- .../output/rust-server-test/Cargo.toml | 32 +- .../rust-server-test/examples/client/main.rs | 35 +- .../rust-server-test/examples/server/main.rs | 5 +- .../examples/server/server.rs | 124 +- .../output/rust-server-test/src/client/mod.rs | 1069 ++--- .../output/rust-server-test/src/context.rs | 95 +- .../output/rust-server-test/src/lib.rs | 183 +- .../output/rust-server-test/src/server/mod.rs | 352 +- 69 files changed, 10635 insertions(+), 10802 deletions(-) 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 64fb641c762..6625d274b0a 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache @@ -27,7 +27,7 @@ client = [ "serde_ignored", "regex", "percent-encoding", "lazy_static", {{/hasCallbacks}} {{! Anything added to the list below, should probably be added to the callbacks list below }} - "hyper", "hyper-openssl", "native-tls", "openssl", "url" + "hyper", "hyper-openssl", "hyper-tls", "native-tls", "openssl", "url" ] server = [ {{#apiUsesMultipart}} @@ -40,7 +40,7 @@ server = [ "hyper_0_10", "mime_multipart", {{/apiUsesMultipartRelated}} {{#hasCallbacks}} - "native-tls", "hyper-openssl", "openssl", + "native-tls", "hyper-openssl", "hyper-tls", "openssl", {{/hasCallbacks}} {{! Anything added to the list below, should probably be added to the callbacks list above }} "serde_ignored", "hyper", "regex", "percent-encoding", "url", "lazy_static" @@ -49,20 +49,22 @@ conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk- [target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] native-tls = { version = "0.2", optional = true } +hyper-tls = { version = "0.4", optional = true } [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dependencies] -hyper-openssl = { version = "0.7.1", optional = true } +hyper-openssl = { version = "0.8", optional = true } openssl = {version = "0.10", optional = true } [dependencies] # Common +async-trait = "0.1.24" chrono = { version = "0.4", features = ["serde"] } -futures = "0.1" -swagger = "4.0" +futures = "0.3" +swagger = "5.0.0-alpha-1" log = "0.4.0" mime = "0.3" -serde = { version = "1.0", features = ["derive"]} +serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" # Crates included if required by the API definition @@ -78,27 +80,27 @@ mime_0_2 = { package = "mime", version = "0.2.6", optional = true } multipart = { version = "0.16", default-features = false, optional = true } {{/apiUsesMultipartFormData}} {{#apiUsesUuid}} -uuid = {version = "0.7", features = ["serde", "v4"]} +uuid = {version = "0.8", features = ["serde", "v4"]} {{/apiUsesUuid}} # Common between server and client features -hyper = {version = "0.12", optional = true} +hyper = {version = "0.13", optional = true} {{#apiUsesMultipartRelated}} mime_multipart = {version = "0.5", optional = true} hyper_0_10 = {package = "hyper", version = "0.10", default-features = false, optional=true} {{/apiUsesMultipartRelated}} -serde_ignored = {version = "0.0.4", optional = true} -url = {version = "1.5", optional = true} +serde_ignored = {version = "0.1.1", optional = true} +url = {version = "2.1", optional = true} # Client-specific {{#usesUrlEncodedForm}} -serde_urlencoded = {version = "0.5.1", optional = true} +serde_urlencoded = {version = "0.6.1", optional = true} {{/usesUrlEncodedForm}} # Server, and client callback-specific lazy_static = { version = "1.4", optional = true } -percent-encoding = {version = "1.0.0", optional = true} -regex = {version = "0.2", optional = true} +percent-encoding = {version = "2.1.0", optional = true} +regex = {version = "1.3", optional = true} # Conversion frunk = { version = "0.3.0", optional = true } @@ -109,15 +111,13 @@ frunk-enum-core = { version = "0.2.0", optional = true } [dev-dependencies] clap = "2.25" -error-chain = "0.12" -env_logger = "0.6" -tokio = "0.1.17" -{{^apiUsesUuid}} -uuid = {version = "0.7", features = ["serde", "v4"]} -{{/apiUsesUuid}} +env_logger = "0.7" +tokio = { version = "0.2", features = ["rt-threaded", "macros", "stream"] } +native-tls = "0.2" +tokio-tls = "0.3" [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dev-dependencies] -tokio-openssl = "0.3" +tokio-openssl = "0.4" openssl = "0.10" [[example]] diff --git a/modules/openapi-generator/src/main/resources/rust-server/client-imports.mustache b/modules/openapi-generator/src/main/resources/rust-server/client-imports.mustache index 1cfedfd0884..673a6856f43 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/client-imports.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/client-imports.mustache @@ -1,26 +1,23 @@ -use futures; -use futures::{Future, Stream, future, stream}; -use hyper; -use hyper::client::HttpConnector; +use async_trait::async_trait; +use futures::{Stream, future, future::BoxFuture, stream, future::TryFutureExt, future::FutureExt, stream::StreamExt}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; -use hyper::{Body, Uri, Response}; -#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] -use hyper_openssl::HttpsConnector; -use serde_json; +use hyper::{Body, Request, Response, service::Service, Uri}; +use percent_encoding::{utf8_percent_encode, AsciiSet}; use std::borrow::Cow; use std::convert::TryInto; -use std::io::{Read, Error, ErrorKind}; -use std::error; +use std::io::{ErrorKind, Read}; +use std::error::Error; +use std::future::Future; use std::fmt; use std::path::Path; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use std::str; use std::str::FromStr; use std::string::ToString; -use swagger; -use swagger::{ApiError, Connector, client::Service, XSpanIdString, Has, AuthData}; +use std::task::{Context, Poll}; +use swagger::{ApiError, AuthData, BodyExt, Connector, Has, XSpanIdString}; use url::form_urlencoded; -use url::percent_encoding::{utf8_percent_encode, PATH_SEGMENT_ENCODE_SET, QUERY_ENCODE_SET}; + {{#apiUsesMultipartFormData}} use mime::Mime; use std::io::Cursor; @@ -30,20 +27,18 @@ use multipart::client::lazy::Multipart; use hyper_0_10::header::{Headers, ContentType}; use mime_multipart::{Node, Part, generate_boundary, write_multipart}; {{/apiUsesMultipartRelated}} -{{#apiUsesUuid}} -use uuid; -{{/apiUsesUuid}} -{{#usesXml}} -use serde_xml_rs; -{{/usesXml}} use crate::models; use crate::header; -url::define_encode_set! { - /// This encode set is used for object IDs - /// - /// Aside from the special characters defined in the `PATH_SEGMENT_ENCODE_SET`, - /// the vertical bar (|) is encoded. - pub ID_ENCODE_SET = [PATH_SEGMENT_ENCODE_SET] | {'|'} -} +/// https://url.spec.whatwg.org/#fragment-percent-encode-set +#[allow(dead_code)] +const FRAGMENT_ENCODE_SET: &AsciiSet = &percent_encoding::CONTROLS + .add(b' ').add(b'"').add(b'<').add(b'>').add(b'`'); + +/// This encode set is used for object IDs +/// +/// Aside from the special characters defined in the `PATH_SEGMENT_ENCODE_SET`, +/// the vertical bar (|) is encoded. +#[allow(dead_code)] +const ID_ENCODE_SET: &AsciiSet = &FRAGMENT_ENCODE_SET.add(b'|'); 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 fb9028992fd..506cf8c8654 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 @@ -8,11 +8,11 @@ pub mod callbacks; {{/hasCallbacks}} /// Convert input into a base path, e.g. "http://example:123". Also checks the scheme as it goes. -fn into_base_path(input: &str, correct_scheme: Option<&'static str>) -> Result { +fn into_base_path(input: impl TryInto, correct_scheme: Option<&'static str>) -> Result { // First convert to Uri, since a base path is a subset of Uri. - let uri = Uri::from_str(input)?; + let uri = input.try_into()?; - let scheme = uri.scheme_part().ok_or(ClientInitError::InvalidScheme)?; + let scheme = uri.scheme_str().ok_or(ClientInitError::InvalidScheme)?; // Check the scheme if necessary if let Some(correct_scheme) = correct_scheme { @@ -22,38 +22,54 @@ fn into_base_path(input: &str, correct_scheme: Option<&'static str>) -> Result +pub struct Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { /// Inner service - client_service: Arc + Send + Sync>>, + client_service: S, /// Base path of the API base_path: String, } -impl fmt::Debug for Client +impl fmt::Debug for Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Client {{ base_path: {} }}", self.base_path) } } -impl Clone for Client +impl Clone for Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { fn clone(&self) -> Self { - Client { + Self { client_service: self.client_service.clone(), base_path: self.base_path.clone(), } } } -impl Client +impl Client> where + C: hyper::client::connect::Connect + Clone + Send + Sync + 'static { /// Create a client with a custom implementation of hyper::client::Connect. /// @@ -66,30 +82,93 @@ impl Client /// /// # Arguments /// - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "http://www.my-api-implementation.com" /// * `protocol` - Which protocol to use when constructing the request url, e.g. `Some("http")` /// * `connector` - Implementation of `hyper::client::Connect` to use for the client - pub fn try_new_with_connector( + pub fn try_new_with_connector( base_path: &str, protocol: Option<&'static str>, connector: C, - ) -> Result where - C: hyper::client::connect::Connect + 'static, - C::Transport: 'static, - C::Future: 'static, + ) -> Result { - let client_service = Box::new(hyper::client::Client::builder().build(connector)); + let client_service = hyper::client::Client::builder().build(connector); - Ok(Client { - client_service: Arc::new(client_service), + Ok(Self { + client_service, base_path: into_base_path(base_path, protocol)?, }) } +} +#[derive(Debug, Clone)] +pub enum HyperClient { + Http(hyper::client::Client), + Https(hyper::client::Client), +} + +impl Service> for HyperClient { + type Response = Response; + type Error = hyper::Error; + type Future = hyper::client::ResponseFuture; + + fn poll_ready(&mut self, cx: &mut Context) -> Poll> { + match self { + HyperClient::Http(client) => client.poll_ready(cx), + HyperClient::Https(client) => client.poll_ready(cx), + } + } + + fn call(&mut self, req: Request) -> Self::Future { + match self { + HyperClient::Http(client) => client.call(req), + HyperClient::Https(client) => client.call(req) + } + } +} + +impl Client { /// Create an HTTP client. /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "http://www.my-api-implementation.com" + pub fn try_new( + base_path: &str, + ) -> Result { + let uri = Uri::from_str(base_path)?; + + let scheme = uri.scheme_str().ok_or(ClientInitError::InvalidScheme)?; + let scheme = scheme.to_ascii_lowercase(); + + let connector = Connector::builder(); + + let client_service = match scheme.as_str() { + "http" => { + HyperClient::Http(hyper::client::Client::builder().build(connector.build())) + }, + "https" => { + let connector = connector.https() + .build() + .map_err(|e| ClientInitError::SslError(e))?; + HyperClient::Https(hyper::client::Client::builder().build(connector)) + }, + _ => { + return Err(ClientInitError::InvalidScheme); + } + }; + + Ok(Self { + client_service, + base_path: into_base_path(base_path, None)?, + }) + } +} + +impl Client> +{ + /// Create an HTTP client. + /// + /// # Arguments + /// * `base_path` - base path of the client API, i.e. "http://www.my-api-implementation.com" pub fn try_new_http( base_path: &str, ) -> Result { @@ -97,11 +176,20 @@ impl Client Self::try_new_with_connector(base_path, Some("http"), http_connector) } +} +#[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] +type HttpsConnector = hyper_tls::HttpsConnector; + +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +type HttpsConnector = hyper_openssl::HttpsConnector; + +impl Client> +{ /// Create a client with a TLS connection to the server /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "https://www.my-api-implementation.com" pub fn try_new_https(base_path: &str) -> Result { let https_connector = Connector::builder() @@ -114,7 +202,7 @@ impl Client /// Create a client with a TLS connection to the server using a pinned certificate /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "https://www.my-api-implementation.com" /// * `ca_certificate` - Path to CA certificate used to authenticate the server #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] pub fn try_new_https_pinned( @@ -135,7 +223,7 @@ impl Client /// Create a client with a mutually authenticated TLS connection to the server. /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "https://www.my-api-implementation.com" /// * `ca_certificate` - Path to CA certificate used to authenticate the server /// * `client_key` - Path to the client private key /// * `client_certificate` - Path to the client's public certificate associated with the private key @@ -161,17 +249,24 @@ impl Client } } -impl Client +impl Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { - /// Constructor for creating a `Client` by passing in a pre-made `swagger::Service` + /// Constructor for creating a `Client` by passing in a pre-made `hyper::service::Service` / + /// `tower::Service` /// /// This allows adding custom wrappers around the underlying transport, for example for logging. pub fn try_new_with_client_service( - client_service: Arc + Send + Sync>>, + client_service: S, base_path: &str, - ) -> Result { - Ok(Client { - client_service: client_service, + ) -> Result + { + Ok(Self { + client_service, base_path: into_base_path(base_path, None)?, }) } @@ -211,16 +306,29 @@ impl fmt::Display for ClientInitError { } } -impl error::Error for ClientInitError { +impl Error for ClientInitError { fn description(&self) -> &str { "Failed to produce a hyper client." } } -impl Api for Client where - C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}}, - F: Future, Error=hyper::Error> + Send + 'static +#[async_trait] +impl Api for Client where + C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Clone + Send + Sync + 'static, + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { + fn poll_ready(&self, cx: &mut Context) -> Poll> { + match self.client_service.clone().poll_ready(cx) { + Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())), + Poll::Ready(Ok(o)) => Poll::Ready(Ok(o)), + Poll::Pending => Poll::Pending, + } + } + {{#apiInfo}} {{#apis}} {{#operations}} diff --git a/modules/openapi-generator/src/main/resources/rust-server/client-operation.mustache b/modules/openapi-generator/src/main/resources/rust-server/client-operation.mustache index cc65e176ac5..9db3e8c2c5c 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/client-operation.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/client-operation.mustache @@ -1,4 +1,4 @@ - fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}( + async fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}( &self, {{#vendorExtensions}} {{#callbackParams}} @@ -8,8 +8,9 @@ {{#allParams}} param_{{{paramName}}}: {{^required}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{/required}}, {{/allParams}} - context: &C) -> Box + Send> + context: &C) -> Result<{{{operationId}}}Response, ApiError> { + let mut client_service = self.client_service.clone(); let mut uri = format!( {{#isCallbackRequest}} "{{vendorExtensions.x-path-format-string}}" @@ -29,105 +30,113 @@ ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); {{#queryParams}} {{^required}} - if let Some(param_{{{paramName}}}) = param_{{{paramName}}} { + if let Some(param_{{{paramName}}}) = param_{{{paramName}}} { {{/required}} - query_string.append_pair("{{{baseName}}}", ¶m_{{{paramName}}}{{#isListContainer}}.iter().map(ToString::to_string).collect::>().join(","){{/isListContainer}}{{^isListContainer}}.to_string(){{/isListContainer}}); + query_string.append_pair("{{{baseName}}}", ¶m_{{{paramName}}}{{#isListContainer}}.iter().map(ToString::to_string).collect::>().join(","){{/isListContainer}}{{^isListContainer}}.to_string(){{/isListContainer}}); {{^required}} - } + } {{/required}} {{/queryParams}} {{#authMethods}} {{#isApiKey}} {{#isKeyInQuery}} - if let Some(auth_data) = (context as &dyn Has>).get().as_ref() { - if let AuthData::ApiKey(ref api_key) = *auth_data { - query_string.append_pair("{{keyParamName}}", api_key); + if let Some(auth_data) = (context as &dyn Has>).get().as_ref() { + if let AuthData::ApiKey(ref api_key) = *auth_data { + query_string.append_pair("{{keyParamName}}", api_key); + } } - } {{/isKeyInQuery}} {{/isApiKey}} {{/authMethods}} - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("{{{vendorExtensions.HttpMethod}}}") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; {{#vendorExtensions}} {{#consumesMultipart}} - let mut multipart = Multipart::new(); + let (body_string, multipart_header) = { + let mut multipart = Multipart::new(); {{#vendorExtensions}} {{#formParams}} {{#-first}} - // For each parameter, encode as appropriate and add to the multipart body as a stream. + // For each parameter, encode as appropriate and add to the multipart body as a stream. {{/-first}} {{^isByteArray}} {{#jsonSchema}} - let {{{paramName}}}_str = match serde_json::to_string(¶m_{{{paramName}}}) { - Ok(str) => str, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to parse {{{paramName}}} to string: {}", e)))), - }; + let {{{paramName}}}_str = match serde_json::to_string(¶m_{{{paramName}}}) { + Ok(str) => str, + Err(e) => return Err(ApiError(format!("Unable to parse {{{paramName}}} to string: {}", e))), + }; - let {{{paramName}}}_vec = {{{paramName}}}_str.as_bytes().to_vec(); + let {{{paramName}}}_vec = {{{paramName}}}_str.as_bytes().to_vec(); + let {{{paramName}}}_mime = mime_0_2::Mime::from_str("application/json").expect("impossible to fail to parse"); + let {{{paramName}}}_cursor = Cursor::new({{{paramName}}}_vec); - let {{{paramName}}}_mime = mime_0_2::Mime::from_str("application/json").expect("impossible to fail to parse"); - - let {{{paramName}}}_cursor = Cursor::new({{{paramName}}}_vec); - - multipart.add_stream("{{{paramName}}}", {{{paramName}}}_cursor, None as Option<&str>, Some({{{paramName}}}_mime)); + multipart.add_stream("{{{paramName}}}", {{{paramName}}}_cursor, None as Option<&str>, Some({{{paramName}}}_mime)); {{/jsonSchema}} {{/isByteArray}} + {{#isByteArray}} - let {{{paramName}}}_vec = param_{{{paramName}}}.to_vec(); + let {{{paramName}}}_vec = param_{{{paramName}}}.to_vec(); - let {{{paramName}}}_mime = match mime_0_2::Mime::from_str("application/octet-stream") { - Ok(mime) => mime, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to get mime type: {:?}", err)))), - }; + let {{{paramName}}}_mime = match mime_0_2::Mime::from_str("application/octet-stream") { + Ok(mime) => mime, + Err(err) => return Err(ApiError(format!("Unable to get mime type: {:?}", err))), + }; - let {{{paramName}}}_cursor = Cursor::new({{{paramName}}}_vec); + let {{{paramName}}}_cursor = Cursor::new({{{paramName}}}_vec); - let filename = None as Option<&str> ; - multipart.add_stream("{{{paramName}}}", {{{paramName}}}_cursor, filename, Some({{{paramName}}}_mime)); + let filename = None as Option<&str> ; + multipart.add_stream("{{{paramName}}}", {{{paramName}}}_cursor, filename, Some({{{paramName}}}_mime)); {{/isByteArray}} {{/formParams}} {{/vendorExtensions}} - let mut fields = match multipart.prepare() { - Ok(fields) => fields, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build request: {}", err)))), + + let mut fields = match multipart.prepare() { + Ok(fields) => fields, + Err(err) => return Err(ApiError(format!("Unable to build request: {}", err))), + }; + + let mut body_string = String::new(); + + match fields.read_to_string(&mut body_string) { + Ok(_) => (), + Err(err) => return Err(ApiError(format!("Unable to build body: {}", err))), + } + + let boundary = fields.boundary(); + + let multipart_header = format!("multipart/form-data;boundary={}", boundary); + + (body_string, multipart_header) }; - let mut body_string = String::new(); - match fields.read_to_string(&mut body_string) { - Ok(_) => (), - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build body: {}", err)))), - } - let boundary = fields.boundary(); - - let multipart_header = format!("multipart/form-data;boundary={}", boundary); - *request.body_mut() = Body::from(body_string); request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(&multipart_header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", multipart_header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", multipart_header, e))) }); {{/consumesMultipart}} @@ -146,7 +155,7 @@ let header = "{{#consumes}}{{#-first}}{{{mediaType}}}{{/-first}}{{/consumes}}{{^consumes}}application/json{{/consumes}}"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); *request.body_mut() = Body::from(body.into_bytes()); {{/-last}} @@ -209,7 +218,7 @@ &[header.as_bytes(), "; boundary=".as_bytes(), &boundary, "; type=\"application/json\"".as_bytes()].concat() ) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); {{/-last}} @@ -264,7 +273,7 @@ let header = "{{#consumes}}{{#-first}}{{{mediaType}}}{{/-first}}{{/consumes}}{{^consumes}}application/json{{/consumes}}"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); {{#-last}} @@ -272,14 +281,14 @@ {{/bodyParam}} {{/consumesMultipart}} {{/vendorExtensions}} - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); {{#hasAuthMethods}} - if let Some(auth_data) = (context as &dyn Has>).get().as_ref() { + if let Some(auth_data) = Has::>::get(context).as_ref() { // Currently only authentication with Basic and Bearer are supported match auth_data { {{#authMethods}} @@ -288,7 +297,7 @@ let auth = swagger::auth::Header(basic_header.clone()); let header = match HeaderValue::from_str(&format!("{}", auth)) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create Authorization header: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create Authorization header: {}", e))) }; request.headers_mut().insert( hyper::header::AUTHORIZATION, @@ -300,7 +309,7 @@ let auth = swagger::auth::Header(bearer_header.clone()); let header = match HeaderValue::from_str(&format!("{}", auth)) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create Authorization header: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create Authorization header: {}", e))) }; request.headers_mut().insert( hyper::header::AUTHORIZATION, @@ -313,7 +322,7 @@ let auth = swagger::auth::Header(bearer_header.clone()); let header = match HeaderValue::from_str(&format!("{}", auth)) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create Authorization header: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create Authorization header: {}", e))) }; request.headers_mut().insert( hyper::header::AUTHORIZATION, @@ -341,8 +350,8 @@ match header::IntoHeaderValue(param_{{{paramName}}}.clone()).try_into() { Ok(header) => header, Err(e) => { - return Box::new(future::err(ApiError(format!( - "Invalid header {{{paramName}}} - {}", e)))) as Box + Send>; + return Err(ApiError(format!( + "Invalid header {{{paramName}}} - {}", e))); }, }); {{^required}} @@ -356,111 +365,102 @@ {{/isMapContainer}} {{/headerParams}} - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { {{#responses}} - {{{code}}} => { + {{{code}}} => { {{#headers}} - let response_{{{name}}} = match response.headers().get(HeaderName::from_static("{{{nameInLowerCase}}}")) { - Some(response_{{{name}}}) => response_{{{name}}}.clone(), - None => return Box::new(future::err(ApiError(String::from("Required response header {{{baseName}}} for response {{{code}}} was not found.")))) as Box + Send>, - }; - let response_{{{name}}} = match TryInto::>::try_into(response_{{{name}}}) { - Ok(value) => value, - Err(e) => { - return Box::new(future::err(ApiError(format!("Invalid response header {{baseName}} for response {{code}} - {}", e)))) as Box + Send>; - }, - }; - let response_{{{name}}} = response_{{{name}}}.0; + let response_{{{name}}} = match response.headers().get(HeaderName::from_static("{{{nameInLowerCase}}}")) { + Some(response_{{{name}}}) => response_{{{name}}}.clone(), + None => { + return Err(ApiError(String::from("Required response header {{{baseName}}} for response {{{code}}} was not found."))); + } + }; + let response_{{{name}}} = match TryInto::>::try_into(response_{{{name}}}) { + Ok(value) => value, + Err(e) => { + return Err(ApiError(format!("Invalid response header {{baseName}} for response {{code}} - {}", e))); + }, + }; + let response_{{{name}}} = response_{{{name}}}.0; {{/headers}} - let body = response.into_body(); - Box::new( + let body = response.into_body(); {{#dataType}} - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; {{#vendorExtensions}} {{#producesBytes}} - Ok(swagger::ByteArray(body.to_vec())) + let body = swagger::ByteArray(body.to_vec()); {{/producesBytes}} {{^producesBytes}} - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; {{#producesXml}} - // ToDo: this will move to swagger-rs and become a standard From conversion trait - // once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream - serde_xml_rs::from_str::<{{{dataType}}}>(body) - .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e))) + // ToDo: this will move to swagger-rs and become a standard From conversion trait + // once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream + let body = serde_xml_rs::from_str::<{{{dataType}}}>(body) + .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e)))?; {{/producesXml}} {{#producesJson}} - serde_json::from_str::<{{{dataType}}}>(body) - .map_err(|e| e.into()) + let body = serde_json::from_str::<{{{dataType}}}>(body)?; {{/producesJson}} {{#producesPlainText}} - Ok(body.to_string()) + let body = body.to_string(); {{/producesPlainText}} - ) {{/producesBytes}} {{/vendorExtensions}} - ) - .map(move |body| { - {{{operationId}}}Response::{{#vendorExtensions}}{{x-responseId}}{{/vendorExtensions}} + Ok({{{operationId}}}Response::{{#vendorExtensions}}{{x-responseId}}{{/vendorExtensions}} {{^headers}} - (body) + (body) {{/headers}} {{#headers}} {{#-first}} - { - body: body, + { + body: body, {{/-first}} - {{{name}}}: response_{{name}}, + {{{name}}}: response_{{name}}, {{#-last}} - } + } {{/-last}} {{/headers}} - }) + ) {{/dataType}} {{^dataType}} - future::ok( - {{{operationId}}}Response::{{#vendorExtensions}}{{x-responseId}}{{/vendorExtensions}} + Ok( + {{{operationId}}}Response::{{#vendorExtensions}}{{x-responseId}}{{/vendorExtensions}} {{#headers}} {{#-first}} - { + { {{/-first}} - {{{name}}}: response_{{name}}, + {{{name}}}: response_{{name}}, {{#-last}} - } + } {{/-last}} {{/headers}} - ) + ) {{/dataType}} - ) as Box + Send> - }, -{{/responses}} - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } } - })) +{{/responses}} + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } diff --git a/modules/openapi-generator/src/main/resources/rust-server/context.mustache b/modules/openapi-generator/src/main/resources/rust-server/context.mustache index 6c627cbceeb..c8b4d2ef5b2 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/context.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/context.mustache @@ -1,13 +1,12 @@ -use futures::Future; -use hyper; +use futures::future::BoxFuture; use hyper::header::HeaderName; -use hyper::{Error, Request, Response, StatusCode, service::Service, body::Payload}; +use hyper::{Error, Request, Response, StatusCode, service::Service}; use url::form_urlencoded; use std::default::Default; use std::io; use std::marker::PhantomData; +use std::task::{Poll, Context}; use swagger::auth::{AuthData, Authorization, Bearer, Scopes}; -use swagger::context::ContextualPayload; use swagger::{EmptyContext, Has, Pop, Push, XSpanIdString}; use crate::Api; @@ -31,58 +30,52 @@ where } // Make a service that adds context. -impl<'a, T, SC, A, B, C, D, E, ME, S, OB, F> hyper::service::MakeService<&'a SC> for +impl Service for MakeAddContext where - A: Default + Push, + Target: Send, + A: Default + Push + Send, B: Push, Result = C>, C: Push, Result = D>, D: Send + 'static, - T: hyper::service::MakeService< - &'a SC, - Error = E, - MakeError = ME, - Service = S, - ReqBody = ContextualPayload, - ResBody = OB, - Future = F - >, - S: Service< - Error = E, - ReqBody = ContextualPayload, - ResBody = OB> + 'static, - ME: swagger::ErrorBound, - E: swagger::ErrorBound, - F: Future + Send + 'static, - S::Future: Send, - OB: Payload, + T: Service + Send, + T::Future: Send + 'static { - type ReqBody = hyper::Body; - type ResBody = OB; - type Error = E; - type MakeError = ME; - type Service = AddContext; - type Future = Box + Send + 'static>; + type Error = T::Error; + type Response = AddContext; + type Future = BoxFuture<'static, Result>; - fn make_service(&mut self, ctx: &'a SC) -> Self::Future { - Box::new(self.inner.make_service(ctx).map(|s| AddContext::new(s))) + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + self.inner.poll_ready(cx) + } + + fn call(&mut self, target: Target) -> Self::Future { + let service = self.inner.call(target); + + Box::pin(async move { + Ok(AddContext::new(service.await?)) + }) } } -/// Middleware to extract authentication data from request -pub struct AddContext { +/// Middleware to add context data from the request +pub struct AddContext +where + A: Default + Push, + B: Push, Result = C>, + C: Push, Result = D> +{ inner: T, marker: PhantomData, } -impl AddContext +impl AddContext where A: Default + Push, B: Push, Result = C>, C: Push, Result = D>, - T: Service, { - pub fn new(inner: T) -> AddContext { + pub fn new(inner: T) -> Self { AddContext { inner, marker: PhantomData, @@ -90,24 +83,26 @@ where } } -impl Service for AddContext +impl Service> for AddContext where A: Default + Push, B: Push, Result=C>, C: Push, Result=D>, D: Send + 'static, - T: Service>, - T::Future: Future, Error=T::Error> + Send + 'static + T: Service<(Request, D)> { - type ReqBody = hyper::Body; - type ResBody = T::ResBody; type Error = T::Error; - type Future = Box, Error=T::Error> + Send + 'static>; + type Future = T::Future; + type Response = T::Response; - fn call(&mut self, req: Request) -> Self::Future { - let context = A::default().push(XSpanIdString::get_or_generate(&req)); - let (head, body) = req.into_parts(); - let headers = head.headers.clone(); + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + self.inner.poll_ready(cx) + } + + + fn call(&mut self, request: Request) -> Self::Future { + let context = A::default().push(XSpanIdString::get_or_generate(&request)); + let headers = request.headers(); {{#authMethods}} {{#isBasic}} @@ -119,12 +114,7 @@ impl Service for AddContext let context = context.push(Some(auth_data)); let context = context.push(None::); - let body = ContextualPayload { - inner: body, - context: context, - }; - - return Box::new(self.inner.call(hyper::Request::from_parts(head, body))); + return self.inner.call((request, context)) } } {{/isBasic}} @@ -137,12 +127,7 @@ impl Service for AddContext let context = context.push(Some(auth_data)); let context = context.push(None::); - let body = ContextualPayload { - inner: body, - context: context, - }; - - return Box::new(self.inner.call(hyper::Request::from_parts(head, body))); + return self.inner.call((request, context)) } } {{/isOAuth}} @@ -156,18 +141,13 @@ impl Service for AddContext let context = context.push(Some(auth_data)); let context = context.push(None::); - let body = ContextualPayload { - inner: body, - context: context, - }; - - return Box::new(self.inner.call(hyper::Request::from_parts(head, body))); + return self.inner.call((request, context)) } } {{/isKeyInHeader}} {{#isKeyInQuery}} { - let key = form_urlencoded::parse(head.uri.query().unwrap_or_default().as_bytes()) + let key = form_urlencoded::parse(request.uri().query().unwrap_or_default().as_bytes()) .filter(|e| e.0 == "api_key_query") .map(|e| e.1.clone().into_owned()) .nth(0); @@ -176,11 +156,7 @@ impl Service for AddContext let context = context.push(Some(auth_data)); let context = context.push(None::); - let body = ContextualPayload { - inner: body, - context: context, - }; - return Box::new(self.inner.call(hyper::Request::from_parts(head, body))); + return self.inner.call((request, context)) } } {{/isKeyInQuery}} @@ -189,11 +165,7 @@ impl Service for AddContext let context = context.push(None::); let context = context.push(None::); - let body = ContextualPayload { - inner: body, - context: context, - }; - Box::new(self.inner.call(hyper::Request::from_parts(head, body))) + self.inner.call((request, context)) } } diff --git a/modules/openapi-generator/src/main/resources/rust-server/example-client-main.mustache b/modules/openapi-generator/src/main/resources/rust-server/example-client-main.mustache index b1f7bbeee95..2463d942f99 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/example-client-main.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/example-client-main.mustache @@ -5,11 +5,18 @@ mod server; {{/hasCallbacks}} #[allow(unused_imports)] -use futures::{Future, future, Stream, stream}; +use futures::{future, Stream, stream}; #[allow(unused_imports)] use {{{externCrateName}}}::{Api, ApiNoContext, Client, ContextWrapperExt, models, - ApiError{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}, - {{{operationId}}}Response{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} +{{#apiInfo}} + {{#apis}} + {{#operations}} + {{#operation}} + {{{operationId}}}Response, + {{/operation}} + {{/operations}} + {{/apis}} +{{/apiInfo}} }; use clap::{App, Arg}; @@ -18,7 +25,9 @@ use log::info; // swagger::Has may be unused if there are no examples #[allow(unused_imports)] -use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData}; +use swagger::{AuthData, ContextBuilder, EmptyContext, Has, Push, XSpanIdString}; + +type ClientContext = swagger::make_context_ty!(ContextBuilder, EmptyContext, Option, XSpanIdString); // rt may be unused if there are no examples #[allow(unused_mut)] @@ -66,21 +75,21 @@ fn main() { matches.value_of("host").unwrap(), matches.value_of("port").unwrap()); - let client = if matches.is_present("https") { - // Using Simple HTTPS - Client::try_new_https(&base_url) - .expect("Failed to create HTTPS client") - } else { - // Using HTTP - Client::try_new_http( - &base_url) - .expect("Failed to create HTTP client") - }; - - let context: swagger::make_context_ty!(ContextBuilder, EmptyContext, Option, XSpanIdString) = + let context: ClientContext = swagger::make_context!(ContextBuilder, EmptyContext, None as Option, XSpanIdString::default()); - let client = client.with_context(context); + let mut client : Box> = if matches.is_present("https") { + // Using Simple HTTPS + let client = Box::new(Client::try_new_https(&base_url) + .expect("Failed to create HTTPS client")); + Box::new(client.with_context(context)) + } else { + // Using HTTP + let client = Box::new(Client::try_new_http( + &base_url) + .expect("Failed to create HTTP client")); + Box::new(client.with_context(context)) + }; let mut rt = tokio::runtime::Runtime::new().unwrap(); {{#hasCallbacks}} diff --git a/modules/openapi-generator/src/main/resources/rust-server/example-client-server.mustache b/modules/openapi-generator/src/main/resources/rust-server/example-client-server.mustache index 43f1ca53a60..126af4cf747 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/example-client-server.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/example-client-server.mustache @@ -1,5 +1,5 @@ {{>example-server-common}} -use {{{externCrateName}}}::{CallbackApi, ApiError}; +use {{{externCrateName}}}::CallbackApi; {{#apiInfo}} {{#apis}} {{#operations}} @@ -16,8 +16,12 @@ use {{{externCrateName}}}::{{{operationId}}}Response; {{/apis}} {{/apiInfo}} use {{{externCrateName}}}::client::callbacks::MakeService; +use std::error::Error; +use swagger::ApiError; -impl CallbackApi for Server where C: Has{ +#[async_trait] +impl CallbackApi for Server where C: Has + Send + Sync +{ {{#apiInfo}} {{#apis}} {{#operations}} diff --git a/modules/openapi-generator/src/main/resources/rust-server/example-server-common.mustache b/modules/openapi-generator/src/main/resources/rust-server/example-server-common.mustache index 16fefd9e6eb..b4090357c30 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/example-server-common.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/example-server-common.mustache @@ -2,30 +2,22 @@ #![allow(unused_imports)] -mod errors { - error_chain::error_chain!{} -} - -pub use self::errors::*; - -use chrono; -use futures::{future, Future, Stream}; +use async_trait::async_trait; +use futures::{future, Stream, StreamExt, TryFutureExt, TryStreamExt}; use hyper::server::conn::Http; -use hyper::service::MakeService as _; +use hyper::service::Service; use log::info; use openssl::ssl::SslAcceptorBuilder; +use std::future::Future; use std::marker::PhantomData; use std::net::SocketAddr; use std::sync::{Arc, Mutex}; -use swagger; +use std::task::{Context, Poll}; use swagger::{Has, XSpanIdString}; use swagger::auth::MakeAllowAllAuthenticator; use swagger::EmptyContext; use tokio::net::TcpListener; -{{#apiUsesUuid}}use uuid;{{/apiUsesUuid}} -#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] -use tokio_openssl::SslAcceptorExt; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; @@ -33,18 +25,18 @@ use {{{externCrateName}}}::models; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] /// Builds an SSL implementation for Simple HTTPS from some hard-coded file names -pub fn create(addr: &str, https: bool) -> Box + Send> { +pub async fn create(addr: &str, https: bool) { let addr = addr.parse().expect("Failed to parse bind address"); let server = Server::new(); - let service_fn = MakeService::new(server); + let service = MakeService::new(server); - let service_fn = MakeAllowAllAuthenticator::new(service_fn, "cosmo"); + let service = MakeAllowAllAuthenticator::new(service, "cosmo"); - let service_fn = + let mut service = {{{externCrateName}}}::server::context::MakeAddContext::<_, EmptyContext>::new( - service_fn + service ); if https { @@ -62,32 +54,31 @@ pub fn create(addr: &str, https: bool) -> Box ssl.set_certificate_chain_file("examples/server-chain.pem").expect("Failed to set cerificate chain"); ssl.check_private_key().expect("Failed to check private key"); - let tls_acceptor = ssl.build(); - let service_fn = Arc::new(Mutex::new(service_fn)); - let tls_listener = TcpListener::bind(&addr).unwrap().incoming().for_each(move |tcp| { - let addr = tcp.peer_addr().expect("Unable to get remote address"); + let tls_acceptor = Arc::new(ssl.build()); + let mut tcp_listener = TcpListener::bind(&addr).await.unwrap(); + let mut incoming = tcp_listener.incoming(); - let service_fn = service_fn.clone(); + while let (Some(tcp), rest) = incoming.into_future().await { + if let Ok(tcp) = tcp { + let addr = tcp.peer_addr().expect("Unable to get remote address"); + let service = service.call(addr); + let tls_acceptor = Arc::clone(&tls_acceptor); - hyper::rt::spawn(tls_acceptor.accept_async(tcp).map_err(|_| ()).and_then(move |tls| { - let ms = { - let mut service_fn = service_fn.lock().unwrap(); - service_fn.make_service(&addr) - }; + tokio::spawn(async move { + let tls = tokio_openssl::accept(&*tls_acceptor, tcp).await.map_err(|_| ())?; - ms.and_then(move |service| { - Http::new().serve_connection(tls, service) - }).map_err(|_| ()) - })); + let service = service.await.map_err(|_| ())?; - Ok(()) - }).map_err(|_| ()); + Http::new().serve_connection(tls, service).await.map_err(|_| ()) + }); + } - Box::new(tls_listener) + incoming = rest; + } } } else { // Using HTTP - Box::new(hyper::server::Server::bind(&addr).serve(service_fn).map_err(|e| panic!("{:?}", e))) + hyper::server::Server::bind(&addr).serve(service).await.unwrap() } } diff --git a/modules/openapi-generator/src/main/resources/rust-server/example-server-main.mustache b/modules/openapi-generator/src/main/resources/rust-server/example-server-main.mustache index 3d7f7045a77..c0d39f682e5 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/example-server-main.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/example-server-main.mustache @@ -9,7 +9,8 @@ mod server; /// Create custom server, wire it to the autogenerated router, /// and pass it to the web server. -fn main() { +#[tokio::main] +async fn main() { env_logger::init(); let matches = App::new("server") @@ -20,5 +21,5 @@ fn main() { let addr = "127.0.0.1:{{{serverPort}}}"; - hyper::rt::run(server::create(addr, matches.is_present("https"))); + server::create(addr, matches.is_present("https")).await; } diff --git a/modules/openapi-generator/src/main/resources/rust-server/example-server-operation.mustache b/modules/openapi-generator/src/main/resources/rust-server/example-server-operation.mustache index f7b1aaa66d0..5caf982d912 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/example-server-operation.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/example-server-operation.mustache @@ -1,7 +1,7 @@ {{#summary}} /// {{{summary}}} {{/summary}} - fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}( + async fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}( &self, {{#vendorExtensions}} {{#callbackParams}} @@ -11,9 +11,9 @@ {{#allParams}} {{{paramName}}}: {{^required}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{/required}}, {{/allParams}} - context: &C) -> Box + Send> + context: &C) -> Result<{{{operationId}}}Response, ApiError> { let context = context.clone(); info!("{{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}({{#allParams}}{{#vendorExtensions}}{{{formatString}}}{{/vendorExtensions}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) - X-Span-ID: {:?}"{{#allParams}}, {{{paramName}}}{{/allParams}}, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } 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 18eb8cdd1ef..d04e09aad88 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 @@ -2,7 +2,6 @@ use {{{externCrateName}}}::{ Api, - ApiError, {{#apiInfo}} {{#apis}} {{#operations}} @@ -14,8 +13,12 @@ use {{{externCrateName}}}::{ {{/apiInfo}} }; use {{{externCrateName}}}::server::MakeService; +use std::error::Error; +use swagger::ApiError; -impl Api for Server where C: Has{ +#[async_trait] +impl Api for Server where C: Has + Send + Sync +{ {{#apiInfo}} {{#apis}} {{#operations}} 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 e5135683f45..2b5af42776a 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/lib.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/lib.mustache @@ -1,12 +1,12 @@ #![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)] +use async_trait::async_trait; use futures::Stream; -use std::io::Error; +use std::error::Error; +use std::task::{Poll, Context}; +use swagger::{ApiError, ContextWrapper}; -#[deprecated(note = "Import swagger-rs directly")] -pub use swagger::{ApiError, ContextWrapper}; -#[deprecated(note = "Import futures directly")] -pub use futures::Future; +type ServiceError = Box; pub const BASE_PATH: &'static str = "{{{basePathWithoutHost}}}"; {{#appVersion}} @@ -23,7 +23,12 @@ pub const API_VERSION: &'static str = "{{{appVersion}}}"; {{/apis}} {{/apiInfo}} /// API -pub trait Api { +#[async_trait] +pub trait Api { + fn poll_ready(&self, _cx: &mut Context) -> Poll>> { + Poll::Ready(Ok(())) + } + {{#apiInfo}} {{#apis}} {{#operations}} @@ -31,12 +36,12 @@ pub trait Api { {{#summary}} /// {{{summary}}} {{/summary}} - fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}( + async fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}( &self, {{#allParams}} {{{paramName}}}: {{^required}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{/required}}, {{/allParams}} - context: &C) -> Box + Send>; + context: &C) -> Result<{{{operationId}}}Response, ApiError>; {{/operation}} {{/operations}} @@ -44,8 +49,14 @@ pub trait Api { {{/apiInfo}} } -/// API without a `Context` -pub trait ApiNoContext { +/// API where `Context` isn't passed on every API call +#[async_trait] +pub trait ApiNoContext { + + fn poll_ready(&self, _cx: &mut Context) -> Poll>>; + + fn context(&self) -> &C; + {{#apiInfo}} {{#apis}} {{#operations}} @@ -53,12 +64,12 @@ pub trait ApiNoContext { {{#summary}} /// {{{summary}}} {{/summary}} - fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}( + async fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}( &self, {{#allParams}} {{{paramName}}}: {{^required}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{/required}}, {{/allParams}} - ) -> Box + Send>; + ) -> Result<{{{operationId}}}Response, ApiError>; {{/operation}} {{/operations}} @@ -67,18 +78,28 @@ pub trait ApiNoContext { } /// Trait to extend an API to make it easy to bind it to a context. -pub trait ContextWrapperExt<'a, C> where Self: Sized { +pub trait ContextWrapperExt where Self: Sized +{ /// Binds this API to a context. - fn with_context(self: &'a Self, context: C) -> ContextWrapper<'a, Self, C>; + fn with_context(self: Self, context: C) -> ContextWrapper; } -impl<'a, T: Api + Sized, C> ContextWrapperExt<'a, C> for T { - fn with_context(self: &'a T, context: C) -> ContextWrapper<'a, T, C> { +impl + Send + Sync, C: Clone + Send + Sync> ContextWrapperExt for T { + fn with_context(self: T, context: C) -> ContextWrapper { ContextWrapper::::new(self, context) } } -impl<'a, T: Api, C> ApiNoContext for ContextWrapper<'a, T, C> { +#[async_trait] +impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for ContextWrapper { + fn poll_ready(&self, cx: &mut Context) -> Poll> { + self.api().poll_ready(cx) + } + + fn context(&self) -> &C { + ContextWrapper::context(self) + } + {{#apiInfo}} {{#apis}} {{#operations}} @@ -86,14 +107,15 @@ impl<'a, T: Api, C> ApiNoContext for ContextWrapper<'a, T, C> { {{#summary}} /// {{{summary}}} {{/summary}} - fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}( + async fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}( &self, {{#allParams}} {{{paramName}}}: {{^required}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{/required}}, {{/allParams}} - ) -> Box + Send> + ) -> Result<{{{operationId}}}Response, ApiError> { - self.api().{{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}({{#allParams}}{{{paramName}}}, {{/allParams}}&self.context()) + let context = self.context().clone(); + self.api().{{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}({{#allParams}}{{{paramName}}}, {{/allParams}}&context).await } {{/operation}} @@ -101,6 +123,7 @@ impl<'a, T: Api, C> ApiNoContext for ContextWrapper<'a, T, C> { {{/apis}} {{/apiInfo}} } + {{#hasCallbacks}} {{#apiInfo}} @@ -120,7 +143,12 @@ impl<'a, T: Api, C> ApiNoContext for ContextWrapper<'a, T, C> { {{/apiInfo}} /// Callback API -pub trait CallbackApi { +#[async_trait] +pub trait CallbackApi { + fn poll_ready(&self, _cx: &mut Context) -> Poll>> { + Poll::Ready(Ok(())) + } + {{#apiInfo}} {{#apis}} {{#operations}} @@ -131,7 +159,7 @@ pub trait CallbackApi { {{#summary}} /// {{{summary}}} {{/summary}} - fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}( + async fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}( &self, {{#vendorExtensions}} {{#callbackParams}} @@ -141,7 +169,7 @@ pub trait CallbackApi { {{#allParams}} {{{paramName}}}: {{^required}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{/required}}, {{/allParams}} - context: &C) -> Box + Send>; + context: &C) -> Result<{{{operationId}}}Response, ApiError>; {{/requests}} {{/urls}} @@ -153,7 +181,12 @@ pub trait CallbackApi { } /// Callback API without a `Context` -pub trait CallbackApiNoContext { +#[async_trait] +pub trait CallbackApiNoContext { + fn poll_ready(&self, _cx: &mut Context) -> Poll>>; + + fn context(&self) -> &C; + {{#apiInfo}} {{#apis}} {{#operations}} @@ -164,7 +197,7 @@ pub trait CallbackApiNoContext { {{#summary}} /// {{{summary}}} {{/summary}} - fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}( + async fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}( &self, {{#vendorExtensions}} {{#callbackParams}} @@ -174,7 +207,7 @@ pub trait CallbackApiNoContext { {{#allParams}} {{{paramName}}}: {{^required}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{/required}}, {{/allParams}} - ) -> Box + Send>; + ) -> Result<{{{operationId}}}Response, ApiError>; {{/requests}} {{/urls}} @@ -185,19 +218,28 @@ pub trait CallbackApiNoContext { {{/apiInfo}} } -/// Trait to extend an API to make it easy to bind it to a context. -pub trait CallbackContextWrapperExt<'a, C> where Self: Sized { +pub trait CallbackContextWrapperExt where Self: Sized +{ /// Binds this API to a context. - fn with_context(self: &'a Self, context: C) -> ContextWrapper<'a, Self, C>; + fn with_context(self: Self, context: C) -> ContextWrapper; } -impl<'a, T: CallbackApi + Sized, C> CallbackContextWrapperExt<'a, C> for T { - fn with_context(self: &'a T, context: C) -> ContextWrapper<'a, T, C> { +impl + Send + Sync, C: Clone + Send + Sync> CallbackContextWrapperExt for T { + fn with_context(self: T, context: C) -> ContextWrapper { ContextWrapper::::new(self, context) } } -impl<'a, T: CallbackApi, C> CallbackApiNoContext for ContextWrapper<'a, T, C> { +#[async_trait] +impl + Send + Sync, C: Clone + Send + Sync> CallbackApiNoContext for ContextWrapper { + fn poll_ready(&self, cx: &mut Context) -> Poll> { + self.api().poll_ready(cx) + } + + fn context(&self) -> &C { + ContextWrapper::context(self) + } + {{#apiInfo}} {{#apis}} {{#operations}} @@ -208,7 +250,7 @@ impl<'a, T: CallbackApi, C> CallbackApiNoContext for ContextWrapper<'a, T, C> {{#summary}} /// {{{summary}}} {{/summary}} - fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}( + async fn {{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}( &self, {{#vendorExtensions}} {{#callbackParams}} @@ -218,8 +260,9 @@ impl<'a, T: CallbackApi, C> CallbackApiNoContext for ContextWrapper<'a, T, C> {{#allParams}} {{{paramName}}}: {{^required}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{/required}}, {{/allParams}} - ) -> Box + Send> + ) -> Result<{{{operationId}}}Response, ApiError> { + let context = self.context().clone(); self.api().{{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}( {{#vendorExtensions}} {{#callbackParams}} @@ -229,7 +272,7 @@ impl<'a, T: CallbackApi, C> CallbackApiNoContext for ContextWrapper<'a, T, C> {{#allParams}} {{{paramName}}}, {{/allParams}} - &self.context()) + &context).await } {{/requests}} diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-callbacks.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-callbacks.mustache index 76f25f90aa7..c51299077f7 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-callbacks.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-callbacks.mustache @@ -17,29 +17,45 @@ use crate::{{{operationId}}}Response; {{/apiInfo}} /// A client that implements the API by making HTTP calls out to a server. -pub struct Client +pub struct Client where + S: Service< + Request, + Response=Response, + Error=hyper::Error> + Clone + Send + Sync, + S::Future: Send + 'static, { /// Inner service - client_service: Arc + Send + Sync>>, + client_service: S, } -impl fmt::Debug for Client +impl fmt::Debug for Client where + S: Service< + Request, + Response=Response, + Error=hyper::Error> + Clone + Send + Sync, + S::Future: Send + 'static, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Client") } } -impl Clone for Client +impl Clone for Client where + S: Service< + Request, + Response=Response, + Error=hyper::Error> + Clone + Send + Sync, + S::Future: Send + 'static, { fn clone(&self) -> Self { - Client { + Self { client_service: self.client_service.clone(), } } } -impl Client +impl Client> where + C: hyper::client::connect::Connect + Clone + Send + Sync + 'static { /// Create a client with a custom implementation of hyper::client::Connect. /// @@ -53,26 +69,33 @@ impl Client /// # Arguments /// /// * `connector` - Implementation of `hyper::client::Connect` to use for the client - pub fn new_with_connector( - connector: C, - ) -> Self where - C: hyper::client::connect::Connect + 'static, - C::Transport: 'static, - C::Future: 'static, + pub fn new_with_connector(connector: C) -> Self { - let client_service = Box::new(hyper::client::Client::builder().build(connector)); + let client_service = hyper::client::Client::builder().build(connector); - Client { - client_service: Arc::new(client_service), + Self { + client_service, } } +} +impl Client> +{ /// Create an HTTP client. pub fn new_http() -> Self { let http_connector = Connector::builder().build(); Self::new_with_connector(http_connector) } +} +#[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] +type HttpConnector = hyper_tls::HttpsConnector; + +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +type HttpsConnector = hyper_openssl::HttpsConnector; + +impl Client> +{ /// Create a client with a TLS connection to the server. #[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] pub fn new_https() -> Result @@ -132,24 +155,43 @@ impl Client } } -impl Client +impl Client where + S: Service< + Request, + Response=Response, + Error=hyper::Error> + Clone + Send + Sync, + S::Future: Send + 'static, { /// Constructor for creating a `Client` by passing in a pre-made `swagger::Service` /// /// This allows adding custom wrappers around the underlying transport, for example for logging. pub fn new_with_client_service( - client_service: Arc + Send + Sync>>, + client_service: S, ) -> Self { Client { - client_service: client_service, + client_service, } } } -impl CallbackApi for Client where - C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}}, - F: Future, Error=hyper::Error> + Send + 'static +#[async_trait] +impl CallbackApi for Client where + C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync, + S: Service< + Request, + Response=Response, + Error=hyper::Error> + Clone + Send + Sync, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { + fn poll_ready(&self, cx: &mut Context) -> Poll> { + match self.client_service.clone().poll_ready(cx) { + Poll::Ready(Err(e)) => Poll::Ready(Err(Box::new(e))), + Poll::Ready(Ok(o)) => Poll::Ready(Ok(o)), + Poll::Pending => Poll::Pending, + } + } + {{#apiInfo}} {{#apis}} {{#operations}} diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-imports.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-imports.mustache index 2edcdd9b98e..9aa79b47ea4 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-imports.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-imports.mustache @@ -1,38 +1,31 @@ -use std::marker::PhantomData; -use futures::{Future, future, Stream, stream}; -use hyper; -use hyper::{Request, Response, Error, StatusCode, Body, HeaderMap}; +use futures::{future, future::BoxFuture, Stream, stream, future::FutureExt, stream::TryStreamExt}; +use hyper::{Request, Response, StatusCode, Body, HeaderMap}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; use log::warn; -use serde_json; #[allow(unused_imports)] use std::convert::{TryFrom, TryInto}; -use std::io; -use url::form_urlencoded; -#[allow(unused_imports)] -use swagger; -use swagger::{ApiError, XSpanIdString, Has, RequestParser}; +use std::error::Error; +use std::future::Future; +use std::marker::PhantomData; +use std::task::{Context, Poll}; +use swagger::{ApiError, BodyExt, Has, RequestParser, XSpanIdString}; pub use swagger::auth::Authorization; use swagger::auth::Scopes; -use swagger::context::ContextualPayload; +use url::form_urlencoded; {{#apiUsesMultipartRelated}} use hyper_0_10::header::{Headers, ContentType}; use mime_0_2::{TopLevel, SubLevel, Mime as Mime2}; use mime_multipart::{read_multipart_body, Node, Part}; {{/apiUsesMultipartRelated}} -{{#apiUsesUuid}} -use uuid; -{{/apiUsesUuid}} {{#apiUsesMultipartFormData}} use multipart::server::Multipart; use multipart::server::save::SaveResult; {{/apiUsesMultipartFormData}} -{{#usesXml}} -use serde_xml_rs; -{{/usesXml}} #[allow(unused_imports)] use crate::models; use crate::header; pub use crate::context; + +type ServiceFuture = BoxFuture<'static, Result, crate::ServiceError>>; diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-make-service.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-make-service.mustache index 238ddb03b72..b2c7afd5fdf 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-make-service.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-make-service.mustache @@ -1,12 +1,14 @@ -pub struct MakeService { +pub struct MakeService where + T: Api + Clone + Send + 'static, + C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync + 'static +{ api_impl: T, - marker: PhantomData, + marker: PhantomData, } -impl MakeService -where - T: Api + Clone + Send + 'static, - RC: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + 'static +impl MakeService where + T: Api + Clone + Send + 'static, + C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync + 'static { pub fn new(api_impl: T) -> Self { MakeService { @@ -16,21 +18,21 @@ where } } -impl<'a, T, SC, RC> hyper::service::MakeService<&'a SC> for MakeService -where - T: Api + Clone + Send + 'static, - RC: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + 'static + Send +impl hyper::service::Service for MakeService where + T: Api + Clone + Send + 'static, + C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync + 'static { - type ReqBody = ContextualPayload; - type ResBody = Body; - type Error = Error; - type Service = Service; - type Future = future::FutureResult; - type MakeError = Error; + type Response = Service; + type Error = crate::ServiceError; + type Future = future::Ready>; - fn make_service(&mut self, _ctx: &'a SC) -> Self::Future { - future::FutureResult::from(Ok(Service::new( + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn call(&mut self, target: Target) -> Self::Future { + futures::future::ok(Service::new( self.api_impl.clone(), - ))) + )) } } diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-operation.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-operation.mustache index cbb011fe9a3..f3306f76a87 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-operation.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-operation.mustache @@ -4,10 +4,10 @@ { let authorization = match (&context as &dyn Has>).get() { &Some(ref authorization) => authorization, - &None => return Box::new(future::ok(Response::builder() + &None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) .body(Body::from("Unauthenticated")) - .expect("Unable to create Authentication Forbidden response"))), + .expect("Unable to create Authentication Forbidden response")), }; {{#authMethods}} {{#isOAuth}} @@ -22,14 +22,14 @@ if !required_scopes.is_subset(scopes) { let missing_scopes = required_scopes.difference(scopes); - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::FORBIDDEN) .body(Body::from(missing_scopes.fold( "Insufficient authorization, missing scopes".to_string(), |s, scope| format!("{} {}", s, scope)) )) .expect("Unable to create Authentication Insufficient response") - )); + ); } } {{/isOAuth}} @@ -41,10 +41,10 @@ {{#consumesMultipart}} let boundary = match swagger::multipart::boundary(&headers) { Some(boundary) => boundary.to_string(), - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Couldn't find valid multipart body".to_string())) - .expect("Unable to create Bad Request response for incorrect boundary"))), + .expect("Unable to create Bad Request response for incorrect boundary")), }; {{/consumesMultipart}} @@ -64,15 +64,15 @@ let param_{{{paramName}}} = match percent_encoding::percent_decode(path_params["{{{baseName}}}"].as_bytes()).decode_utf8() { Ok(param_{{{paramName}}}) => match param_{{{paramName}}}.parse::<{{{dataType}}}>() { Ok(param_{{{paramName}}}) => param_{{{paramName}}}, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse path parameter {{{baseName}}}: {}", e))) - .expect("Unable to create Bad Request response for invalid path parameter"))), + .expect("Unable to create Bad Request response for invalid path parameter")), }, - Err(_) => return Box::new(future::ok(Response::builder() + Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["{{{baseName}}}"]))) - .expect("Unable to create Bad Request response for invalid percent decode"))) + .expect("Unable to create Bad Request response for invalid percent decode")) }; {{/pathParams}} @@ -97,19 +97,19 @@ Some(result.0), {{/required}} Err(err) => { - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Invalid header {{{baseName}}} - {}", err))) - .expect("Unable to create Bad Request response for invalid header {{{baseName}}}"))); + .expect("Unable to create Bad Request response for invalid header {{{baseName}}}")); }, }, None => { {{#required}} - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required header {{{baseName}}}")) - .expect("Unable to create Bad Request response for missing required header {{{baseName}}}"))); + .expect("Unable to create Bad Request response for missing required header {{{baseName}}}")); {{/required}} {{^required}} None @@ -143,15 +143,15 @@ let param_{{{paramName}}} = match param_{{{paramName}}} { Some(param_{{{paramName}}}) => match param_{{{paramName}}}.parse::<{{{dataType}}}>() { Ok(param_{{{paramName}}}) => param_{{{paramName}}}, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse query parameter {{{baseName}}} - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid query parameter {{{baseName}}}"))), + .expect("Unable to create Bad Request response for invalid query parameter {{{baseName}}}")), }, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required query parameter {{{baseName}}}")) - .expect("Unable to create Bad Request response for missing qeury parameter {{{baseName}}}"))), + .expect("Unable to create Bad Request response for missing qeury parameter {{{baseName}}}")), }; {{/required}} {{^required}} @@ -169,9 +169,8 @@ // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { {{#vendorExtensions}} {{^consumesPlainText}} @@ -191,10 +190,10 @@ }) { Ok(param_{{{paramName}}}) => param_{{{paramName}}}, {{#required}} - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse body parameter {{{baseName}}} - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid body parameter {{{baseName}}} due to schema"))), + .expect("Unable to create Bad Request response for invalid body parameter {{{baseName}}} due to schema")), {{/required}} {{^required}} Err(_) => None, @@ -208,10 +207,10 @@ {{#isString}} match String::from_utf8(body.to_vec()) { Ok(param_{{{paramName}}}) => Some(param_{{{paramName}}}), - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse body parameter {{{baseName}}} - not valid UTF-8: {}", e))) - .expect("Unable to create Bad Request response for invalid body parameter {{{baseName}}} due to UTF-8"))), + .expect("Unable to create Bad Request response for invalid body parameter {{{baseName}}} due to UTF-8")), } {{/isString}} {{/consumesPlainText}} @@ -222,10 +221,10 @@ {{#required}} let param_{{{paramName}}} = match param_{{{paramName}}} { Some(param_{{{paramName}}}) => param_{{{paramName}}}, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required body parameter {{{baseName}}}")) - .expect("Unable to create Bad Request response for missing body parameter {{{baseName}}}"))), + .expect("Unable to create Bad Request response for missing body parameter {{{baseName}}}")), }; {{/required}} {{/-first}} @@ -240,9 +239,8 @@ // Form Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw(); + match result.await { Ok(body) => { use std::io::Read; @@ -252,10 +250,10 @@ entries }, _ => { - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Unable to process all message parts"))) - .expect("Unable to create Bad Request response due to failure to process all message"))) + .expect("Unable to create Bad Request response due to failure to process all message")) }, }; {{#formParams}} @@ -278,11 +276,11 @@ let {{{paramName}}}_model: {{{dataType}}} = match serde_json::from_str(&data) { Ok(model) => model, Err(e) => { - return Box::new(future::ok( + return Ok( Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("{{{paramName}}} data does not match API definition : {}", e))) - .expect("Unable to create Bad Request due to missing required form parameter {{{paramName}}}"))) + .expect("Unable to create Bad Request due to missing required form parameter {{{paramName}}}")) } }; {{{paramName}}}_model @@ -294,11 +292,11 @@ }, None => { {{#required}} - return Box::new(future::ok( + return Ok( Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Missing required form parameter {{{paramName}}}"))) - .expect("Unable to create Bad Request due to missing required form parameter {{{paramName}}}"))) + .expect("Unable to create Bad Request due to missing required form parameter {{{paramName}}}")) {{/required}} {{^required}} None @@ -313,8 +311,6 @@ {{^consumesMultipart}} {{^bodyParams}} {{#vendorExtensions}} - Box::new({ - {{ {{#formParams}} {{#-first}} // Form parameters @@ -332,9 +328,8 @@ // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw(); + match result.await { Ok(body) => { let mut unused_elements: Vec = vec![]; @@ -354,10 +349,10 @@ multi_part_headers.set(ContentType(content_type_mime)); }, Err(e) => { - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(e)) - .expect("Unable to create Bad Request response due to unable to read content-type header for {{operationId}}"))); + .expect("Unable to create Bad Request response due to unable to read content-type header for {{operationId}}")); } } @@ -366,10 +361,10 @@ let nodes = match read_multipart_body(&mut&*body, &multi_part_headers, false) { Ok(nodes) => nodes, Err(e) => { - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Could not read multipart body for {{operationId}}: {}", e))) - .expect("Unable to create Bad Request response due to unable to read multipart body for {{operationId}}"))); + .expect("Unable to create Bad Request response due to unable to read multipart body for {{operationId}}")); } }; @@ -391,10 +386,10 @@ unused_elements.push(path.to_string()); }) { Ok(json_data) => json_data, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse body parameter {{dataType}} - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid body parameter {{dataType}} due to schema"))) + .expect("Unable to create Bad Request response for invalid body parameter {{dataType}} due to schema")) }; // Push JSON part to return object. param_{{{paramName}}}.get_or_insert(json_data); @@ -427,10 +422,10 @@ {{#required}} let param_{{{paramName}}} = match param_required_binary_field { Some(x) => x, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Missing required multipart/related parameter {{{paramName}}}"))) - .expect("Unable to create Bad Request response for missing multipart/related parameter {{{paramName}}} due to schema"))) + .expect("Unable to create Bad Request response for missing multipart/related parameter {{{paramName}}} due to schema")) }; {{/required}} {{#-last}} @@ -439,8 +434,7 @@ {{/formParams}} {{/consumesMultipartRelated}} {{/vendorExtensions}} - Box::new( - api_impl.{{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}( + let result = api_impl.{{#vendorExtensions}}{{{operation_id}}}{{/vendorExtensions}}( {{#vendorExtensions}} {{#callbackParams}} callback_{{.}}, @@ -450,9 +444,9 @@ param_{{{paramName}}}{{#isListContainer}}.as_ref(){{/isListContainer}}, {{/allParams}} &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -505,7 +499,7 @@ let {{{name}}} = match header::IntoHeaderValue({{{name}}}).try_into() { Ok(val) => val, Err(e) => { - return future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) .body(Body::from(format!("An internal server error occurred handling {{name}} header - {}", e))) .expect("Unable to create Internal Server Error for invalid response header")) @@ -569,26 +563,18 @@ }, } - future::ok(response) - } - )) + Ok(response) {{#vendorExtensions}} {{^consumesMultipart}} {{^bodyParams}} {{#vendorExtensions}} {{#consumesMultipartRelated}} }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter {{{baseName}}}: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter {{{baseName}}}"))), + .expect("Unable to create Bad Request response due to unable to read body parameter {{{baseName}}}")), } - }) - ) as Self::Future -{{/consumesMultipartRelated}} -{{^consumesMultipartRelated}} - }} - }) as Self::Future {{/consumesMultipartRelated}} {{/vendorExtensions}} {{/bodyParams}} @@ -597,28 +583,23 @@ {{#bodyParams}} {{#-first}} }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter {{{baseName}}}: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter {{{baseName}}}"))), + .expect("Unable to create Bad Request response due to unable to read body parameter {{{baseName}}}")), } - }) - ) as Self::Future {{/-first}} {{/bodyParams}} {{#vendorExtensions}} {{#consumesMultipart}} {{^bodyParams}} {{#vendorExtensions}} - as Self::Future }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read multipart body"))) - .expect("Unable to create Bad Request response due to unable read multipart body"))), + .expect("Unable to create Bad Request response due to unable read multipart body")), } - }) - ) {{/vendorExtensions}} {{/bodyParams}} {{/consumesMultipart}} diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-service-footer.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-service-footer.mustache index 568c8fb801d..25e9c12a5b3 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-service-footer.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-service-footer.mustache @@ -1,18 +1,6 @@ - _ => Box::new(future::ok( - Response::builder().status(StatusCode::NOT_FOUND) + _ => Ok(Response::builder().status(StatusCode::NOT_FOUND) .body(Body::empty()) - .expect("Unable to create Not Found response") - )) as Self::Future + .expect("Unable to create Not Found response")) } - } -} - -impl Clone for Service where T: Clone -{ - fn clone(&self) -> Self { - Service { - api_impl: self.api_impl.clone(), - marker: self.marker.clone(), - } - } + } Box::pin(run(self.api_impl.clone(), req)) } } diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-service-header.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-service-header.mustache index da785bbbfb4..76c0e9a8540 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-service-header.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-service-header.mustache @@ -1,22 +1,23 @@ -type ServiceFuture = Box, Error = Error> + Send>; - -fn method_not_allowed() -> ServiceFuture { - Box::new(future::ok( +fn method_not_allowed() -> Result, crate::ServiceError> { + Ok( Response::builder().status(StatusCode::METHOD_NOT_ALLOWED) .body(Body::empty()) .expect("Unable to create Method Not Allowed response") - )) + ) } -pub struct Service { +pub struct Service where + T: Api + Clone + Send + 'static, + C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync + 'static +{ api_impl: T, - marker: PhantomData, + marker: PhantomData, } -impl Service -where - T: Api + Clone + Send + 'static, - RC: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + 'static { +impl Service where + T: Api + Clone + Send + 'static, + C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync + 'static +{ pub fn new(api_impl: T) -> Self { Service { api_impl: api_impl, @@ -25,23 +26,38 @@ where } } -impl hyper::service::Service for Service -where +impl Clone for Service where T: Api + Clone + Send + 'static, - C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + 'static + Send + C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync + 'static { - type ReqBody = ContextualPayload; - type ResBody = Body; - type Error = Error; + fn clone(&self) -> Self { + Service { + api_impl: self.api_impl.clone(), + marker: self.marker.clone(), + } + } +} + +impl hyper::service::Service<(Request, C)> for Service where + T: Api + Clone + Send + Sync + 'static, + C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync + 'static +{ + type Response = Response; + type Error = crate::ServiceError; type Future = ServiceFuture; - fn call(&mut self, req: Request) -> Self::Future { - let api_impl = self.api_impl.clone(); - let (parts, body) = req.into_parts(); + fn poll_ready(&mut self, cx: &mut Context) -> Poll> { + self.api_impl.poll_ready(cx) + } + + fn call(&mut self, req: (Request, C)) -> Self::Future { async fn run(mut api_impl: T, req: (Request, C)) -> Result, crate::ServiceError> where + T: Api + Clone + Send + 'static, + C: Has {{#hasAuthMethods}}+ Has>{{/hasAuthMethods}} + Send + Sync + 'static + { + let (request, context) = req; + let (parts, body) = request.into_parts(); let (method, uri, headers) = (parts.method, parts.uri, parts.headers); let path = paths::GLOBAL_REGEX_SET.matches(uri.path()); - let mut context = body.context; - let body = body.inner; {{! This match statement is duplicated below in `parse_operation_id()`. diff --git a/samples/server/petstore/rust-server/output/multipart-v3/Cargo.toml b/samples/server/petstore/rust-server/output/multipart-v3/Cargo.toml index 2caa6327e8f..eaca5af92e2 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/Cargo.toml +++ b/samples/server/petstore/rust-server/output/multipart-v3/Cargo.toml @@ -12,7 +12,7 @@ client = [ "mime_0_2", "multipart", "multipart/client", "swagger/multipart", "hyper_0_10", "mime_multipart", - "hyper", "hyper-openssl", "native-tls", "openssl", "url" + "hyper", "hyper-openssl", "hyper-tls", "native-tls", "openssl", "url" ] server = [ "mime_0_2", @@ -24,20 +24,22 @@ conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk- [target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] native-tls = { version = "0.2", optional = true } +hyper-tls = { version = "0.4", optional = true } [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dependencies] -hyper-openssl = { version = "0.7.1", optional = true } +hyper-openssl = { version = "0.8", optional = true } openssl = {version = "0.10", optional = true } [dependencies] # Common +async-trait = "0.1.24" chrono = { version = "0.4", features = ["serde"] } -futures = "0.1" -swagger = "4.0" +futures = "0.3" +swagger = "5.0.0-alpha-1" log = "0.4.0" mime = "0.3" -serde = { version = "1.0", features = ["derive"]} +serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" # Crates included if required by the API definition @@ -45,18 +47,18 @@ mime_0_2 = { package = "mime", version = "0.2.6", optional = true } multipart = { version = "0.16", default-features = false, optional = true } # Common between server and client features -hyper = {version = "0.12", optional = true} +hyper = {version = "0.13", optional = true} mime_multipart = {version = "0.5", optional = true} hyper_0_10 = {package = "hyper", version = "0.10", default-features = false, optional=true} -serde_ignored = {version = "0.0.4", optional = true} -url = {version = "1.5", optional = true} +serde_ignored = {version = "0.1.1", optional = true} +url = {version = "2.1", optional = true} # Client-specific # Server, and client callback-specific lazy_static = { version = "1.4", optional = true } -percent-encoding = {version = "1.0.0", optional = true} -regex = {version = "0.2", optional = true} +percent-encoding = {version = "2.1.0", optional = true} +regex = {version = "1.3", optional = true} # Conversion frunk = { version = "0.3.0", optional = true } @@ -67,13 +69,13 @@ frunk-enum-core = { version = "0.2.0", optional = true } [dev-dependencies] clap = "2.25" -error-chain = "0.12" -env_logger = "0.6" -tokio = "0.1.17" -uuid = {version = "0.7", features = ["serde", "v4"]} +env_logger = "0.7" +tokio = { version = "0.2", features = ["rt-threaded", "macros", "stream"] } +native-tls = "0.2" +tokio-tls = "0.3" [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dev-dependencies] -tokio-openssl = "0.3" +tokio-openssl = "0.4" openssl = "0.10" [[example]] diff --git a/samples/server/petstore/rust-server/output/multipart-v3/examples/client/main.rs b/samples/server/petstore/rust-server/output/multipart-v3/examples/client/main.rs index b6ac0eea5f1..2723cbfc98d 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/examples/client/main.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/examples/client/main.rs @@ -2,13 +2,12 @@ #[allow(unused_imports)] -use futures::{Future, future, Stream, stream}; +use futures::{future, Stream, stream}; #[allow(unused_imports)] use multipart_v3::{Api, ApiNoContext, Client, ContextWrapperExt, models, - ApiError, MultipartRelatedRequestPostResponse, MultipartRequestPostResponse, - MultipleIdenticalMimeTypesPostResponse + MultipleIdenticalMimeTypesPostResponse, }; use clap::{App, Arg}; @@ -17,7 +16,9 @@ use log::info; // swagger::Has may be unused if there are no examples #[allow(unused_imports)] -use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData}; +use swagger::{AuthData, ContextBuilder, EmptyContext, Has, Push, XSpanIdString}; + +type ClientContext = swagger::make_context_ty!(ContextBuilder, EmptyContext, Option, XSpanIdString); // rt may be unused if there are no examples #[allow(unused_mut)] @@ -55,21 +56,21 @@ fn main() { matches.value_of("host").unwrap(), matches.value_of("port").unwrap()); - let client = if matches.is_present("https") { - // Using Simple HTTPS - Client::try_new_https(&base_url) - .expect("Failed to create HTTPS client") - } else { - // Using HTTP - Client::try_new_http( - &base_url) - .expect("Failed to create HTTP client") - }; - - let context: swagger::make_context_ty!(ContextBuilder, EmptyContext, Option, XSpanIdString) = + let context: ClientContext = swagger::make_context!(ContextBuilder, EmptyContext, None as Option, XSpanIdString::default()); - let client = client.with_context(context); + let mut client : Box> = if matches.is_present("https") { + // Using Simple HTTPS + let client = Box::new(Client::try_new_https(&base_url) + .expect("Failed to create HTTPS client")); + Box::new(client.with_context(context)) + } else { + // Using HTTP + let client = Box::new(Client::try_new_http( + &base_url) + .expect("Failed to create HTTP client")); + Box::new(client.with_context(context)) + }; let mut rt = tokio::runtime::Runtime::new().unwrap(); diff --git a/samples/server/petstore/rust-server/output/multipart-v3/examples/server/main.rs b/samples/server/petstore/rust-server/output/multipart-v3/examples/server/main.rs index 02fc2a751b0..834961ce82e 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/examples/server/main.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/examples/server/main.rs @@ -9,7 +9,8 @@ mod server; /// Create custom server, wire it to the autogenerated router, /// and pass it to the web server. -fn main() { +#[tokio::main] +async fn main() { env_logger::init(); let matches = App::new("server") @@ -20,5 +21,5 @@ fn main() { let addr = "127.0.0.1:8080"; - hyper::rt::run(server::create(addr, matches.is_present("https"))); + server::create(addr, matches.is_present("https")).await; } diff --git a/samples/server/petstore/rust-server/output/multipart-v3/examples/server/server.rs b/samples/server/petstore/rust-server/output/multipart-v3/examples/server/server.rs index 4c6938ce12c..b8977da45a3 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/examples/server/server.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/examples/server/server.rs @@ -2,30 +2,22 @@ #![allow(unused_imports)] -mod errors { - error_chain::error_chain!{} -} - -pub use self::errors::*; - -use chrono; -use futures::{future, Future, Stream}; +use async_trait::async_trait; +use futures::{future, Stream, StreamExt, TryFutureExt, TryStreamExt}; use hyper::server::conn::Http; -use hyper::service::MakeService as _; +use hyper::service::Service; use log::info; use openssl::ssl::SslAcceptorBuilder; +use std::future::Future; use std::marker::PhantomData; use std::net::SocketAddr; use std::sync::{Arc, Mutex}; -use swagger; +use std::task::{Context, Poll}; use swagger::{Has, XSpanIdString}; use swagger::auth::MakeAllowAllAuthenticator; use swagger::EmptyContext; use tokio::net::TcpListener; - -#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] -use tokio_openssl::SslAcceptorExt; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; @@ -33,18 +25,18 @@ use multipart_v3::models; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] /// Builds an SSL implementation for Simple HTTPS from some hard-coded file names -pub fn create(addr: &str, https: bool) -> Box + Send> { +pub async fn create(addr: &str, https: bool) { let addr = addr.parse().expect("Failed to parse bind address"); let server = Server::new(); - let service_fn = MakeService::new(server); + let service = MakeService::new(server); - let service_fn = MakeAllowAllAuthenticator::new(service_fn, "cosmo"); + let service = MakeAllowAllAuthenticator::new(service, "cosmo"); - let service_fn = + let mut service = multipart_v3::server::context::MakeAddContext::<_, EmptyContext>::new( - service_fn + service ); if https { @@ -62,32 +54,31 @@ pub fn create(addr: &str, https: bool) -> Box ssl.set_certificate_chain_file("examples/server-chain.pem").expect("Failed to set cerificate chain"); ssl.check_private_key().expect("Failed to check private key"); - let tls_acceptor = ssl.build(); - let service_fn = Arc::new(Mutex::new(service_fn)); - let tls_listener = TcpListener::bind(&addr).unwrap().incoming().for_each(move |tcp| { - let addr = tcp.peer_addr().expect("Unable to get remote address"); + let tls_acceptor = Arc::new(ssl.build()); + let mut tcp_listener = TcpListener::bind(&addr).await.unwrap(); + let mut incoming = tcp_listener.incoming(); - let service_fn = service_fn.clone(); + while let (Some(tcp), rest) = incoming.into_future().await { + if let Ok(tcp) = tcp { + let addr = tcp.peer_addr().expect("Unable to get remote address"); + let service = service.call(addr); + let tls_acceptor = Arc::clone(&tls_acceptor); - hyper::rt::spawn(tls_acceptor.accept_async(tcp).map_err(|_| ()).and_then(move |tls| { - let ms = { - let mut service_fn = service_fn.lock().unwrap(); - service_fn.make_service(&addr) - }; + tokio::spawn(async move { + let tls = tokio_openssl::accept(&*tls_acceptor, tcp).await.map_err(|_| ())?; - ms.and_then(move |service| { - Http::new().serve_connection(tls, service) - }).map_err(|_| ()) - })); + let service = service.await.map_err(|_| ())?; - Ok(()) - }).map_err(|_| ()); + Http::new().serve_connection(tls, service).await.map_err(|_| ()) + }); + } - Box::new(tls_listener) + incoming = rest; + } } } else { // Using HTTP - Box::new(hyper::server::Server::bind(&addr).serve(service_fn).map_err(|e| panic!("{:?}", e))) + hyper::server::Server::bind(&addr).serve(service).await.unwrap() } } @@ -105,48 +96,51 @@ impl Server { use multipart_v3::{ Api, - ApiError, MultipartRelatedRequestPostResponse, MultipartRequestPostResponse, MultipleIdenticalMimeTypesPostResponse, }; use multipart_v3::server::MakeService; +use std::error::Error; +use swagger::ApiError; -impl Api for Server where C: Has{ - fn multipart_related_request_post( +#[async_trait] +impl Api for Server where C: Has + Send + Sync +{ + async fn multipart_related_request_post( &self, required_binary_field: swagger::ByteArray, object_field: Option, optional_binary_field: Option, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("multipart_related_request_post({:?}, {:?}, {:?}) - X-Span-ID: {:?}", required_binary_field, object_field, optional_binary_field, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn multipart_request_post( + async fn multipart_request_post( &self, string_field: String, binary_field: swagger::ByteArray, optional_string_field: Option, object_field: Option, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("multipart_request_post(\"{}\", {:?}, {:?}, {:?}) - X-Span-ID: {:?}", string_field, binary_field, optional_string_field, object_field, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn multiple_identical_mime_types_post( + async fn multiple_identical_mime_types_post( &self, binary1: Option, binary2: Option, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("multiple_identical_mime_types_post({:?}, {:?}) - X-Span-ID: {:?}", binary1, binary2, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } } diff --git a/samples/server/petstore/rust-server/output/multipart-v3/src/client/mod.rs b/samples/server/petstore/rust-server/output/multipart-v3/src/client/mod.rs index ed3ab5d92b7..44319896f1e 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/src/client/mod.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/src/client/mod.rs @@ -1,26 +1,23 @@ -use futures; -use futures::{Future, Stream, future, stream}; -use hyper; -use hyper::client::HttpConnector; +use async_trait::async_trait; +use futures::{Stream, future, future::BoxFuture, stream, future::TryFutureExt, future::FutureExt, stream::StreamExt}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; -use hyper::{Body, Uri, Response}; -#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] -use hyper_openssl::HttpsConnector; -use serde_json; +use hyper::{Body, Request, Response, service::Service, Uri}; +use percent_encoding::{utf8_percent_encode, AsciiSet}; use std::borrow::Cow; use std::convert::TryInto; -use std::io::{Read, Error, ErrorKind}; -use std::error; +use std::io::{ErrorKind, Read}; +use std::error::Error; +use std::future::Future; use std::fmt; use std::path::Path; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use std::str; use std::str::FromStr; use std::string::ToString; -use swagger; -use swagger::{ApiError, Connector, client::Service, XSpanIdString, Has, AuthData}; +use std::task::{Context, Poll}; +use swagger::{ApiError, AuthData, BodyExt, Connector, Has, XSpanIdString}; use url::form_urlencoded; -use url::percent_encoding::{utf8_percent_encode, PATH_SEGMENT_ENCODE_SET, QUERY_ENCODE_SET}; + use mime::Mime; use std::io::Cursor; use multipart::client::lazy::Multipart; @@ -30,13 +27,17 @@ use mime_multipart::{Node, Part, generate_boundary, write_multipart}; use crate::models; use crate::header; -url::define_encode_set! { - /// This encode set is used for object IDs - /// - /// Aside from the special characters defined in the `PATH_SEGMENT_ENCODE_SET`, - /// the vertical bar (|) is encoded. - pub ID_ENCODE_SET = [PATH_SEGMENT_ENCODE_SET] | {'|'} -} +/// https://url.spec.whatwg.org/#fragment-percent-encode-set +#[allow(dead_code)] +const FRAGMENT_ENCODE_SET: &AsciiSet = &percent_encoding::CONTROLS + .add(b' ').add(b'"').add(b'<').add(b'>').add(b'`'); + +/// This encode set is used for object IDs +/// +/// Aside from the special characters defined in the `PATH_SEGMENT_ENCODE_SET`, +/// the vertical bar (|) is encoded. +#[allow(dead_code)] +const ID_ENCODE_SET: &AsciiSet = &FRAGMENT_ENCODE_SET.add(b'|'); use crate::{Api, MultipartRelatedRequestPostResponse, @@ -45,11 +46,11 @@ use crate::{Api, }; /// Convert input into a base path, e.g. "http://example:123". Also checks the scheme as it goes. -fn into_base_path(input: &str, correct_scheme: Option<&'static str>) -> Result { +fn into_base_path(input: impl TryInto, correct_scheme: Option<&'static str>) -> Result { // First convert to Uri, since a base path is a subset of Uri. - let uri = Uri::from_str(input)?; + let uri = input.try_into()?; - let scheme = uri.scheme_part().ok_or(ClientInitError::InvalidScheme)?; + let scheme = uri.scheme_str().ok_or(ClientInitError::InvalidScheme)?; // Check the scheme if necessary if let Some(correct_scheme) = correct_scheme { @@ -59,38 +60,54 @@ fn into_base_path(input: &str, correct_scheme: Option<&'static str>) -> Result +pub struct Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { /// Inner service - client_service: Arc + Send + Sync>>, + client_service: S, /// Base path of the API base_path: String, } -impl fmt::Debug for Client +impl fmt::Debug for Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Client {{ base_path: {} }}", self.base_path) } } -impl Clone for Client +impl Clone for Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { fn clone(&self) -> Self { - Client { + Self { client_service: self.client_service.clone(), base_path: self.base_path.clone(), } } } -impl Client +impl Client> where + C: hyper::client::connect::Connect + Clone + Send + Sync + 'static { /// Create a client with a custom implementation of hyper::client::Connect. /// @@ -103,30 +120,93 @@ impl Client /// /// # Arguments /// - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "http://www.my-api-implementation.com" /// * `protocol` - Which protocol to use when constructing the request url, e.g. `Some("http")` /// * `connector` - Implementation of `hyper::client::Connect` to use for the client - pub fn try_new_with_connector( + pub fn try_new_with_connector( base_path: &str, protocol: Option<&'static str>, connector: C, - ) -> Result where - C: hyper::client::connect::Connect + 'static, - C::Transport: 'static, - C::Future: 'static, + ) -> Result { - let client_service = Box::new(hyper::client::Client::builder().build(connector)); + let client_service = hyper::client::Client::builder().build(connector); - Ok(Client { - client_service: Arc::new(client_service), + Ok(Self { + client_service, base_path: into_base_path(base_path, protocol)?, }) } +} +#[derive(Debug, Clone)] +pub enum HyperClient { + Http(hyper::client::Client), + Https(hyper::client::Client), +} + +impl Service> for HyperClient { + type Response = Response; + type Error = hyper::Error; + type Future = hyper::client::ResponseFuture; + + fn poll_ready(&mut self, cx: &mut Context) -> Poll> { + match self { + HyperClient::Http(client) => client.poll_ready(cx), + HyperClient::Https(client) => client.poll_ready(cx), + } + } + + fn call(&mut self, req: Request) -> Self::Future { + match self { + HyperClient::Http(client) => client.call(req), + HyperClient::Https(client) => client.call(req) + } + } +} + +impl Client { /// Create an HTTP client. /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "http://www.my-api-implementation.com" + pub fn try_new( + base_path: &str, + ) -> Result { + let uri = Uri::from_str(base_path)?; + + let scheme = uri.scheme_str().ok_or(ClientInitError::InvalidScheme)?; + let scheme = scheme.to_ascii_lowercase(); + + let connector = Connector::builder(); + + let client_service = match scheme.as_str() { + "http" => { + HyperClient::Http(hyper::client::Client::builder().build(connector.build())) + }, + "https" => { + let connector = connector.https() + .build() + .map_err(|e| ClientInitError::SslError(e))?; + HyperClient::Https(hyper::client::Client::builder().build(connector)) + }, + _ => { + return Err(ClientInitError::InvalidScheme); + } + }; + + Ok(Self { + client_service, + base_path: into_base_path(base_path, None)?, + }) + } +} + +impl Client> +{ + /// Create an HTTP client. + /// + /// # Arguments + /// * `base_path` - base path of the client API, i.e. "http://www.my-api-implementation.com" pub fn try_new_http( base_path: &str, ) -> Result { @@ -134,11 +214,20 @@ impl Client Self::try_new_with_connector(base_path, Some("http"), http_connector) } +} +#[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] +type HttpsConnector = hyper_tls::HttpsConnector; + +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +type HttpsConnector = hyper_openssl::HttpsConnector; + +impl Client> +{ /// Create a client with a TLS connection to the server /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "https://www.my-api-implementation.com" pub fn try_new_https(base_path: &str) -> Result { let https_connector = Connector::builder() @@ -151,7 +240,7 @@ impl Client /// Create a client with a TLS connection to the server using a pinned certificate /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "https://www.my-api-implementation.com" /// * `ca_certificate` - Path to CA certificate used to authenticate the server #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] pub fn try_new_https_pinned( @@ -172,7 +261,7 @@ impl Client /// Create a client with a mutually authenticated TLS connection to the server. /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "https://www.my-api-implementation.com" /// * `ca_certificate` - Path to CA certificate used to authenticate the server /// * `client_key` - Path to the client private key /// * `client_certificate` - Path to the client's public certificate associated with the private key @@ -198,17 +287,24 @@ impl Client } } -impl Client +impl Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { - /// Constructor for creating a `Client` by passing in a pre-made `swagger::Service` + /// Constructor for creating a `Client` by passing in a pre-made `hyper::service::Service` / + /// `tower::Service` /// /// This allows adding custom wrappers around the underlying transport, for example for logging. pub fn try_new_with_client_service( - client_service: Arc + Send + Sync>>, + client_service: S, base_path: &str, - ) -> Result { - Ok(Client { - client_service: client_service, + ) -> Result + { + Ok(Self { + client_service, base_path: into_base_path(base_path, None)?, }) } @@ -248,47 +344,63 @@ impl fmt::Display for ClientInitError { } } -impl error::Error for ClientInitError { +impl Error for ClientInitError { fn description(&self) -> &str { "Failed to produce a hyper client." } } -impl Api for Client where - C: Has , - F: Future, Error=hyper::Error> + Send + 'static +#[async_trait] +impl Api for Client where + C: Has + Clone + Send + Sync + 'static, + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { - fn multipart_related_request_post( + fn poll_ready(&self, cx: &mut Context) -> Poll> { + match self.client_service.clone().poll_ready(cx) { + Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())), + Poll::Ready(Ok(o)) => Poll::Ready(Ok(o)), + Poll::Pending => Poll::Pending, + } + } + + async fn multipart_related_request_post( &self, param_required_binary_field: swagger::ByteArray, param_object_field: Option, param_optional_binary_field: Option, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/multipart_related_request", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; // Construct the Body for a multipart/related request. The mime 0.2.6 library @@ -359,229 +471,230 @@ impl Api for Client where &[header.as_bytes(), "; boundary=".as_bytes(), &boundary, "; type=\"application/json\"".as_bytes()].concat() ) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 201 => { - let body = response.into_body(); - Box::new( - future::ok( - MultipartRelatedRequestPostResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 201 => { + let body = response.into_body(); + Ok( + MultipartRelatedRequestPostResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn multipart_request_post( + async fn multipart_request_post( &self, param_string_field: String, param_binary_field: swagger::ByteArray, param_optional_string_field: Option, param_object_field: Option, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/multipart_request", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let mut multipart = Multipart::new(); + let (body_string, multipart_header) = { + let mut multipart = Multipart::new(); - // For each parameter, encode as appropriate and add to the multipart body as a stream. + // For each parameter, encode as appropriate and add to the multipart body as a stream. - let string_field_str = match serde_json::to_string(¶m_string_field) { - Ok(str) => str, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to parse string_field to string: {}", e)))), + let string_field_str = match serde_json::to_string(¶m_string_field) { + Ok(str) => str, + Err(e) => return Err(ApiError(format!("Unable to parse string_field to string: {}", e))), + }; + + let string_field_vec = string_field_str.as_bytes().to_vec(); + let string_field_mime = mime_0_2::Mime::from_str("application/json").expect("impossible to fail to parse"); + let string_field_cursor = Cursor::new(string_field_vec); + + multipart.add_stream("string_field", string_field_cursor, None as Option<&str>, Some(string_field_mime)); + + + let optional_string_field_str = match serde_json::to_string(¶m_optional_string_field) { + Ok(str) => str, + Err(e) => return Err(ApiError(format!("Unable to parse optional_string_field to string: {}", e))), + }; + + let optional_string_field_vec = optional_string_field_str.as_bytes().to_vec(); + let optional_string_field_mime = mime_0_2::Mime::from_str("application/json").expect("impossible to fail to parse"); + let optional_string_field_cursor = Cursor::new(optional_string_field_vec); + + multipart.add_stream("optional_string_field", optional_string_field_cursor, None as Option<&str>, Some(optional_string_field_mime)); + + + let object_field_str = match serde_json::to_string(¶m_object_field) { + Ok(str) => str, + Err(e) => return Err(ApiError(format!("Unable to parse object_field to string: {}", e))), + }; + + let object_field_vec = object_field_str.as_bytes().to_vec(); + let object_field_mime = mime_0_2::Mime::from_str("application/json").expect("impossible to fail to parse"); + let object_field_cursor = Cursor::new(object_field_vec); + + multipart.add_stream("object_field", object_field_cursor, None as Option<&str>, Some(object_field_mime)); + + + + let binary_field_vec = param_binary_field.to_vec(); + + let binary_field_mime = match mime_0_2::Mime::from_str("application/octet-stream") { + Ok(mime) => mime, + Err(err) => return Err(ApiError(format!("Unable to get mime type: {:?}", err))), + }; + + let binary_field_cursor = Cursor::new(binary_field_vec); + + let filename = None as Option<&str> ; + multipart.add_stream("binary_field", binary_field_cursor, filename, Some(binary_field_mime)); + + let mut fields = match multipart.prepare() { + Ok(fields) => fields, + Err(err) => return Err(ApiError(format!("Unable to build request: {}", err))), + }; + + let mut body_string = String::new(); + + match fields.read_to_string(&mut body_string) { + Ok(_) => (), + Err(err) => return Err(ApiError(format!("Unable to build body: {}", err))), + } + + let boundary = fields.boundary(); + + let multipart_header = format!("multipart/form-data;boundary={}", boundary); + + (body_string, multipart_header) }; - let string_field_vec = string_field_str.as_bytes().to_vec(); - - let string_field_mime = mime_0_2::Mime::from_str("application/json").expect("impossible to fail to parse"); - - let string_field_cursor = Cursor::new(string_field_vec); - - multipart.add_stream("string_field", string_field_cursor, None as Option<&str>, Some(string_field_mime)); - - let optional_string_field_str = match serde_json::to_string(¶m_optional_string_field) { - Ok(str) => str, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to parse optional_string_field to string: {}", e)))), - }; - - let optional_string_field_vec = optional_string_field_str.as_bytes().to_vec(); - - let optional_string_field_mime = mime_0_2::Mime::from_str("application/json").expect("impossible to fail to parse"); - - let optional_string_field_cursor = Cursor::new(optional_string_field_vec); - - multipart.add_stream("optional_string_field", optional_string_field_cursor, None as Option<&str>, Some(optional_string_field_mime)); - - let object_field_str = match serde_json::to_string(¶m_object_field) { - Ok(str) => str, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to parse object_field to string: {}", e)))), - }; - - let object_field_vec = object_field_str.as_bytes().to_vec(); - - let object_field_mime = mime_0_2::Mime::from_str("application/json").expect("impossible to fail to parse"); - - let object_field_cursor = Cursor::new(object_field_vec); - - multipart.add_stream("object_field", object_field_cursor, None as Option<&str>, Some(object_field_mime)); - - let binary_field_vec = param_binary_field.to_vec(); - - let binary_field_mime = match mime_0_2::Mime::from_str("application/octet-stream") { - Ok(mime) => mime, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to get mime type: {:?}", err)))), - }; - - let binary_field_cursor = Cursor::new(binary_field_vec); - - let filename = None as Option<&str> ; - multipart.add_stream("binary_field", binary_field_cursor, filename, Some(binary_field_mime)); - let mut fields = match multipart.prepare() { - Ok(fields) => fields, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build request: {}", err)))), - }; - - let mut body_string = String::new(); - match fields.read_to_string(&mut body_string) { - Ok(_) => (), - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build body: {}", err)))), - } - let boundary = fields.boundary(); - - let multipart_header = format!("multipart/form-data;boundary={}", boundary); - *request.body_mut() = Body::from(body_string); request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(&multipart_header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", multipart_header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", multipart_header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 201 => { - let body = response.into_body(); - Box::new( - future::ok( - MultipartRequestPostResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 201 => { + let body = response.into_body(); + Ok( + MultipartRequestPostResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn multiple_identical_mime_types_post( + async fn multiple_identical_mime_types_post( &self, param_binary1: Option, param_binary2: Option, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/multiple-identical-mime-types", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; // Construct the Body for a multipart/related request. The mime 0.2.6 library @@ -637,48 +750,43 @@ impl Api for Client where &[header.as_bytes(), "; boundary=".as_bytes(), &boundary, "; type=\"application/json\"".as_bytes()].concat() ) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - MultipleIdenticalMimeTypesPostResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + MultipleIdenticalMimeTypesPostResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } } diff --git a/samples/server/petstore/rust-server/output/multipart-v3/src/context.rs b/samples/server/petstore/rust-server/output/multipart-v3/src/context.rs index d14e73f822d..fadd880b965 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/src/context.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/src/context.rs @@ -1,13 +1,12 @@ -use futures::Future; -use hyper; +use futures::future::BoxFuture; use hyper::header::HeaderName; -use hyper::{Error, Request, Response, StatusCode, service::Service, body::Payload}; +use hyper::{Error, Request, Response, StatusCode, service::Service}; use url::form_urlencoded; use std::default::Default; use std::io; use std::marker::PhantomData; +use std::task::{Poll, Context}; use swagger::auth::{AuthData, Authorization, Bearer, Scopes}; -use swagger::context::ContextualPayload; use swagger::{EmptyContext, Has, Pop, Push, XSpanIdString}; use crate::Api; @@ -31,58 +30,52 @@ where } // Make a service that adds context. -impl<'a, T, SC, A, B, C, D, E, ME, S, OB, F> hyper::service::MakeService<&'a SC> for +impl Service for MakeAddContext where - A: Default + Push, + Target: Send, + A: Default + Push + Send, B: Push, Result = C>, C: Push, Result = D>, D: Send + 'static, - T: hyper::service::MakeService< - &'a SC, - Error = E, - MakeError = ME, - Service = S, - ReqBody = ContextualPayload, - ResBody = OB, - Future = F - >, - S: Service< - Error = E, - ReqBody = ContextualPayload, - ResBody = OB> + 'static, - ME: swagger::ErrorBound, - E: swagger::ErrorBound, - F: Future + Send + 'static, - S::Future: Send, - OB: Payload, + T: Service + Send, + T::Future: Send + 'static { - type ReqBody = hyper::Body; - type ResBody = OB; - type Error = E; - type MakeError = ME; - type Service = AddContext; - type Future = Box + Send + 'static>; + type Error = T::Error; + type Response = AddContext; + type Future = BoxFuture<'static, Result>; - fn make_service(&mut self, ctx: &'a SC) -> Self::Future { - Box::new(self.inner.make_service(ctx).map(|s| AddContext::new(s))) + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + self.inner.poll_ready(cx) + } + + fn call(&mut self, target: Target) -> Self::Future { + let service = self.inner.call(target); + + Box::pin(async move { + Ok(AddContext::new(service.await?)) + }) } } -/// Middleware to extract authentication data from request -pub struct AddContext { +/// Middleware to add context data from the request +pub struct AddContext +where + A: Default + Push, + B: Push, Result = C>, + C: Push, Result = D> +{ inner: T, marker: PhantomData, } -impl AddContext +impl AddContext where A: Default + Push, B: Push, Result = C>, C: Push, Result = D>, - T: Service, { - pub fn new(inner: T) -> AddContext { + pub fn new(inner: T) -> Self { AddContext { inner, marker: PhantomData, @@ -90,33 +83,31 @@ where } } -impl Service for AddContext +impl Service> for AddContext where A: Default + Push, B: Push, Result=C>, C: Push, Result=D>, D: Send + 'static, - T: Service>, - T::Future: Future, Error=T::Error> + Send + 'static + T: Service<(Request, D)> { - type ReqBody = hyper::Body; - type ResBody = T::ResBody; type Error = T::Error; - type Future = Box, Error=T::Error> + Send + 'static>; + type Future = T::Future; + type Response = T::Response; - fn call(&mut self, req: Request) -> Self::Future { - let context = A::default().push(XSpanIdString::get_or_generate(&req)); - let (head, body) = req.into_parts(); - let headers = head.headers.clone(); + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + self.inner.poll_ready(cx) + } + + + fn call(&mut self, request: Request) -> Self::Future { + let context = A::default().push(XSpanIdString::get_or_generate(&request)); + let headers = request.headers(); let context = context.push(None::); let context = context.push(None::); - let body = ContextualPayload { - inner: body, - context: context, - }; - Box::new(self.inner.call(hyper::Request::from_parts(head, body))) + self.inner.call((request, context)) } } diff --git a/samples/server/petstore/rust-server/output/multipart-v3/src/lib.rs b/samples/server/petstore/rust-server/output/multipart-v3/src/lib.rs index b1ab43ac849..2415ea2ce4e 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/src/lib.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/src/lib.rs @@ -1,12 +1,12 @@ #![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)] +use async_trait::async_trait; use futures::Stream; -use std::io::Error; +use std::error::Error; +use std::task::{Poll, Context}; +use swagger::{ApiError, ContextWrapper}; -#[deprecated(note = "Import swagger-rs directly")] -pub use swagger::{ApiError, ContextWrapper}; -#[deprecated(note = "Import futures directly")] -pub use futures::Future; +type ServiceError = Box; pub const BASE_PATH: &'static str = ""; pub const API_VERSION: &'static str = "1.0.7"; @@ -30,100 +30,125 @@ pub enum MultipleIdenticalMimeTypesPostResponse { } /// API -pub trait Api { - fn multipart_related_request_post( +#[async_trait] +pub trait Api { + fn poll_ready(&self, _cx: &mut Context) -> Poll>> { + Poll::Ready(Ok(())) + } + + async fn multipart_related_request_post( &self, required_binary_field: swagger::ByteArray, object_field: Option, optional_binary_field: Option, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn multipart_request_post( + async fn multipart_request_post( &self, string_field: String, binary_field: swagger::ByteArray, optional_string_field: Option, object_field: Option, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn multiple_identical_mime_types_post( + async fn multiple_identical_mime_types_post( &self, binary1: Option, binary2: Option, - context: &C) -> Box + Send>; + context: &C) -> Result; } -/// API without a `Context` -pub trait ApiNoContext { - fn multipart_related_request_post( +/// API where `Context` isn't passed on every API call +#[async_trait] +pub trait ApiNoContext { + + fn poll_ready(&self, _cx: &mut Context) -> Poll>>; + + fn context(&self) -> &C; + + async fn multipart_related_request_post( &self, required_binary_field: swagger::ByteArray, object_field: Option, optional_binary_field: Option, - ) -> Box + Send>; + ) -> Result; - fn multipart_request_post( + async fn multipart_request_post( &self, string_field: String, binary_field: swagger::ByteArray, optional_string_field: Option, object_field: Option, - ) -> Box + Send>; + ) -> Result; - fn multiple_identical_mime_types_post( + async fn multiple_identical_mime_types_post( &self, binary1: Option, binary2: Option, - ) -> Box + Send>; + ) -> Result; } /// Trait to extend an API to make it easy to bind it to a context. -pub trait ContextWrapperExt<'a, C> where Self: Sized { +pub trait ContextWrapperExt where Self: Sized +{ /// Binds this API to a context. - fn with_context(self: &'a Self, context: C) -> ContextWrapper<'a, Self, C>; + fn with_context(self: Self, context: C) -> ContextWrapper; } -impl<'a, T: Api + Sized, C> ContextWrapperExt<'a, C> for T { - fn with_context(self: &'a T, context: C) -> ContextWrapper<'a, T, C> { +impl + Send + Sync, C: Clone + Send + Sync> ContextWrapperExt for T { + fn with_context(self: T, context: C) -> ContextWrapper { ContextWrapper::::new(self, context) } } -impl<'a, T: Api, C> ApiNoContext for ContextWrapper<'a, T, C> { - fn multipart_related_request_post( +#[async_trait] +impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for ContextWrapper { + fn poll_ready(&self, cx: &mut Context) -> Poll> { + self.api().poll_ready(cx) + } + + fn context(&self) -> &C { + ContextWrapper::context(self) + } + + async fn multipart_related_request_post( &self, required_binary_field: swagger::ByteArray, object_field: Option, optional_binary_field: Option, - ) -> Box + Send> + ) -> Result { - self.api().multipart_related_request_post(required_binary_field, object_field, optional_binary_field, &self.context()) + let context = self.context().clone(); + self.api().multipart_related_request_post(required_binary_field, object_field, optional_binary_field, &context).await } - fn multipart_request_post( + async fn multipart_request_post( &self, string_field: String, binary_field: swagger::ByteArray, optional_string_field: Option, object_field: Option, - ) -> Box + Send> + ) -> Result { - self.api().multipart_request_post(string_field, binary_field, optional_string_field, object_field, &self.context()) + let context = self.context().clone(); + self.api().multipart_request_post(string_field, binary_field, optional_string_field, object_field, &context).await } - fn multiple_identical_mime_types_post( + async fn multiple_identical_mime_types_post( &self, binary1: Option, binary2: Option, - ) -> Box + Send> + ) -> Result { - self.api().multiple_identical_mime_types_post(binary1, binary2, &self.context()) + let context = self.context().clone(); + self.api().multiple_identical_mime_types_post(binary1, binary2, &context).await } } + #[cfg(feature = "client")] pub mod client; diff --git a/samples/server/petstore/rust-server/output/multipart-v3/src/server/mod.rs b/samples/server/petstore/rust-server/output/multipart-v3/src/server/mod.rs index eb870f1833e..72cf6b4f20e 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/src/server/mod.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/src/server/mod.rs @@ -1,20 +1,17 @@ -use std::marker::PhantomData; -use futures::{Future, future, Stream, stream}; -use hyper; -use hyper::{Request, Response, Error, StatusCode, Body, HeaderMap}; +use futures::{future, future::BoxFuture, Stream, stream, future::FutureExt, stream::TryStreamExt}; +use hyper::{Request, Response, StatusCode, Body, HeaderMap}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; use log::warn; -use serde_json; #[allow(unused_imports)] use std::convert::{TryFrom, TryInto}; -use std::io; -use url::form_urlencoded; -#[allow(unused_imports)] -use swagger; -use swagger::{ApiError, XSpanIdString, Has, RequestParser}; +use std::error::Error; +use std::future::Future; +use std::marker::PhantomData; +use std::task::{Context, Poll}; +use swagger::{ApiError, BodyExt, Has, RequestParser, XSpanIdString}; pub use swagger::auth::Authorization; use swagger::auth::Scopes; -use swagger::context::ContextualPayload; +use url::form_urlencoded; use hyper_0_10::header::{Headers, ContentType}; use mime_0_2::{TopLevel, SubLevel, Mime as Mime2}; use mime_multipart::{read_multipart_body, Node, Part}; @@ -27,6 +24,8 @@ use crate::header; pub use crate::context; +type ServiceFuture = BoxFuture<'static, Result, crate::ServiceError>>; + use crate::{Api, MultipartRelatedRequestPostResponse, MultipartRequestPostResponse, @@ -49,15 +48,17 @@ mod paths { pub(crate) static ID_MULTIPLE_IDENTICAL_MIME_TYPES: usize = 2; } -pub struct MakeService { +pub struct MakeService where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static +{ api_impl: T, - marker: PhantomData, + marker: PhantomData, } -impl MakeService -where - T: Api + Clone + Send + 'static, - RC: Has + 'static +impl MakeService where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static { pub fn new(api_impl: T) -> Self { MakeService { @@ -67,44 +68,45 @@ where } } -impl<'a, T, SC, RC> hyper::service::MakeService<&'a SC> for MakeService -where - T: Api + Clone + Send + 'static, - RC: Has + 'static + Send +impl hyper::service::Service for MakeService where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static { - type ReqBody = ContextualPayload; - type ResBody = Body; - type Error = Error; - type Service = Service; - type Future = future::FutureResult; - type MakeError = Error; + type Response = Service; + type Error = crate::ServiceError; + type Future = future::Ready>; - fn make_service(&mut self, _ctx: &'a SC) -> Self::Future { - future::FutureResult::from(Ok(Service::new( + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn call(&mut self, target: Target) -> Self::Future { + futures::future::ok(Service::new( self.api_impl.clone(), - ))) + )) } } -type ServiceFuture = Box, Error = Error> + Send>; - -fn method_not_allowed() -> ServiceFuture { - Box::new(future::ok( +fn method_not_allowed() -> Result, crate::ServiceError> { + Ok( Response::builder().status(StatusCode::METHOD_NOT_ALLOWED) .body(Body::empty()) .expect("Unable to create Method Not Allowed response") - )) + ) } -pub struct Service { +pub struct Service where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static +{ api_impl: T, - marker: PhantomData, + marker: PhantomData, } -impl Service -where - T: Api + Clone + Send + 'static, - RC: Has + 'static { +impl Service where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static +{ pub fn new(api_impl: T) -> Self { Service { api_impl: api_impl, @@ -113,23 +115,38 @@ where } } -impl hyper::service::Service for Service -where +impl Clone for Service where T: Api + Clone + Send + 'static, - C: Has + 'static + Send + C: Has + Send + Sync + 'static { - type ReqBody = ContextualPayload; - type ResBody = Body; - type Error = Error; + fn clone(&self) -> Self { + Service { + api_impl: self.api_impl.clone(), + marker: self.marker.clone(), + } + } +} + +impl hyper::service::Service<(Request, C)> for Service where + T: Api + Clone + Send + Sync + 'static, + C: Has + Send + Sync + 'static +{ + type Response = Response; + type Error = crate::ServiceError; type Future = ServiceFuture; - fn call(&mut self, req: Request) -> Self::Future { - let api_impl = self.api_impl.clone(); - let (parts, body) = req.into_parts(); + fn poll_ready(&mut self, cx: &mut Context) -> Poll> { + self.api_impl.poll_ready(cx) + } + + fn call(&mut self, req: (Request, C)) -> Self::Future { async fn run(mut api_impl: T, req: (Request, C)) -> Result, crate::ServiceError> where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static + { + let (request, context) = req; + let (parts, body) = request.into_parts(); let (method, uri, headers) = (parts.method, parts.uri, parts.headers); let path = paths::GLOBAL_REGEX_SET.matches(uri.path()); - let mut context = body.context; - let body = body.inner; match &method { @@ -138,9 +155,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw(); + match result.await { Ok(body) => { let mut unused_elements: Vec = vec![]; @@ -160,10 +176,10 @@ where multi_part_headers.set(ContentType(content_type_mime)); }, Err(e) => { - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(e)) - .expect("Unable to create Bad Request response due to unable to read content-type header for MultipartRelatedRequestPost"))); + .expect("Unable to create Bad Request response due to unable to read content-type header for MultipartRelatedRequestPost")); } } @@ -172,10 +188,10 @@ where let nodes = match read_multipart_body(&mut&*body, &multi_part_headers, false) { Ok(nodes) => nodes, Err(e) => { - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Could not read multipart body for MultipartRelatedRequestPost: {}", e))) - .expect("Unable to create Bad Request response due to unable to read multipart body for MultipartRelatedRequestPost"))); + .expect("Unable to create Bad Request response due to unable to read multipart body for MultipartRelatedRequestPost")); } }; @@ -195,10 +211,10 @@ where unused_elements.push(path.to_string()); }) { Ok(json_data) => json_data, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse body parameter models::MultipartRequestObjectField - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid body parameter models::MultipartRequestObjectField due to schema"))) + .expect("Unable to create Bad Request response for invalid body parameter models::MultipartRequestObjectField due to schema")) }; // Push JSON part to return object. param_object_field.get_or_insert(json_data); @@ -226,21 +242,20 @@ where // Check that the required multipart chunks are present. let param_required_binary_field = match param_required_binary_field { Some(x) => x, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Missing required multipart/related parameter required_binary_field"))) - .expect("Unable to create Bad Request response for missing multipart/related parameter required_binary_field due to schema"))) + .expect("Unable to create Bad Request response for missing multipart/related parameter required_binary_field due to schema")) }; - Box::new( - api_impl.multipart_related_request_post( + let result = api_impl.multipart_related_request_post( param_required_binary_field, param_object_field, param_optional_binary_field, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -260,35 +275,30 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter Default: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter Default"))), + .expect("Unable to create Bad Request response due to unable to read body parameter Default")), } - }) - ) as Self::Future }, // MultipartRequestPost - POST /multipart_request &hyper::Method::POST if path.matched(paths::ID_MULTIPART_REQUEST) => { let boundary = match swagger::multipart::boundary(&headers) { Some(boundary) => boundary.to_string(), - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Couldn't find valid multipart body".to_string())) - .expect("Unable to create Bad Request response for incorrect boundary"))), + .expect("Unable to create Bad Request response for incorrect boundary")), }; // Form Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw(); + match result.await { Ok(body) => { use std::io::Read; @@ -298,10 +308,10 @@ where entries }, _ => { - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Unable to process all message parts"))) - .expect("Unable to create Bad Request response due to failure to process all message"))) + .expect("Unable to create Bad Request response due to failure to process all message")) }, }; let field_string_field = entries.fields.remove("string_field"); @@ -313,21 +323,21 @@ where let string_field_model: String = match serde_json::from_str(&data) { Ok(model) => model, Err(e) => { - return Box::new(future::ok( + return Ok( Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("string_field data does not match API definition : {}", e))) - .expect("Unable to create Bad Request due to missing required form parameter string_field"))) + .expect("Unable to create Bad Request due to missing required form parameter string_field")) } }; string_field_model }, None => { - return Box::new(future::ok( + return Ok( Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Missing required form parameter string_field"))) - .expect("Unable to create Bad Request due to missing required form parameter string_field"))) + .expect("Unable to create Bad Request due to missing required form parameter string_field")) } }; let field_optional_string_field = entries.fields.remove("optional_string_field"); @@ -340,11 +350,11 @@ where let optional_string_field_model: String = match serde_json::from_str(&data) { Ok(model) => model, Err(e) => { - return Box::new(future::ok( + return Ok( Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("optional_string_field data does not match API definition : {}", e))) - .expect("Unable to create Bad Request due to missing required form parameter optional_string_field"))) + .expect("Unable to create Bad Request due to missing required form parameter optional_string_field")) } }; optional_string_field_model @@ -364,11 +374,11 @@ where let object_field_model: models::MultipartRequestObjectField = match serde_json::from_str(&data) { Ok(model) => model, Err(e) => { - return Box::new(future::ok( + return Ok( Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("object_field data does not match API definition : {}", e))) - .expect("Unable to create Bad Request due to missing required form parameter object_field"))) + .expect("Unable to create Bad Request due to missing required form parameter object_field")) } }; object_field_model @@ -387,23 +397,22 @@ where swagger::ByteArray(data) }, None => { - return Box::new(future::ok( + return Ok( Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Missing required form parameter binary_field"))) - .expect("Unable to create Bad Request due to missing required form parameter binary_field"))) + .expect("Unable to create Bad Request due to missing required form parameter binary_field")) } }; - Box::new( - api_impl.multipart_request_post( + let result = api_impl.multipart_request_post( param_string_field, param_binary_field, param_optional_string_field, param_object_field, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -423,18 +432,13 @@ where }, } - future::ok(response) - } - )) - as Self::Future + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read multipart body"))) - .expect("Unable to create Bad Request response due to unable read multipart body"))), + .expect("Unable to create Bad Request response due to unable read multipart body")), } - }) - ) }, // MultipleIdenticalMimeTypesPost - POST /multiple-identical-mime-types @@ -442,9 +446,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw(); + match result.await { Ok(body) => { let mut unused_elements: Vec = vec![]; @@ -464,10 +467,10 @@ where multi_part_headers.set(ContentType(content_type_mime)); }, Err(e) => { - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(e)) - .expect("Unable to create Bad Request response due to unable to read content-type header for MultipleIdenticalMimeTypesPost"))); + .expect("Unable to create Bad Request response due to unable to read content-type header for MultipleIdenticalMimeTypesPost")); } } @@ -476,10 +479,10 @@ where let nodes = match read_multipart_body(&mut&*body, &multi_part_headers, false) { Ok(nodes) => nodes, Err(e) => { - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Could not read multipart body for MultipleIdenticalMimeTypesPost: {}", e))) - .expect("Unable to create Bad Request response due to unable to read multipart body for MultipleIdenticalMimeTypesPost"))); + .expect("Unable to create Bad Request response due to unable to read multipart body for MultipleIdenticalMimeTypesPost")); } }; @@ -512,14 +515,13 @@ where // Check that the required multipart chunks are present. - Box::new( - api_impl.multiple_identical_mime_types_post( + let result = api_impl.multiple_identical_mime_types_post( param_binary1, param_binary2, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -539,39 +541,23 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter Default: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter Default"))), + .expect("Unable to create Bad Request response due to unable to read body parameter Default")), } - }) - ) as Self::Future }, _ if path.matched(paths::ID_MULTIPART_RELATED_REQUEST) => method_not_allowed(), _ if path.matched(paths::ID_MULTIPART_REQUEST) => method_not_allowed(), _ if path.matched(paths::ID_MULTIPLE_IDENTICAL_MIME_TYPES) => method_not_allowed(), - _ => Box::new(future::ok( - Response::builder().status(StatusCode::NOT_FOUND) + _ => Ok(Response::builder().status(StatusCode::NOT_FOUND) .body(Body::empty()) - .expect("Unable to create Not Found response") - )) as Self::Future + .expect("Unable to create Not Found response")) } - } -} - -impl Clone for Service where T: Clone -{ - fn clone(&self) -> Self { - Service { - api_impl: self.api_impl.clone(), - marker: self.marker.clone(), - } - } + } Box::pin(run(self.api_impl.clone(), req)) } } /// Request parser for `Api`. diff --git a/samples/server/petstore/rust-server/output/no-example-v3/Cargo.toml b/samples/server/petstore/rust-server/output/no-example-v3/Cargo.toml index b8dc9850d73..da632fac28d 100644 --- a/samples/server/petstore/rust-server/output/no-example-v3/Cargo.toml +++ b/samples/server/petstore/rust-server/output/no-example-v3/Cargo.toml @@ -9,7 +9,7 @@ edition = "2018" [features] default = ["client", "server"] client = [ - "hyper", "hyper-openssl", "native-tls", "openssl", "url" + "hyper", "hyper-openssl", "hyper-tls", "native-tls", "openssl", "url" ] server = [ "serde_ignored", "hyper", "regex", "percent-encoding", "url", "lazy_static" @@ -18,35 +18,37 @@ conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk- [target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] native-tls = { version = "0.2", optional = true } +hyper-tls = { version = "0.4", optional = true } [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dependencies] -hyper-openssl = { version = "0.7.1", optional = true } +hyper-openssl = { version = "0.8", optional = true } openssl = {version = "0.10", optional = true } [dependencies] # Common +async-trait = "0.1.24" chrono = { version = "0.4", features = ["serde"] } -futures = "0.1" -swagger = "4.0" +futures = "0.3" +swagger = "5.0.0-alpha-1" log = "0.4.0" mime = "0.3" -serde = { version = "1.0", features = ["derive"]} +serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" # Crates included if required by the API definition # Common between server and client features -hyper = {version = "0.12", optional = true} -serde_ignored = {version = "0.0.4", optional = true} -url = {version = "1.5", optional = true} +hyper = {version = "0.13", optional = true} +serde_ignored = {version = "0.1.1", optional = true} +url = {version = "2.1", optional = true} # Client-specific # Server, and client callback-specific lazy_static = { version = "1.4", optional = true } -percent-encoding = {version = "1.0.0", optional = true} -regex = {version = "0.2", optional = true} +percent-encoding = {version = "2.1.0", optional = true} +regex = {version = "1.3", optional = true} # Conversion frunk = { version = "0.3.0", optional = true } @@ -57,13 +59,13 @@ frunk-enum-core = { version = "0.2.0", optional = true } [dev-dependencies] clap = "2.25" -error-chain = "0.12" -env_logger = "0.6" -tokio = "0.1.17" -uuid = {version = "0.7", features = ["serde", "v4"]} +env_logger = "0.7" +tokio = { version = "0.2", features = ["rt-threaded", "macros", "stream"] } +native-tls = "0.2" +tokio-tls = "0.3" [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dev-dependencies] -tokio-openssl = "0.3" +tokio-openssl = "0.4" openssl = "0.10" [[example]] diff --git a/samples/server/petstore/rust-server/output/no-example-v3/examples/client/main.rs b/samples/server/petstore/rust-server/output/no-example-v3/examples/client/main.rs index 1f404ee95b6..ce34c07c8d5 100644 --- a/samples/server/petstore/rust-server/output/no-example-v3/examples/client/main.rs +++ b/samples/server/petstore/rust-server/output/no-example-v3/examples/client/main.rs @@ -2,11 +2,10 @@ #[allow(unused_imports)] -use futures::{Future, future, Stream, stream}; +use futures::{future, Stream, stream}; #[allow(unused_imports)] use no_example_v3::{Api, ApiNoContext, Client, ContextWrapperExt, models, - ApiError, - OpGetResponse + OpGetResponse, }; use clap::{App, Arg}; @@ -15,7 +14,9 @@ use log::info; // swagger::Has may be unused if there are no examples #[allow(unused_imports)] -use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData}; +use swagger::{AuthData, ContextBuilder, EmptyContext, Has, Push, XSpanIdString}; + +type ClientContext = swagger::make_context_ty!(ContextBuilder, EmptyContext, Option, XSpanIdString); // rt may be unused if there are no examples #[allow(unused_mut)] @@ -50,21 +51,21 @@ fn main() { matches.value_of("host").unwrap(), matches.value_of("port").unwrap()); - let client = if matches.is_present("https") { - // Using Simple HTTPS - Client::try_new_https(&base_url) - .expect("Failed to create HTTPS client") - } else { - // Using HTTP - Client::try_new_http( - &base_url) - .expect("Failed to create HTTP client") - }; - - let context: swagger::make_context_ty!(ContextBuilder, EmptyContext, Option, XSpanIdString) = + let context: ClientContext = swagger::make_context!(ContextBuilder, EmptyContext, None as Option, XSpanIdString::default()); - let client = client.with_context(context); + let mut client : Box> = if matches.is_present("https") { + // Using Simple HTTPS + let client = Box::new(Client::try_new_https(&base_url) + .expect("Failed to create HTTPS client")); + Box::new(client.with_context(context)) + } else { + // Using HTTP + let client = Box::new(Client::try_new_http( + &base_url) + .expect("Failed to create HTTP client")); + Box::new(client.with_context(context)) + }; let mut rt = tokio::runtime::Runtime::new().unwrap(); diff --git a/samples/server/petstore/rust-server/output/no-example-v3/examples/server/main.rs b/samples/server/petstore/rust-server/output/no-example-v3/examples/server/main.rs index 30b1c5c5e12..d1a25ec9b63 100644 --- a/samples/server/petstore/rust-server/output/no-example-v3/examples/server/main.rs +++ b/samples/server/petstore/rust-server/output/no-example-v3/examples/server/main.rs @@ -9,7 +9,8 @@ mod server; /// Create custom server, wire it to the autogenerated router, /// and pass it to the web server. -fn main() { +#[tokio::main] +async fn main() { env_logger::init(); let matches = App::new("server") @@ -20,5 +21,5 @@ fn main() { let addr = "127.0.0.1:8080"; - hyper::rt::run(server::create(addr, matches.is_present("https"))); + server::create(addr, matches.is_present("https")).await; } diff --git a/samples/server/petstore/rust-server/output/no-example-v3/examples/server/server.rs b/samples/server/petstore/rust-server/output/no-example-v3/examples/server/server.rs index 0ec693c32e5..5da31b0d716 100644 --- a/samples/server/petstore/rust-server/output/no-example-v3/examples/server/server.rs +++ b/samples/server/petstore/rust-server/output/no-example-v3/examples/server/server.rs @@ -2,30 +2,22 @@ #![allow(unused_imports)] -mod errors { - error_chain::error_chain!{} -} - -pub use self::errors::*; - -use chrono; -use futures::{future, Future, Stream}; +use async_trait::async_trait; +use futures::{future, Stream, StreamExt, TryFutureExt, TryStreamExt}; use hyper::server::conn::Http; -use hyper::service::MakeService as _; +use hyper::service::Service; use log::info; use openssl::ssl::SslAcceptorBuilder; +use std::future::Future; use std::marker::PhantomData; use std::net::SocketAddr; use std::sync::{Arc, Mutex}; -use swagger; +use std::task::{Context, Poll}; use swagger::{Has, XSpanIdString}; use swagger::auth::MakeAllowAllAuthenticator; use swagger::EmptyContext; use tokio::net::TcpListener; - -#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] -use tokio_openssl::SslAcceptorExt; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; @@ -33,18 +25,18 @@ use no_example_v3::models; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] /// Builds an SSL implementation for Simple HTTPS from some hard-coded file names -pub fn create(addr: &str, https: bool) -> Box + Send> { +pub async fn create(addr: &str, https: bool) { let addr = addr.parse().expect("Failed to parse bind address"); let server = Server::new(); - let service_fn = MakeService::new(server); + let service = MakeService::new(server); - let service_fn = MakeAllowAllAuthenticator::new(service_fn, "cosmo"); + let service = MakeAllowAllAuthenticator::new(service, "cosmo"); - let service_fn = + let mut service = no_example_v3::server::context::MakeAddContext::<_, EmptyContext>::new( - service_fn + service ); if https { @@ -62,32 +54,31 @@ pub fn create(addr: &str, https: bool) -> Box ssl.set_certificate_chain_file("examples/server-chain.pem").expect("Failed to set cerificate chain"); ssl.check_private_key().expect("Failed to check private key"); - let tls_acceptor = ssl.build(); - let service_fn = Arc::new(Mutex::new(service_fn)); - let tls_listener = TcpListener::bind(&addr).unwrap().incoming().for_each(move |tcp| { - let addr = tcp.peer_addr().expect("Unable to get remote address"); + let tls_acceptor = Arc::new(ssl.build()); + let mut tcp_listener = TcpListener::bind(&addr).await.unwrap(); + let mut incoming = tcp_listener.incoming(); - let service_fn = service_fn.clone(); + while let (Some(tcp), rest) = incoming.into_future().await { + if let Ok(tcp) = tcp { + let addr = tcp.peer_addr().expect("Unable to get remote address"); + let service = service.call(addr); + let tls_acceptor = Arc::clone(&tls_acceptor); - hyper::rt::spawn(tls_acceptor.accept_async(tcp).map_err(|_| ()).and_then(move |tls| { - let ms = { - let mut service_fn = service_fn.lock().unwrap(); - service_fn.make_service(&addr) - }; + tokio::spawn(async move { + let tls = tokio_openssl::accept(&*tls_acceptor, tcp).await.map_err(|_| ())?; - ms.and_then(move |service| { - Http::new().serve_connection(tls, service) - }).map_err(|_| ()) - })); + let service = service.await.map_err(|_| ())?; - Ok(()) - }).map_err(|_| ()); + Http::new().serve_connection(tls, service).await.map_err(|_| ()) + }); + } - Box::new(tls_listener) + incoming = rest; + } } } else { // Using HTTP - Box::new(hyper::server::Server::bind(&addr).serve(service_fn).map_err(|e| panic!("{:?}", e))) + hyper::server::Server::bind(&addr).serve(service).await.unwrap() } } @@ -105,20 +96,23 @@ impl Server { use no_example_v3::{ Api, - ApiError, OpGetResponse, }; use no_example_v3::server::MakeService; +use std::error::Error; +use swagger::ApiError; -impl Api for Server where C: Has{ - fn op_get( +#[async_trait] +impl Api for Server where C: Has + Send + Sync +{ + async fn op_get( &self, inline_object: models::InlineObject, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op_get({:?}) - X-Span-ID: {:?}", inline_object, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } } diff --git a/samples/server/petstore/rust-server/output/no-example-v3/src/client/mod.rs b/samples/server/petstore/rust-server/output/no-example-v3/src/client/mod.rs index 4e55ac6c63d..5948c84d2eb 100644 --- a/samples/server/petstore/rust-server/output/no-example-v3/src/client/mod.rs +++ b/samples/server/petstore/rust-server/output/no-example-v3/src/client/mod.rs @@ -1,48 +1,49 @@ -use futures; -use futures::{Future, Stream, future, stream}; -use hyper; -use hyper::client::HttpConnector; +use async_trait::async_trait; +use futures::{Stream, future, future::BoxFuture, stream, future::TryFutureExt, future::FutureExt, stream::StreamExt}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; -use hyper::{Body, Uri, Response}; -#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] -use hyper_openssl::HttpsConnector; -use serde_json; +use hyper::{Body, Request, Response, service::Service, Uri}; +use percent_encoding::{utf8_percent_encode, AsciiSet}; use std::borrow::Cow; use std::convert::TryInto; -use std::io::{Read, Error, ErrorKind}; -use std::error; +use std::io::{ErrorKind, Read}; +use std::error::Error; +use std::future::Future; use std::fmt; use std::path::Path; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use std::str; use std::str::FromStr; use std::string::ToString; -use swagger; -use swagger::{ApiError, Connector, client::Service, XSpanIdString, Has, AuthData}; +use std::task::{Context, Poll}; +use swagger::{ApiError, AuthData, BodyExt, Connector, Has, XSpanIdString}; use url::form_urlencoded; -use url::percent_encoding::{utf8_percent_encode, PATH_SEGMENT_ENCODE_SET, QUERY_ENCODE_SET}; + use crate::models; use crate::header; -url::define_encode_set! { - /// This encode set is used for object IDs - /// - /// Aside from the special characters defined in the `PATH_SEGMENT_ENCODE_SET`, - /// the vertical bar (|) is encoded. - pub ID_ENCODE_SET = [PATH_SEGMENT_ENCODE_SET] | {'|'} -} +/// https://url.spec.whatwg.org/#fragment-percent-encode-set +#[allow(dead_code)] +const FRAGMENT_ENCODE_SET: &AsciiSet = &percent_encoding::CONTROLS + .add(b' ').add(b'"').add(b'<').add(b'>').add(b'`'); + +/// This encode set is used for object IDs +/// +/// Aside from the special characters defined in the `PATH_SEGMENT_ENCODE_SET`, +/// the vertical bar (|) is encoded. +#[allow(dead_code)] +const ID_ENCODE_SET: &AsciiSet = &FRAGMENT_ENCODE_SET.add(b'|'); use crate::{Api, OpGetResponse }; /// Convert input into a base path, e.g. "http://example:123". Also checks the scheme as it goes. -fn into_base_path(input: &str, correct_scheme: Option<&'static str>) -> Result { +fn into_base_path(input: impl TryInto, correct_scheme: Option<&'static str>) -> Result { // First convert to Uri, since a base path is a subset of Uri. - let uri = Uri::from_str(input)?; + let uri = input.try_into()?; - let scheme = uri.scheme_part().ok_or(ClientInitError::InvalidScheme)?; + let scheme = uri.scheme_str().ok_or(ClientInitError::InvalidScheme)?; // Check the scheme if necessary if let Some(correct_scheme) = correct_scheme { @@ -52,38 +53,54 @@ fn into_base_path(input: &str, correct_scheme: Option<&'static str>) -> Result +pub struct Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { /// Inner service - client_service: Arc + Send + Sync>>, + client_service: S, /// Base path of the API base_path: String, } -impl fmt::Debug for Client +impl fmt::Debug for Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Client {{ base_path: {} }}", self.base_path) } } -impl Clone for Client +impl Clone for Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { fn clone(&self) -> Self { - Client { + Self { client_service: self.client_service.clone(), base_path: self.base_path.clone(), } } } -impl Client +impl Client> where + C: hyper::client::connect::Connect + Clone + Send + Sync + 'static { /// Create a client with a custom implementation of hyper::client::Connect. /// @@ -96,30 +113,93 @@ impl Client /// /// # Arguments /// - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "http://www.my-api-implementation.com" /// * `protocol` - Which protocol to use when constructing the request url, e.g. `Some("http")` /// * `connector` - Implementation of `hyper::client::Connect` to use for the client - pub fn try_new_with_connector( + pub fn try_new_with_connector( base_path: &str, protocol: Option<&'static str>, connector: C, - ) -> Result where - C: hyper::client::connect::Connect + 'static, - C::Transport: 'static, - C::Future: 'static, + ) -> Result { - let client_service = Box::new(hyper::client::Client::builder().build(connector)); + let client_service = hyper::client::Client::builder().build(connector); - Ok(Client { - client_service: Arc::new(client_service), + Ok(Self { + client_service, base_path: into_base_path(base_path, protocol)?, }) } +} +#[derive(Debug, Clone)] +pub enum HyperClient { + Http(hyper::client::Client), + Https(hyper::client::Client), +} + +impl Service> for HyperClient { + type Response = Response; + type Error = hyper::Error; + type Future = hyper::client::ResponseFuture; + + fn poll_ready(&mut self, cx: &mut Context) -> Poll> { + match self { + HyperClient::Http(client) => client.poll_ready(cx), + HyperClient::Https(client) => client.poll_ready(cx), + } + } + + fn call(&mut self, req: Request) -> Self::Future { + match self { + HyperClient::Http(client) => client.call(req), + HyperClient::Https(client) => client.call(req) + } + } +} + +impl Client { /// Create an HTTP client. /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "http://www.my-api-implementation.com" + pub fn try_new( + base_path: &str, + ) -> Result { + let uri = Uri::from_str(base_path)?; + + let scheme = uri.scheme_str().ok_or(ClientInitError::InvalidScheme)?; + let scheme = scheme.to_ascii_lowercase(); + + let connector = Connector::builder(); + + let client_service = match scheme.as_str() { + "http" => { + HyperClient::Http(hyper::client::Client::builder().build(connector.build())) + }, + "https" => { + let connector = connector.https() + .build() + .map_err(|e| ClientInitError::SslError(e))?; + HyperClient::Https(hyper::client::Client::builder().build(connector)) + }, + _ => { + return Err(ClientInitError::InvalidScheme); + } + }; + + Ok(Self { + client_service, + base_path: into_base_path(base_path, None)?, + }) + } +} + +impl Client> +{ + /// Create an HTTP client. + /// + /// # Arguments + /// * `base_path` - base path of the client API, i.e. "http://www.my-api-implementation.com" pub fn try_new_http( base_path: &str, ) -> Result { @@ -127,11 +207,20 @@ impl Client Self::try_new_with_connector(base_path, Some("http"), http_connector) } +} +#[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] +type HttpsConnector = hyper_tls::HttpsConnector; + +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +type HttpsConnector = hyper_openssl::HttpsConnector; + +impl Client> +{ /// Create a client with a TLS connection to the server /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "https://www.my-api-implementation.com" pub fn try_new_https(base_path: &str) -> Result { let https_connector = Connector::builder() @@ -144,7 +233,7 @@ impl Client /// Create a client with a TLS connection to the server using a pinned certificate /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "https://www.my-api-implementation.com" /// * `ca_certificate` - Path to CA certificate used to authenticate the server #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] pub fn try_new_https_pinned( @@ -165,7 +254,7 @@ impl Client /// Create a client with a mutually authenticated TLS connection to the server. /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "https://www.my-api-implementation.com" /// * `ca_certificate` - Path to CA certificate used to authenticate the server /// * `client_key` - Path to the client private key /// * `client_certificate` - Path to the client's public certificate associated with the private key @@ -191,17 +280,24 @@ impl Client } } -impl Client +impl Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { - /// Constructor for creating a `Client` by passing in a pre-made `swagger::Service` + /// Constructor for creating a `Client` by passing in a pre-made `hyper::service::Service` / + /// `tower::Service` /// /// This allows adding custom wrappers around the underlying transport, for example for logging. pub fn try_new_with_client_service( - client_service: Arc + Send + Sync>>, + client_service: S, base_path: &str, - ) -> Result { - Ok(Client { - client_service: client_service, + ) -> Result + { + Ok(Self { + client_service, base_path: into_base_path(base_path, None)?, }) } @@ -241,45 +337,61 @@ impl fmt::Display for ClientInitError { } } -impl error::Error for ClientInitError { +impl Error for ClientInitError { fn description(&self) -> &str { "Failed to produce a hyper client." } } -impl Api for Client where - C: Has , - F: Future, Error=hyper::Error> + Send + 'static +#[async_trait] +impl Api for Client where + C: Has + Clone + Send + Sync + 'static, + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { - fn op_get( + fn poll_ready(&self, cx: &mut Context) -> Poll> { + match self.client_service.clone().poll_ready(cx) { + Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())), + Poll::Ready(Ok(o)) => Poll::Ready(Ok(o)), + Poll::Pending => Poll::Pending, + } + } + + async fn op_get( &self, param_inline_object: models::InlineObject, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; // Body parameter @@ -290,48 +402,43 @@ impl Api for Client where let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - OpGetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + OpGetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } } diff --git a/samples/server/petstore/rust-server/output/no-example-v3/src/context.rs b/samples/server/petstore/rust-server/output/no-example-v3/src/context.rs index d14e73f822d..fadd880b965 100644 --- a/samples/server/petstore/rust-server/output/no-example-v3/src/context.rs +++ b/samples/server/petstore/rust-server/output/no-example-v3/src/context.rs @@ -1,13 +1,12 @@ -use futures::Future; -use hyper; +use futures::future::BoxFuture; use hyper::header::HeaderName; -use hyper::{Error, Request, Response, StatusCode, service::Service, body::Payload}; +use hyper::{Error, Request, Response, StatusCode, service::Service}; use url::form_urlencoded; use std::default::Default; use std::io; use std::marker::PhantomData; +use std::task::{Poll, Context}; use swagger::auth::{AuthData, Authorization, Bearer, Scopes}; -use swagger::context::ContextualPayload; use swagger::{EmptyContext, Has, Pop, Push, XSpanIdString}; use crate::Api; @@ -31,58 +30,52 @@ where } // Make a service that adds context. -impl<'a, T, SC, A, B, C, D, E, ME, S, OB, F> hyper::service::MakeService<&'a SC> for +impl Service for MakeAddContext where - A: Default + Push, + Target: Send, + A: Default + Push + Send, B: Push, Result = C>, C: Push, Result = D>, D: Send + 'static, - T: hyper::service::MakeService< - &'a SC, - Error = E, - MakeError = ME, - Service = S, - ReqBody = ContextualPayload, - ResBody = OB, - Future = F - >, - S: Service< - Error = E, - ReqBody = ContextualPayload, - ResBody = OB> + 'static, - ME: swagger::ErrorBound, - E: swagger::ErrorBound, - F: Future + Send + 'static, - S::Future: Send, - OB: Payload, + T: Service + Send, + T::Future: Send + 'static { - type ReqBody = hyper::Body; - type ResBody = OB; - type Error = E; - type MakeError = ME; - type Service = AddContext; - type Future = Box + Send + 'static>; + type Error = T::Error; + type Response = AddContext; + type Future = BoxFuture<'static, Result>; - fn make_service(&mut self, ctx: &'a SC) -> Self::Future { - Box::new(self.inner.make_service(ctx).map(|s| AddContext::new(s))) + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + self.inner.poll_ready(cx) + } + + fn call(&mut self, target: Target) -> Self::Future { + let service = self.inner.call(target); + + Box::pin(async move { + Ok(AddContext::new(service.await?)) + }) } } -/// Middleware to extract authentication data from request -pub struct AddContext { +/// Middleware to add context data from the request +pub struct AddContext +where + A: Default + Push, + B: Push, Result = C>, + C: Push, Result = D> +{ inner: T, marker: PhantomData, } -impl AddContext +impl AddContext where A: Default + Push, B: Push, Result = C>, C: Push, Result = D>, - T: Service, { - pub fn new(inner: T) -> AddContext { + pub fn new(inner: T) -> Self { AddContext { inner, marker: PhantomData, @@ -90,33 +83,31 @@ where } } -impl Service for AddContext +impl Service> for AddContext where A: Default + Push, B: Push, Result=C>, C: Push, Result=D>, D: Send + 'static, - T: Service>, - T::Future: Future, Error=T::Error> + Send + 'static + T: Service<(Request, D)> { - type ReqBody = hyper::Body; - type ResBody = T::ResBody; type Error = T::Error; - type Future = Box, Error=T::Error> + Send + 'static>; + type Future = T::Future; + type Response = T::Response; - fn call(&mut self, req: Request) -> Self::Future { - let context = A::default().push(XSpanIdString::get_or_generate(&req)); - let (head, body) = req.into_parts(); - let headers = head.headers.clone(); + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + self.inner.poll_ready(cx) + } + + + fn call(&mut self, request: Request) -> Self::Future { + let context = A::default().push(XSpanIdString::get_or_generate(&request)); + let headers = request.headers(); let context = context.push(None::); let context = context.push(None::); - let body = ContextualPayload { - inner: body, - context: context, - }; - Box::new(self.inner.call(hyper::Request::from_parts(head, body))) + self.inner.call((request, context)) } } diff --git a/samples/server/petstore/rust-server/output/no-example-v3/src/lib.rs b/samples/server/petstore/rust-server/output/no-example-v3/src/lib.rs index 0a6aa8ad57e..a6c48e87c07 100644 --- a/samples/server/petstore/rust-server/output/no-example-v3/src/lib.rs +++ b/samples/server/petstore/rust-server/output/no-example-v3/src/lib.rs @@ -1,12 +1,12 @@ #![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)] +use async_trait::async_trait; use futures::Stream; -use std::io::Error; +use std::error::Error; +use std::task::{Poll, Context}; +use swagger::{ApiError, ContextWrapper}; -#[deprecated(note = "Import swagger-rs directly")] -pub use swagger::{ApiError, ContextWrapper}; -#[deprecated(note = "Import futures directly")] -pub use futures::Future; +type ServiceError = Box; pub const BASE_PATH: &'static str = ""; pub const API_VERSION: &'static str = "0.0.1"; @@ -18,46 +18,69 @@ pub enum OpGetResponse { } /// API -pub trait Api { - fn op_get( +#[async_trait] +pub trait Api { + fn poll_ready(&self, _cx: &mut Context) -> Poll>> { + Poll::Ready(Ok(())) + } + + async fn op_get( &self, inline_object: models::InlineObject, - context: &C) -> Box + Send>; + context: &C) -> Result; } -/// API without a `Context` -pub trait ApiNoContext { - fn op_get( +/// API where `Context` isn't passed on every API call +#[async_trait] +pub trait ApiNoContext { + + fn poll_ready(&self, _cx: &mut Context) -> Poll>>; + + fn context(&self) -> &C; + + async fn op_get( &self, inline_object: models::InlineObject, - ) -> Box + Send>; + ) -> Result; } /// Trait to extend an API to make it easy to bind it to a context. -pub trait ContextWrapperExt<'a, C> where Self: Sized { +pub trait ContextWrapperExt where Self: Sized +{ /// Binds this API to a context. - fn with_context(self: &'a Self, context: C) -> ContextWrapper<'a, Self, C>; + fn with_context(self: Self, context: C) -> ContextWrapper; } -impl<'a, T: Api + Sized, C> ContextWrapperExt<'a, C> for T { - fn with_context(self: &'a T, context: C) -> ContextWrapper<'a, T, C> { +impl + Send + Sync, C: Clone + Send + Sync> ContextWrapperExt for T { + fn with_context(self: T, context: C) -> ContextWrapper { ContextWrapper::::new(self, context) } } -impl<'a, T: Api, C> ApiNoContext for ContextWrapper<'a, T, C> { - fn op_get( +#[async_trait] +impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for ContextWrapper { + fn poll_ready(&self, cx: &mut Context) -> Poll> { + self.api().poll_ready(cx) + } + + fn context(&self) -> &C { + ContextWrapper::context(self) + } + + async fn op_get( &self, inline_object: models::InlineObject, - ) -> Box + Send> + ) -> Result { - self.api().op_get(inline_object, &self.context()) + let context = self.context().clone(); + self.api().op_get(inline_object, &context).await } } + #[cfg(feature = "client")] pub mod client; diff --git a/samples/server/petstore/rust-server/output/no-example-v3/src/server/mod.rs b/samples/server/petstore/rust-server/output/no-example-v3/src/server/mod.rs index 3c1062d0f9b..0610da8c15b 100644 --- a/samples/server/petstore/rust-server/output/no-example-v3/src/server/mod.rs +++ b/samples/server/petstore/rust-server/output/no-example-v3/src/server/mod.rs @@ -1,20 +1,17 @@ -use std::marker::PhantomData; -use futures::{Future, future, Stream, stream}; -use hyper; -use hyper::{Request, Response, Error, StatusCode, Body, HeaderMap}; +use futures::{future, future::BoxFuture, Stream, stream, future::FutureExt, stream::TryStreamExt}; +use hyper::{Request, Response, StatusCode, Body, HeaderMap}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; use log::warn; -use serde_json; #[allow(unused_imports)] use std::convert::{TryFrom, TryInto}; -use std::io; -use url::form_urlencoded; -#[allow(unused_imports)] -use swagger; -use swagger::{ApiError, XSpanIdString, Has, RequestParser}; +use std::error::Error; +use std::future::Future; +use std::marker::PhantomData; +use std::task::{Context, Poll}; +use swagger::{ApiError, BodyExt, Has, RequestParser, XSpanIdString}; pub use swagger::auth::Authorization; use swagger::auth::Scopes; -use swagger::context::ContextualPayload; +use url::form_urlencoded; #[allow(unused_imports)] use crate::models; @@ -22,6 +19,8 @@ use crate::header; pub use crate::context; +type ServiceFuture = BoxFuture<'static, Result, crate::ServiceError>>; + use crate::{Api, OpGetResponse }; @@ -38,15 +37,17 @@ mod paths { pub(crate) static ID_OP: usize = 0; } -pub struct MakeService { +pub struct MakeService where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static +{ api_impl: T, - marker: PhantomData, + marker: PhantomData, } -impl MakeService -where - T: Api + Clone + Send + 'static, - RC: Has + 'static +impl MakeService where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static { pub fn new(api_impl: T) -> Self { MakeService { @@ -56,44 +57,45 @@ where } } -impl<'a, T, SC, RC> hyper::service::MakeService<&'a SC> for MakeService -where - T: Api + Clone + Send + 'static, - RC: Has + 'static + Send +impl hyper::service::Service for MakeService where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static { - type ReqBody = ContextualPayload; - type ResBody = Body; - type Error = Error; - type Service = Service; - type Future = future::FutureResult; - type MakeError = Error; + type Response = Service; + type Error = crate::ServiceError; + type Future = future::Ready>; - fn make_service(&mut self, _ctx: &'a SC) -> Self::Future { - future::FutureResult::from(Ok(Service::new( + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn call(&mut self, target: Target) -> Self::Future { + futures::future::ok(Service::new( self.api_impl.clone(), - ))) + )) } } -type ServiceFuture = Box, Error = Error> + Send>; - -fn method_not_allowed() -> ServiceFuture { - Box::new(future::ok( +fn method_not_allowed() -> Result, crate::ServiceError> { + Ok( Response::builder().status(StatusCode::METHOD_NOT_ALLOWED) .body(Body::empty()) .expect("Unable to create Method Not Allowed response") - )) + ) } -pub struct Service { +pub struct Service where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static +{ api_impl: T, - marker: PhantomData, + marker: PhantomData, } -impl Service -where - T: Api + Clone + Send + 'static, - RC: Has + 'static { +impl Service where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static +{ pub fn new(api_impl: T) -> Self { Service { api_impl: api_impl, @@ -102,23 +104,38 @@ where } } -impl hyper::service::Service for Service -where +impl Clone for Service where T: Api + Clone + Send + 'static, - C: Has + 'static + Send + C: Has + Send + Sync + 'static { - type ReqBody = ContextualPayload; - type ResBody = Body; - type Error = Error; + fn clone(&self) -> Self { + Service { + api_impl: self.api_impl.clone(), + marker: self.marker.clone(), + } + } +} + +impl hyper::service::Service<(Request, C)> for Service where + T: Api + Clone + Send + Sync + 'static, + C: Has + Send + Sync + 'static +{ + type Response = Response; + type Error = crate::ServiceError; type Future = ServiceFuture; - fn call(&mut self, req: Request) -> Self::Future { - let api_impl = self.api_impl.clone(); - let (parts, body) = req.into_parts(); + fn poll_ready(&mut self, cx: &mut Context) -> Poll> { + self.api_impl.poll_ready(cx) + } + + fn call(&mut self, req: (Request, C)) -> Self::Future { async fn run(mut api_impl: T, req: (Request, C)) -> Result, crate::ServiceError> where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static + { + let (request, context) = req; + let (parts, body) = request.into_parts(); let (method, uri, headers) = (parts.method, parts.uri, parts.headers); let path = paths::GLOBAL_REGEX_SET.matches(uri.path()); - let mut context = body.context; - let body = body.inner; match &method { @@ -127,9 +144,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_inline_object: Option = if !body.is_empty() { @@ -139,29 +155,28 @@ where unused_elements.push(path.to_string()); }) { Ok(param_inline_object) => param_inline_object, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse body parameter InlineObject - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid body parameter InlineObject due to schema"))), + .expect("Unable to create Bad Request response for invalid body parameter InlineObject due to schema")), } } else { None }; let param_inline_object = match param_inline_object { Some(param_inline_object) => param_inline_object, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required body parameter InlineObject")) - .expect("Unable to create Bad Request response for missing body parameter InlineObject"))), + .expect("Unable to create Bad Request response for missing body parameter InlineObject")), }; - Box::new( - api_impl.op_get( + let result = api_impl.op_get( param_inline_object, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -188,37 +203,21 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter InlineObject: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter InlineObject"))), + .expect("Unable to create Bad Request response due to unable to read body parameter InlineObject")), } - }) - ) as Self::Future }, _ if path.matched(paths::ID_OP) => method_not_allowed(), - _ => Box::new(future::ok( - Response::builder().status(StatusCode::NOT_FOUND) + _ => Ok(Response::builder().status(StatusCode::NOT_FOUND) .body(Body::empty()) - .expect("Unable to create Not Found response") - )) as Self::Future + .expect("Unable to create Not Found response")) } - } -} - -impl Clone for Service where T: Clone -{ - fn clone(&self) -> Self { - Service { - api_impl: self.api_impl.clone(), - marker: self.marker.clone(), - } - } + } Box::pin(run(self.api_impl.clone(), req)) } } /// Request parser for `Api`. diff --git a/samples/server/petstore/rust-server/output/openapi-v3/Cargo.toml b/samples/server/petstore/rust-server/output/openapi-v3/Cargo.toml index 67413a16903..0f19d1f064a 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/Cargo.toml +++ b/samples/server/petstore/rust-server/output/openapi-v3/Cargo.toml @@ -10,49 +10,51 @@ edition = "2018" default = ["client", "server"] client = [ "serde_ignored", "regex", "percent-encoding", "lazy_static", - "hyper", "hyper-openssl", "native-tls", "openssl", "url" + "hyper", "hyper-openssl", "hyper-tls", "native-tls", "openssl", "url" ] server = [ - "native-tls", "hyper-openssl", "openssl", + "native-tls", "hyper-openssl", "hyper-tls", "openssl", "serde_ignored", "hyper", "regex", "percent-encoding", "url", "lazy_static" ] conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] [target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] native-tls = { version = "0.2", optional = true } +hyper-tls = { version = "0.4", optional = true } [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dependencies] -hyper-openssl = { version = "0.7.1", optional = true } +hyper-openssl = { version = "0.8", optional = true } openssl = {version = "0.10", optional = true } [dependencies] # Common +async-trait = "0.1.24" chrono = { version = "0.4", features = ["serde"] } -futures = "0.1" -swagger = "4.0" +futures = "0.3" +swagger = "5.0.0-alpha-1" log = "0.4.0" mime = "0.3" -serde = { version = "1.0", features = ["derive"]} +serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" # Crates included if required by the API definition # TODO: this should be updated to point at the official crate once # https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream serde-xml-rs = {git = "git://github.com/Metaswitch/serde-xml-rs.git" , branch = "master"} -uuid = {version = "0.7", features = ["serde", "v4"]} +uuid = {version = "0.8", features = ["serde", "v4"]} # Common between server and client features -hyper = {version = "0.12", optional = true} -serde_ignored = {version = "0.0.4", optional = true} -url = {version = "1.5", optional = true} +hyper = {version = "0.13", optional = true} +serde_ignored = {version = "0.1.1", optional = true} +url = {version = "2.1", optional = true} # Client-specific # Server, and client callback-specific lazy_static = { version = "1.4", optional = true } -percent-encoding = {version = "1.0.0", optional = true} -regex = {version = "0.2", optional = true} +percent-encoding = {version = "2.1.0", optional = true} +regex = {version = "1.3", optional = true} # Conversion frunk = { version = "0.3.0", optional = true } @@ -63,12 +65,13 @@ frunk-enum-core = { version = "0.2.0", optional = true } [dev-dependencies] clap = "2.25" -error-chain = "0.12" -env_logger = "0.6" -tokio = "0.1.17" +env_logger = "0.7" +tokio = { version = "0.2", features = ["rt-threaded", "macros", "stream"] } +native-tls = "0.2" +tokio-tls = "0.3" [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dev-dependencies] -tokio-openssl = "0.3" +tokio-openssl = "0.4" openssl = "0.10" [[example]] diff --git a/samples/server/petstore/rust-server/output/openapi-v3/examples/client/main.rs b/samples/server/petstore/rust-server/output/openapi-v3/examples/client/main.rs index 20d587392f5..633d4e31914 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/examples/client/main.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/examples/client/main.rs @@ -3,10 +3,9 @@ mod server; #[allow(unused_imports)] -use futures::{Future, future, Stream, stream}; +use futures::{future, Stream, stream}; #[allow(unused_imports)] use openapi_v3::{Api, ApiNoContext, Client, ContextWrapperExt, models, - ApiError, CallbackWithHeaderPostResponse, ComplexQueryParamGetResponse, EnumInPathPathParamGetResponse, @@ -29,7 +28,7 @@ use openapi_v3::{Api, ApiNoContext, Client, ContextWrapperExt, models, XmlPostResponse, XmlPutResponse, CreateRepoResponse, - GetRepoInfoResponse + GetRepoInfoResponse, }; use clap::{App, Arg}; @@ -38,7 +37,9 @@ use log::info; // swagger::Has may be unused if there are no examples #[allow(unused_imports)] -use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData}; +use swagger::{AuthData, ContextBuilder, EmptyContext, Has, Push, XSpanIdString}; + +type ClientContext = swagger::make_context_ty!(ContextBuilder, EmptyContext, Option, XSpanIdString); // rt may be unused if there are no examples #[allow(unused_mut)] @@ -95,21 +96,21 @@ fn main() { matches.value_of("host").unwrap(), matches.value_of("port").unwrap()); - let client = if matches.is_present("https") { - // Using Simple HTTPS - Client::try_new_https(&base_url) - .expect("Failed to create HTTPS client") - } else { - // Using HTTP - Client::try_new_http( - &base_url) - .expect("Failed to create HTTP client") - }; - - let context: swagger::make_context_ty!(ContextBuilder, EmptyContext, Option, XSpanIdString) = + let context: ClientContext = swagger::make_context!(ContextBuilder, EmptyContext, None as Option, XSpanIdString::default()); - let client = client.with_context(context); + let mut client : Box> = if matches.is_present("https") { + // Using Simple HTTPS + let client = Box::new(Client::try_new_https(&base_url) + .expect("Failed to create HTTPS client")); + Box::new(client.with_context(context)) + } else { + // Using HTTP + let client = Box::new(Client::try_new_http( + &base_url) + .expect("Failed to create HTTP client")); + Box::new(client.with_context(context)) + }; let mut rt = tokio::runtime::Runtime::new().unwrap(); diff --git a/samples/server/petstore/rust-server/output/openapi-v3/examples/client/server.rs b/samples/server/petstore/rust-server/output/openapi-v3/examples/client/server.rs index 2e2a3036b65..9d295a0f9e3 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/examples/client/server.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/examples/client/server.rs @@ -2,30 +2,22 @@ #![allow(unused_imports)] -mod errors { - error_chain::error_chain!{} -} - -pub use self::errors::*; - -use chrono; -use futures::{future, Future, Stream}; +use async_trait::async_trait; +use futures::{future, Stream, StreamExt, TryFutureExt, TryStreamExt}; use hyper::server::conn::Http; -use hyper::service::MakeService as _; +use hyper::service::Service; use log::info; use openssl::ssl::SslAcceptorBuilder; +use std::future::Future; use std::marker::PhantomData; use std::net::SocketAddr; use std::sync::{Arc, Mutex}; -use swagger; +use std::task::{Context, Poll}; use swagger::{Has, XSpanIdString}; use swagger::auth::MakeAllowAllAuthenticator; use swagger::EmptyContext; use tokio::net::TcpListener; -use uuid; -#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] -use tokio_openssl::SslAcceptorExt; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; @@ -33,18 +25,18 @@ use openapi_v3::models; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] /// Builds an SSL implementation for Simple HTTPS from some hard-coded file names -pub fn create(addr: &str, https: bool) -> Box + Send> { +pub async fn create(addr: &str, https: bool) { let addr = addr.parse().expect("Failed to parse bind address"); let server = Server::new(); - let service_fn = MakeService::new(server); + let service = MakeService::new(server); - let service_fn = MakeAllowAllAuthenticator::new(service_fn, "cosmo"); + let service = MakeAllowAllAuthenticator::new(service, "cosmo"); - let service_fn = + let mut service = openapi_v3::server::context::MakeAddContext::<_, EmptyContext>::new( - service_fn + service ); if https { @@ -62,32 +54,31 @@ pub fn create(addr: &str, https: bool) -> Box ssl.set_certificate_chain_file("examples/server-chain.pem").expect("Failed to set cerificate chain"); ssl.check_private_key().expect("Failed to check private key"); - let tls_acceptor = ssl.build(); - let service_fn = Arc::new(Mutex::new(service_fn)); - let tls_listener = TcpListener::bind(&addr).unwrap().incoming().for_each(move |tcp| { - let addr = tcp.peer_addr().expect("Unable to get remote address"); + let tls_acceptor = Arc::new(ssl.build()); + let mut tcp_listener = TcpListener::bind(&addr).await.unwrap(); + let mut incoming = tcp_listener.incoming(); - let service_fn = service_fn.clone(); + while let (Some(tcp), rest) = incoming.into_future().await { + if let Ok(tcp) = tcp { + let addr = tcp.peer_addr().expect("Unable to get remote address"); + let service = service.call(addr); + let tls_acceptor = Arc::clone(&tls_acceptor); - hyper::rt::spawn(tls_acceptor.accept_async(tcp).map_err(|_| ()).and_then(move |tls| { - let ms = { - let mut service_fn = service_fn.lock().unwrap(); - service_fn.make_service(&addr) - }; + tokio::spawn(async move { + let tls = tokio_openssl::accept(&*tls_acceptor, tcp).await.map_err(|_| ())?; - ms.and_then(move |service| { - Http::new().serve_connection(tls, service) - }).map_err(|_| ()) - })); + let service = service.await.map_err(|_| ())?; - Ok(()) - }).map_err(|_| ()); + Http::new().serve_connection(tls, service).await.map_err(|_| ()) + }); + } - Box::new(tls_listener) + incoming = rest; + } } } else { // Using HTTP - Box::new(hyper::server::Server::bind(&addr).serve(service_fn).map_err(|e| panic!("{:?}", e))) + hyper::server::Server::bind(&addr).serve(service).await.unwrap() } } @@ -102,31 +93,35 @@ impl Server { } } -use openapi_v3::{CallbackApi, ApiError}; +use openapi_v3::CallbackApi; use openapi_v3::CallbackCallbackWithHeaderPostResponse; use openapi_v3::CallbackCallbackPostResponse; use openapi_v3::client::callbacks::MakeService; +use std::error::Error; +use swagger::ApiError; -impl CallbackApi for Server where C: Has{ - fn callback_callback_with_header_post( +#[async_trait] +impl CallbackApi for Server where C: Has + Send + Sync +{ + async fn callback_callback_with_header_post( &self, callback_request_query_url: String, information: Option, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("callback_callback_with_header_post({:?}) - X-Span-ID: {:?}", information, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn callback_callback_post( + async fn callback_callback_post( &self, callback_request_query_url: String, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("callback_callback_post() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } } diff --git a/samples/server/petstore/rust-server/output/openapi-v3/examples/server/main.rs b/samples/server/petstore/rust-server/output/openapi-v3/examples/server/main.rs index bc1abfaa554..448771feb06 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/examples/server/main.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/examples/server/main.rs @@ -9,7 +9,8 @@ mod server; /// Create custom server, wire it to the autogenerated router, /// and pass it to the web server. -fn main() { +#[tokio::main] +async fn main() { env_logger::init(); let matches = App::new("server") @@ -20,5 +21,5 @@ fn main() { let addr = "127.0.0.1:8080"; - hyper::rt::run(server::create(addr, matches.is_present("https"))); + server::create(addr, matches.is_present("https")).await; } diff --git a/samples/server/petstore/rust-server/output/openapi-v3/examples/server/server.rs b/samples/server/petstore/rust-server/output/openapi-v3/examples/server/server.rs index 0326561a01d..9377679f314 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/examples/server/server.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/examples/server/server.rs @@ -2,30 +2,22 @@ #![allow(unused_imports)] -mod errors { - error_chain::error_chain!{} -} - -pub use self::errors::*; - -use chrono; -use futures::{future, Future, Stream}; +use async_trait::async_trait; +use futures::{future, Stream, StreamExt, TryFutureExt, TryStreamExt}; use hyper::server::conn::Http; -use hyper::service::MakeService as _; +use hyper::service::Service; use log::info; use openssl::ssl::SslAcceptorBuilder; +use std::future::Future; use std::marker::PhantomData; use std::net::SocketAddr; use std::sync::{Arc, Mutex}; -use swagger; +use std::task::{Context, Poll}; use swagger::{Has, XSpanIdString}; use swagger::auth::MakeAllowAllAuthenticator; use swagger::EmptyContext; use tokio::net::TcpListener; -use uuid; -#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] -use tokio_openssl::SslAcceptorExt; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; @@ -33,18 +25,18 @@ use openapi_v3::models; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] /// Builds an SSL implementation for Simple HTTPS from some hard-coded file names -pub fn create(addr: &str, https: bool) -> Box + Send> { +pub async fn create(addr: &str, https: bool) { let addr = addr.parse().expect("Failed to parse bind address"); let server = Server::new(); - let service_fn = MakeService::new(server); + let service = MakeService::new(server); - let service_fn = MakeAllowAllAuthenticator::new(service_fn, "cosmo"); + let service = MakeAllowAllAuthenticator::new(service, "cosmo"); - let service_fn = + let mut service = openapi_v3::server::context::MakeAddContext::<_, EmptyContext>::new( - service_fn + service ); if https { @@ -62,32 +54,31 @@ pub fn create(addr: &str, https: bool) -> Box ssl.set_certificate_chain_file("examples/server-chain.pem").expect("Failed to set cerificate chain"); ssl.check_private_key().expect("Failed to check private key"); - let tls_acceptor = ssl.build(); - let service_fn = Arc::new(Mutex::new(service_fn)); - let tls_listener = TcpListener::bind(&addr).unwrap().incoming().for_each(move |tcp| { - let addr = tcp.peer_addr().expect("Unable to get remote address"); + let tls_acceptor = Arc::new(ssl.build()); + let mut tcp_listener = TcpListener::bind(&addr).await.unwrap(); + let mut incoming = tcp_listener.incoming(); - let service_fn = service_fn.clone(); + while let (Some(tcp), rest) = incoming.into_future().await { + if let Ok(tcp) = tcp { + let addr = tcp.peer_addr().expect("Unable to get remote address"); + let service = service.call(addr); + let tls_acceptor = Arc::clone(&tls_acceptor); - hyper::rt::spawn(tls_acceptor.accept_async(tcp).map_err(|_| ()).and_then(move |tls| { - let ms = { - let mut service_fn = service_fn.lock().unwrap(); - service_fn.make_service(&addr) - }; + tokio::spawn(async move { + let tls = tokio_openssl::accept(&*tls_acceptor, tcp).await.map_err(|_| ())?; - ms.and_then(move |service| { - Http::new().serve_connection(tls, service) - }).map_err(|_| ()) - })); + let service = service.await.map_err(|_| ())?; - Ok(()) - }).map_err(|_| ()); + Http::new().serve_connection(tls, service).await.map_err(|_| ()) + }); + } - Box::new(tls_listener) + incoming = rest; + } } } else { // Using HTTP - Box::new(hyper::server::Server::bind(&addr).serve(service_fn).map_err(|e| panic!("{:?}", e))) + hyper::server::Server::bind(&addr).serve(service).await.unwrap() } } @@ -105,7 +96,6 @@ impl Server { use openapi_v3::{ Api, - ApiError, CallbackWithHeaderPostResponse, ComplexQueryParamGetResponse, EnumInPathPathParamGetResponse, @@ -131,233 +121,237 @@ use openapi_v3::{ GetRepoInfoResponse, }; use openapi_v3::server::MakeService; +use std::error::Error; +use swagger::ApiError; -impl Api for Server where C: Has{ - fn callback_with_header_post( +#[async_trait] +impl Api for Server where C: Has + Send + Sync +{ + async fn callback_with_header_post( &self, url: String, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("callback_with_header_post(\"{}\") - X-Span-ID: {:?}", url, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn complex_query_param_get( + async fn complex_query_param_get( &self, list_of_strings: Option<&Vec>, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("complex_query_param_get({:?}) - X-Span-ID: {:?}", list_of_strings, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn enum_in_path_path_param_get( + async fn enum_in_path_path_param_get( &self, path_param: models::StringEnum, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("enum_in_path_path_param_get({:?}) - X-Span-ID: {:?}", path_param, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn mandatory_request_header_get( + async fn mandatory_request_header_get( &self, x_header: String, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("mandatory_request_header_get(\"{}\") - X-Span-ID: {:?}", x_header, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn merge_patch_json_get( + async fn merge_patch_json_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("merge_patch_json_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Get some stuff. - fn multiget_get( + async fn multiget_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("multiget_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn multiple_auth_scheme_get( + async fn multiple_auth_scheme_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("multiple_auth_scheme_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn override_server_get( + async fn override_server_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("override_server_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Get some stuff with parameters. - fn paramget_get( + async fn paramget_get( &self, uuid: Option, some_object: Option, some_list: Option, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("paramget_get({:?}, {:?}, {:?}) - X-Span-ID: {:?}", uuid, some_object, some_list, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn readonly_auth_scheme_get( + async fn readonly_auth_scheme_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("readonly_auth_scheme_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn register_callback_post( + async fn register_callback_post( &self, url: String, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("register_callback_post(\"{}\") - X-Span-ID: {:?}", url, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn required_octet_stream_put( + async fn required_octet_stream_put( &self, body: swagger::ByteArray, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("required_octet_stream_put({:?}) - X-Span-ID: {:?}", body, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn responses_with_headers_get( + async fn responses_with_headers_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("responses_with_headers_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn rfc7807_get( + async fn rfc7807_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("rfc7807_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn untyped_property_get( + async fn untyped_property_get( &self, object_untyped_props: Option, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("untyped_property_get({:?}) - X-Span-ID: {:?}", object_untyped_props, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn uuid_get( + async fn uuid_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("uuid_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn xml_extra_post( + async fn xml_extra_post( &self, duplicate_xml_object: Option, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("xml_extra_post({:?}) - X-Span-ID: {:?}", duplicate_xml_object, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn xml_other_post( + async fn xml_other_post( &self, another_xml_object: Option, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("xml_other_post({:?}) - X-Span-ID: {:?}", another_xml_object, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn xml_other_put( + async fn xml_other_put( &self, another_xml_array: Option, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("xml_other_put({:?}) - X-Span-ID: {:?}", another_xml_array, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Post an array - fn xml_post( + async fn xml_post( &self, xml_array: Option, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("xml_post({:?}) - X-Span-ID: {:?}", xml_array, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn xml_put( + async fn xml_put( &self, xml_object: Option, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("xml_put({:?}) - X-Span-ID: {:?}", xml_object, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn create_repo( + async fn create_repo( &self, object_param: models::ObjectParam, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("create_repo({:?}) - X-Span-ID: {:?}", object_param, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn get_repo_info( + async fn get_repo_info( &self, repo_id: String, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("get_repo_info(\"{}\") - X-Span-ID: {:?}", repo_id, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } } diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/client/callbacks.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/client/callbacks.rs index 7ed0cb95aac..e20da072d9d 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/client/callbacks.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/client/callbacks.rs @@ -1,22 +1,17 @@ -use std::marker::PhantomData; -use futures::{Future, future, Stream, stream}; -use hyper; -use hyper::{Request, Response, Error, StatusCode, Body, HeaderMap}; +use futures::{future, future::BoxFuture, Stream, stream, future::FutureExt, stream::TryStreamExt}; +use hyper::{Request, Response, StatusCode, Body, HeaderMap}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; use log::warn; -use serde_json; #[allow(unused_imports)] use std::convert::{TryFrom, TryInto}; -use std::io; -use url::form_urlencoded; -#[allow(unused_imports)] -use swagger; -use swagger::{ApiError, XSpanIdString, Has, RequestParser}; +use std::error::Error; +use std::future::Future; +use std::marker::PhantomData; +use std::task::{Context, Poll}; +use swagger::{ApiError, BodyExt, Has, RequestParser, XSpanIdString}; pub use swagger::auth::Authorization; use swagger::auth::Scopes; -use swagger::context::ContextualPayload; -use uuid; -use serde_xml_rs; +use url::form_urlencoded; #[allow(unused_imports)] use crate::models; @@ -24,6 +19,8 @@ use crate::header; pub use crate::context; +type ServiceFuture = BoxFuture<'static, Result, crate::ServiceError>>; + use crate::CallbackApi as Api; use crate::CallbackCallbackWithHeaderPostResponse; use crate::CallbackCallbackPostResponse; @@ -53,15 +50,17 @@ mod paths { } -pub struct MakeService { +pub struct MakeService where + T: Api + Clone + Send + 'static, + C: Has + Has> + Send + Sync + 'static +{ api_impl: T, - marker: PhantomData, + marker: PhantomData, } -impl MakeService -where - T: Api + Clone + Send + 'static, - RC: Has + Has> + 'static +impl MakeService where + T: Api + Clone + Send + 'static, + C: Has + Has> + Send + Sync + 'static { pub fn new(api_impl: T) -> Self { MakeService { @@ -71,45 +70,46 @@ where } } -impl<'a, T, SC, RC> hyper::service::MakeService<&'a SC> for MakeService -where - T: Api + Clone + Send + 'static, - RC: Has + Has> + 'static + Send +impl hyper::service::Service for MakeService where + T: Api + Clone + Send + 'static, + C: Has + Has> + Send + Sync + 'static { - type ReqBody = ContextualPayload; - type ResBody = Body; - type Error = Error; - type Service = Service; - type Future = future::FutureResult; - type MakeError = Error; + type Response = Service; + type Error = crate::ServiceError; + type Future = future::Ready>; - fn make_service(&mut self, _ctx: &'a SC) -> Self::Future { - future::FutureResult::from(Ok(Service::new( + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn call(&mut self, target: Target) -> Self::Future { + futures::future::ok(Service::new( self.api_impl.clone(), - ))) + )) } } -type ServiceFuture = Box, Error = Error> + Send>; - -fn method_not_allowed() -> ServiceFuture { - Box::new(future::ok( +fn method_not_allowed() -> Result, crate::ServiceError> { + Ok( Response::builder().status(StatusCode::METHOD_NOT_ALLOWED) .body(Body::empty()) .expect("Unable to create Method Not Allowed response") - )) + ) } -pub struct Service { +pub struct Service where + T: Api + Clone + Send + 'static, + C: Has + Has> + Send + Sync + 'static +{ api_impl: T, - marker: PhantomData, + marker: PhantomData, } -impl Service -where - T: Api + Clone + Send + 'static, - RC: Has + Has> + 'static { +impl Service where + T: Api + Clone + Send + 'static, + C: Has + Has> + Send + Sync + 'static +{ pub fn new(api_impl: T) -> Self { Service { api_impl: api_impl, @@ -118,23 +118,38 @@ where } } -impl hyper::service::Service for Service -where +impl Clone for Service where T: Api + Clone + Send + 'static, - C: Has + Has> + 'static + Send + C: Has + Has> + Send + Sync + 'static { - type ReqBody = ContextualPayload; - type ResBody = Body; - type Error = Error; + fn clone(&self) -> Self { + Service { + api_impl: self.api_impl.clone(), + marker: self.marker.clone(), + } + } +} + +impl hyper::service::Service<(Request, C)> for Service where + T: Api + Clone + Send + Sync + 'static, + C: Has + Has> + Send + Sync + 'static +{ + type Response = Response; + type Error = crate::ServiceError; type Future = ServiceFuture; - fn call(&mut self, req: Request) -> Self::Future { - let api_impl = self.api_impl.clone(); - let (parts, body) = req.into_parts(); + fn poll_ready(&mut self, cx: &mut Context) -> Poll> { + self.api_impl.poll_ready(cx) + } + + fn call(&mut self, req: (Request, C)) -> Self::Future { async fn run(mut api_impl: T, req: (Request, C)) -> Result, crate::ServiceError> where + T: Api + Clone + Send + 'static, + C: Has + Has> + Send + Sync + 'static + { + let (request, context) = req; + let (parts, body) = request.into_parts(); let (method, uri, headers) = (parts.method, parts.uri, parts.headers); let path = paths::GLOBAL_REGEX_SET.matches(uri.path()); - let mut context = body.context; - let body = body.inner; match &method { @@ -158,10 +173,10 @@ where Ok(result) => Some(result.0), Err(err) => { - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Invalid header Information - {}", err))) - .expect("Unable to create Bad Request response for invalid header Information"))); + .expect("Unable to create Bad Request response for invalid header Information")); }, }, @@ -170,16 +185,13 @@ where } }; - Box::new({ - {{ - Box::new( - api_impl.callback_callback_with_header_post( + let result = api_impl.callback_callback_with_header_post( callback_request_query_url, param_information, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -199,11 +211,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // CallbackCallbackPost - POST /{$request.query.url}/callback @@ -218,15 +226,12 @@ where ); let callback_request_query_url = path_params["request_query_url"].to_string(); - Box::new({ - {{ - Box::new( - api_impl.callback_callback_post( + let result = api_impl.callback_callback_post( callback_request_query_url, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -246,32 +251,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, _ if path.matched(paths::ID_REQUEST_QUERY_URL_CALLBACK) => method_not_allowed(), _ if path.matched(paths::ID_REQUEST_QUERY_URL_CALLBACK_WITH_HEADER) => method_not_allowed(), - _ => Box::new(future::ok( - Response::builder().status(StatusCode::NOT_FOUND) + _ => Ok(Response::builder().status(StatusCode::NOT_FOUND) .body(Body::empty()) - .expect("Unable to create Not Found response") - )) as Self::Future + .expect("Unable to create Not Found response")) } - } -} - -impl Clone for Service where T: Clone -{ - fn clone(&self) -> Self { - Service { - api_impl: self.api_impl.clone(), - marker: self.marker.clone(), - } - } + } Box::pin(run(self.api_impl.clone(), req)) } } /// Request parser for `Api`. diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/client/mod.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/client/mod.rs index 063ec490254..46a80096974 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/client/mod.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/client/mod.rs @@ -1,39 +1,38 @@ -use futures; -use futures::{Future, Stream, future, stream}; -use hyper; -use hyper::client::HttpConnector; +use async_trait::async_trait; +use futures::{Stream, future, future::BoxFuture, stream, future::TryFutureExt, future::FutureExt, stream::StreamExt}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; -use hyper::{Body, Uri, Response}; -#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] -use hyper_openssl::HttpsConnector; -use serde_json; +use hyper::{Body, Request, Response, service::Service, Uri}; +use percent_encoding::{utf8_percent_encode, AsciiSet}; use std::borrow::Cow; use std::convert::TryInto; -use std::io::{Read, Error, ErrorKind}; -use std::error; +use std::io::{ErrorKind, Read}; +use std::error::Error; +use std::future::Future; use std::fmt; use std::path::Path; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use std::str; use std::str::FromStr; use std::string::ToString; -use swagger; -use swagger::{ApiError, Connector, client::Service, XSpanIdString, Has, AuthData}; +use std::task::{Context, Poll}; +use swagger::{ApiError, AuthData, BodyExt, Connector, Has, XSpanIdString}; use url::form_urlencoded; -use url::percent_encoding::{utf8_percent_encode, PATH_SEGMENT_ENCODE_SET, QUERY_ENCODE_SET}; -use uuid; -use serde_xml_rs; + use crate::models; use crate::header; -url::define_encode_set! { - /// This encode set is used for object IDs - /// - /// Aside from the special characters defined in the `PATH_SEGMENT_ENCODE_SET`, - /// the vertical bar (|) is encoded. - pub ID_ENCODE_SET = [PATH_SEGMENT_ENCODE_SET] | {'|'} -} +/// https://url.spec.whatwg.org/#fragment-percent-encode-set +#[allow(dead_code)] +const FRAGMENT_ENCODE_SET: &AsciiSet = &percent_encoding::CONTROLS + .add(b' ').add(b'"').add(b'<').add(b'>').add(b'`'); + +/// This encode set is used for object IDs +/// +/// Aside from the special characters defined in the `PATH_SEGMENT_ENCODE_SET`, +/// the vertical bar (|) is encoded. +#[allow(dead_code)] +const ID_ENCODE_SET: &AsciiSet = &FRAGMENT_ENCODE_SET.add(b'|'); use crate::{Api, CallbackWithHeaderPostResponse, @@ -64,11 +63,11 @@ use crate::{Api, pub mod callbacks; /// Convert input into a base path, e.g. "http://example:123". Also checks the scheme as it goes. -fn into_base_path(input: &str, correct_scheme: Option<&'static str>) -> Result { +fn into_base_path(input: impl TryInto, correct_scheme: Option<&'static str>) -> Result { // First convert to Uri, since a base path is a subset of Uri. - let uri = Uri::from_str(input)?; + let uri = input.try_into()?; - let scheme = uri.scheme_part().ok_or(ClientInitError::InvalidScheme)?; + let scheme = uri.scheme_str().ok_or(ClientInitError::InvalidScheme)?; // Check the scheme if necessary if let Some(correct_scheme) = correct_scheme { @@ -78,38 +77,54 @@ fn into_base_path(input: &str, correct_scheme: Option<&'static str>) -> Result +pub struct Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { /// Inner service - client_service: Arc + Send + Sync>>, + client_service: S, /// Base path of the API base_path: String, } -impl fmt::Debug for Client +impl fmt::Debug for Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Client {{ base_path: {} }}", self.base_path) } } -impl Clone for Client +impl Clone for Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { fn clone(&self) -> Self { - Client { + Self { client_service: self.client_service.clone(), base_path: self.base_path.clone(), } } } -impl Client +impl Client> where + C: hyper::client::connect::Connect + Clone + Send + Sync + 'static { /// Create a client with a custom implementation of hyper::client::Connect. /// @@ -122,30 +137,93 @@ impl Client /// /// # Arguments /// - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "http://www.my-api-implementation.com" /// * `protocol` - Which protocol to use when constructing the request url, e.g. `Some("http")` /// * `connector` - Implementation of `hyper::client::Connect` to use for the client - pub fn try_new_with_connector( + pub fn try_new_with_connector( base_path: &str, protocol: Option<&'static str>, connector: C, - ) -> Result where - C: hyper::client::connect::Connect + 'static, - C::Transport: 'static, - C::Future: 'static, + ) -> Result { - let client_service = Box::new(hyper::client::Client::builder().build(connector)); + let client_service = hyper::client::Client::builder().build(connector); - Ok(Client { - client_service: Arc::new(client_service), + Ok(Self { + client_service, base_path: into_base_path(base_path, protocol)?, }) } +} +#[derive(Debug, Clone)] +pub enum HyperClient { + Http(hyper::client::Client), + Https(hyper::client::Client), +} + +impl Service> for HyperClient { + type Response = Response; + type Error = hyper::Error; + type Future = hyper::client::ResponseFuture; + + fn poll_ready(&mut self, cx: &mut Context) -> Poll> { + match self { + HyperClient::Http(client) => client.poll_ready(cx), + HyperClient::Https(client) => client.poll_ready(cx), + } + } + + fn call(&mut self, req: Request) -> Self::Future { + match self { + HyperClient::Http(client) => client.call(req), + HyperClient::Https(client) => client.call(req) + } + } +} + +impl Client { /// Create an HTTP client. /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "http://www.my-api-implementation.com" + pub fn try_new( + base_path: &str, + ) -> Result { + let uri = Uri::from_str(base_path)?; + + let scheme = uri.scheme_str().ok_or(ClientInitError::InvalidScheme)?; + let scheme = scheme.to_ascii_lowercase(); + + let connector = Connector::builder(); + + let client_service = match scheme.as_str() { + "http" => { + HyperClient::Http(hyper::client::Client::builder().build(connector.build())) + }, + "https" => { + let connector = connector.https() + .build() + .map_err(|e| ClientInitError::SslError(e))?; + HyperClient::Https(hyper::client::Client::builder().build(connector)) + }, + _ => { + return Err(ClientInitError::InvalidScheme); + } + }; + + Ok(Self { + client_service, + base_path: into_base_path(base_path, None)?, + }) + } +} + +impl Client> +{ + /// Create an HTTP client. + /// + /// # Arguments + /// * `base_path` - base path of the client API, i.e. "http://www.my-api-implementation.com" pub fn try_new_http( base_path: &str, ) -> Result { @@ -153,11 +231,20 @@ impl Client Self::try_new_with_connector(base_path, Some("http"), http_connector) } +} +#[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] +type HttpsConnector = hyper_tls::HttpsConnector; + +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +type HttpsConnector = hyper_openssl::HttpsConnector; + +impl Client> +{ /// Create a client with a TLS connection to the server /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "https://www.my-api-implementation.com" pub fn try_new_https(base_path: &str) -> Result { let https_connector = Connector::builder() @@ -170,7 +257,7 @@ impl Client /// Create a client with a TLS connection to the server using a pinned certificate /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "https://www.my-api-implementation.com" /// * `ca_certificate` - Path to CA certificate used to authenticate the server #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] pub fn try_new_https_pinned( @@ -191,7 +278,7 @@ impl Client /// Create a client with a mutually authenticated TLS connection to the server. /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "https://www.my-api-implementation.com" /// * `ca_certificate` - Path to CA certificate used to authenticate the server /// * `client_key` - Path to the client private key /// * `client_certificate` - Path to the client's public certificate associated with the private key @@ -217,17 +304,24 @@ impl Client } } -impl Client +impl Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { - /// Constructor for creating a `Client` by passing in a pre-made `swagger::Service` + /// Constructor for creating a `Client` by passing in a pre-made `hyper::service::Service` / + /// `tower::Service` /// /// This allows adding custom wrappers around the underlying transport, for example for logging. pub fn try_new_with_client_service( - client_service: Arc + Send + Sync>>, + client_service: S, base_path: &str, - ) -> Result { - Ok(Client { - client_service: client_service, + ) -> Result + { + Ok(Self { + client_service, base_path: into_base_path(base_path, None)?, }) } @@ -267,169 +361,179 @@ impl fmt::Display for ClientInitError { } } -impl error::Error for ClientInitError { +impl Error for ClientInitError { fn description(&self) -> &str { "Failed to produce a hyper client." } } -impl Api for Client where - C: Has + Has>, - F: Future, Error=hyper::Error> + Send + 'static +#[async_trait] +impl Api for Client where + C: Has + Has> + Clone + Send + Sync + 'static, + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { - fn callback_with_header_post( + fn poll_ready(&self, cx: &mut Context) -> Poll> { + match self.client_service.clone().poll_ready(cx) { + Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())), + Poll::Ready(Ok(o)) => Poll::Ready(Ok(o)), + Poll::Pending => Poll::Pending, + } + } + + async fn callback_with_header_post( &self, param_url: String, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/callback-with-header", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - query_string.append_pair("url", ¶m_url.to_string()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.append_pair("url", ¶m_url.to_string()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 204 => { - let body = response.into_body(); - Box::new( - future::ok( - CallbackWithHeaderPostResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 204 => { + let body = response.into_body(); + Ok( + CallbackWithHeaderPostResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn complex_query_param_get( + async fn complex_query_param_get( &self, param_list_of_strings: Option<&Vec>, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/complex-query-param", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - if let Some(param_list_of_strings) = param_list_of_strings { - query_string.append_pair("list-of-strings", ¶m_list_of_strings.iter().map(ToString::to_string).collect::>().join(",")); - } - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + if let Some(param_list_of_strings) = param_list_of_strings { + query_string.append_pair("list-of-strings", ¶m_list_of_strings.iter().map(ToString::to_string).collect::>().join(",")); + } + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - ComplexQueryParamGetResponse::Success - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + ComplexQueryParamGetResponse::Success + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn enum_in_path_path_param_get( + async fn enum_in_path_path_param_get( &self, param_path_param: models::StringEnum, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/enum_in_path/{path_param}", self.base_path @@ -437,102 +541,102 @@ impl Api for Client where ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - EnumInPathPathParamGetResponse::Success - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + EnumInPathPathParamGetResponse::Success + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn mandatory_request_header_get( + async fn mandatory_request_header_get( &self, param_x_header: String, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/mandatory-request-header", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); // Header parameters @@ -541,372 +645,311 @@ impl Api for Client where match header::IntoHeaderValue(param_x_header.clone()).try_into() { Ok(header) => header, Err(e) => { - return Box::new(future::err(ApiError(format!( - "Invalid header x_header - {}", e)))) as Box + Send>; + return Err(ApiError(format!( + "Invalid header x_header - {}", e))); }, }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - MandatoryRequestHeaderGetResponse::Success - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + MandatoryRequestHeaderGetResponse::Success + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn merge_patch_json_get( + async fn merge_patch_json_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/merge-patch-json", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - serde_json::from_str::(body) - .map_err(|e| e.into()) - ) - ) - .map(move |body| { - MergePatchJsonGetResponse::Merge - (body) - }) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(body)?; + Ok(MergePatchJsonGetResponse::Merge + (body) + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn multiget_get( + async fn multiget_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/multiget", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - serde_json::from_str::(body) - .map_err(|e| e.into()) - ) - ) - .map(move |body| { - MultigetGetResponse::JSONRsp - (body) - }) - ) as Box + Send> - }, - 201 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - // ToDo: this will move to swagger-rs and become a standard From conversion trait - // once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream - serde_xml_rs::from_str::(body) - .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e))) - ) - ) - .map(move |body| { - MultigetGetResponse::XMLRsp - (body) - }) - ) as Box + Send> - }, - 202 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - Ok(swagger::ByteArray(body.to_vec())) - ) - .map(move |body| { - MultigetGetResponse::OctetRsp - (body) - }) - ) as Box + Send> - }, - 203 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - Ok(body.to_string()) - ) - ) - .map(move |body| { - MultigetGetResponse::StringRsp - (body) - }) - ) as Box + Send> - }, - 204 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - serde_json::from_str::(body) - .map_err(|e| e.into()) - ) - ) - .map(move |body| { - MultigetGetResponse::DuplicateResponseLongText - (body) - }) - ) as Box + Send> - }, - 205 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - serde_json::from_str::(body) - .map_err(|e| e.into()) - ) - ) - .map(move |body| { - MultigetGetResponse::DuplicateResponseLongText_2 - (body) - }) - ) as Box + Send> - }, - 206 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - serde_json::from_str::(body) - .map_err(|e| e.into()) - ) - ) - .map(move |body| { - MultigetGetResponse::DuplicateResponseLongText_3 - (body) - }) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(body)?; + Ok(MultigetGetResponse::JSONRsp + (body) + ) } - })) + 201 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + // ToDo: this will move to swagger-rs and become a standard From conversion trait + // once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream + let body = serde_xml_rs::from_str::(body) + .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e)))?; + Ok(MultigetGetResponse::XMLRsp + (body) + ) + } + 202 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = swagger::ByteArray(body.to_vec()); + Ok(MultigetGetResponse::OctetRsp + (body) + ) + } + 203 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = body.to_string(); + Ok(MultigetGetResponse::StringRsp + (body) + ) + } + 204 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(body)?; + Ok(MultigetGetResponse::DuplicateResponseLongText + (body) + ) + } + 205 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(body)?; + Ok(MultigetGetResponse::DuplicateResponseLongText_2 + (body) + ) + } + 206 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(body)?; + Ok(MultigetGetResponse::DuplicateResponseLongText_3 + (body) + ) + } + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn multiple_auth_scheme_get( + async fn multiple_auth_scheme_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/multiple_auth_scheme", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - if let Some(auth_data) = (context as &dyn Has>).get().as_ref() { + if let Some(auth_data) = Has::>::get(context).as_ref() { // Currently only authentication with Basic and Bearer are supported match auth_data { &AuthData::Bearer(ref bearer_header) => { let auth = swagger::auth::Header(bearer_header.clone()); let header = match HeaderValue::from_str(&format!("{}", auth)) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create Authorization header: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create Authorization header: {}", e))) }; request.headers_mut().insert( hyper::header::AUTHORIZATION, @@ -916,251 +959,239 @@ impl Api for Client where } } - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - MultipleAuthSchemeGetResponse::CheckThatLimitingToMultipleRequiredAuthSchemesWorks - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + MultipleAuthSchemeGetResponse::CheckThatLimitingToMultipleRequiredAuthSchemesWorks + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn override_server_get( + async fn override_server_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/override/override-server", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 204 => { - let body = response.into_body(); - Box::new( - future::ok( - OverrideServerGetResponse::Success - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 204 => { + let body = response.into_body(); + Ok( + OverrideServerGetResponse::Success + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn paramget_get( + async fn paramget_get( &self, param_uuid: Option, param_some_object: Option, param_some_list: Option, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/paramget", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - if let Some(param_uuid) = param_uuid { - query_string.append_pair("uuid", ¶m_uuid.to_string()); - } - if let Some(param_some_object) = param_some_object { - query_string.append_pair("someObject", ¶m_some_object.to_string()); - } - if let Some(param_some_list) = param_some_list { - query_string.append_pair("someList", ¶m_some_list.to_string()); - } - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + if let Some(param_uuid) = param_uuid { + query_string.append_pair("uuid", ¶m_uuid.to_string()); + } + if let Some(param_some_object) = param_some_object { + query_string.append_pair("someObject", ¶m_some_object.to_string()); + } + if let Some(param_some_list) = param_some_list { + query_string.append_pair("someList", ¶m_some_list.to_string()); + } + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - serde_json::from_str::(body) - .map_err(|e| e.into()) - ) - ) - .map(move |body| { - ParamgetGetResponse::JSONRsp - (body) - }) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(body)?; + Ok(ParamgetGetResponse::JSONRsp + (body) + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn readonly_auth_scheme_get( + async fn readonly_auth_scheme_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/readonly_auth_scheme", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - if let Some(auth_data) = (context as &dyn Has>).get().as_ref() { + if let Some(auth_data) = Has::>::get(context).as_ref() { // Currently only authentication with Basic and Bearer are supported match auth_data { &AuthData::Bearer(ref bearer_header) => { let auth = swagger::auth::Header(bearer_header.clone()); let header = match HeaderValue::from_str(&format!("{}", auth)) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create Authorization header: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create Authorization header: {}", e))) }; request.headers_mut().insert( hyper::header::AUTHORIZATION, @@ -1170,143 +1201,139 @@ impl Api for Client where } } - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - ReadonlyAuthSchemeGetResponse::CheckThatLimitingToASingleRequiredAuthSchemeWorks - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + ReadonlyAuthSchemeGetResponse::CheckThatLimitingToASingleRequiredAuthSchemeWorks + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn register_callback_post( + async fn register_callback_post( &self, param_url: String, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/register-callback", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - query_string.append_pair("url", ¶m_url.to_string()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.append_pair("url", ¶m_url.to_string()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 204 => { - let body = response.into_body(); - Box::new( - future::ok( - RegisterCallbackPostResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 204 => { + let body = response.into_body(); + Ok( + RegisterCallbackPostResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn required_octet_stream_put( + async fn required_octet_stream_put( &self, param_body: swagger::ByteArray, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/required_octet_stream", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("PUT") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let body = param_body.0; @@ -1315,363 +1342,338 @@ impl Api for Client where let header = "application/octet-stream"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - RequiredOctetStreamPutResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + RequiredOctetStreamPutResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn responses_with_headers_get( + async fn responses_with_headers_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/responses_with_headers", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let response_success_info = match response.headers().get(HeaderName::from_static("success-info")) { - Some(response_success_info) => response_success_info.clone(), - None => return Box::new(future::err(ApiError(String::from("Required response header Success-Info for response 200 was not found.")))) as Box + Send>, - }; - let response_success_info = match TryInto::>::try_into(response_success_info) { - Ok(value) => value, - Err(e) => { - return Box::new(future::err(ApiError(format!("Invalid response header Success-Info for response 200 - {}", e)))) as Box + Send>; - }, - }; - let response_success_info = response_success_info.0; + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; - let response_bool_header = match response.headers().get(HeaderName::from_static("bool-header")) { - Some(response_bool_header) => response_bool_header.clone(), - None => return Box::new(future::err(ApiError(String::from("Required response header Bool-Header for response 200 was not found.")))) as Box + Send>, - }; - let response_bool_header = match TryInto::>::try_into(response_bool_header) { - Ok(value) => value, - Err(e) => { - return Box::new(future::err(ApiError(format!("Invalid response header Bool-Header for response 200 - {}", e)))) as Box + Send>; - }, - }; - let response_bool_header = response_bool_header.0; + match response.status().as_u16() { + 200 => { + let response_success_info = match response.headers().get(HeaderName::from_static("success-info")) { + Some(response_success_info) => response_success_info.clone(), + None => { + return Err(ApiError(String::from("Required response header Success-Info for response 200 was not found."))); + } + }; + let response_success_info = match TryInto::>::try_into(response_success_info) { + Ok(value) => value, + Err(e) => { + return Err(ApiError(format!("Invalid response header Success-Info for response 200 - {}", e))); + }, + }; + let response_success_info = response_success_info.0; - let response_object_header = match response.headers().get(HeaderName::from_static("object-header")) { - Some(response_object_header) => response_object_header.clone(), - None => return Box::new(future::err(ApiError(String::from("Required response header Object-Header for response 200 was not found.")))) as Box + Send>, - }; - let response_object_header = match TryInto::>::try_into(response_object_header) { - Ok(value) => value, - Err(e) => { - return Box::new(future::err(ApiError(format!("Invalid response header Object-Header for response 200 - {}", e)))) as Box + Send>; - }, - }; - let response_object_header = response_object_header.0; + let response_bool_header = match response.headers().get(HeaderName::from_static("bool-header")) { + Some(response_bool_header) => response_bool_header.clone(), + None => { + return Err(ApiError(String::from("Required response header Bool-Header for response 200 was not found."))); + } + }; + let response_bool_header = match TryInto::>::try_into(response_bool_header) { + Ok(value) => value, + Err(e) => { + return Err(ApiError(format!("Invalid response header Bool-Header for response 200 - {}", e))); + }, + }; + let response_bool_header = response_bool_header.0; - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - serde_json::from_str::(body) - .map_err(|e| e.into()) - ) - ) - .map(move |body| { - ResponsesWithHeadersGetResponse::Success - { - body: body, - success_info: response_success_info, - bool_header: response_bool_header, - object_header: response_object_header, - } - }) - ) as Box + Send> - }, - 412 => { - let response_further_info = match response.headers().get(HeaderName::from_static("further-info")) { - Some(response_further_info) => response_further_info.clone(), - None => return Box::new(future::err(ApiError(String::from("Required response header Further-Info for response 412 was not found.")))) as Box + Send>, - }; - let response_further_info = match TryInto::>::try_into(response_further_info) { - Ok(value) => value, - Err(e) => { - return Box::new(future::err(ApiError(format!("Invalid response header Further-Info for response 412 - {}", e)))) as Box + Send>; - }, - }; - let response_further_info = response_further_info.0; + let response_object_header = match response.headers().get(HeaderName::from_static("object-header")) { + Some(response_object_header) => response_object_header.clone(), + None => { + return Err(ApiError(String::from("Required response header Object-Header for response 200 was not found."))); + } + }; + let response_object_header = match TryInto::>::try_into(response_object_header) { + Ok(value) => value, + Err(e) => { + return Err(ApiError(format!("Invalid response header Object-Header for response 200 - {}", e))); + }, + }; + let response_object_header = response_object_header.0; - let response_failure_info = match response.headers().get(HeaderName::from_static("failure-info")) { - Some(response_failure_info) => response_failure_info.clone(), - None => return Box::new(future::err(ApiError(String::from("Required response header Failure-Info for response 412 was not found.")))) as Box + Send>, - }; - let response_failure_info = match TryInto::>::try_into(response_failure_info) { - Ok(value) => value, - Err(e) => { - return Box::new(future::err(ApiError(format!("Invalid response header Failure-Info for response 412 - {}", e)))) as Box + Send>; - }, - }; - let response_failure_info = response_failure_info.0; - - let body = response.into_body(); - Box::new( - future::ok( - ResponsesWithHeadersGetResponse::PreconditionFailed - { - further_info: response_further_info, - failure_info: response_failure_info, - } - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(body)?; + Ok(ResponsesWithHeadersGetResponse::Success + { + body: body, + success_info: response_success_info, + bool_header: response_bool_header, + object_header: response_object_header, + } + ) } - })) + 412 => { + let response_further_info = match response.headers().get(HeaderName::from_static("further-info")) { + Some(response_further_info) => response_further_info.clone(), + None => { + return Err(ApiError(String::from("Required response header Further-Info for response 412 was not found."))); + } + }; + let response_further_info = match TryInto::>::try_into(response_further_info) { + Ok(value) => value, + Err(e) => { + return Err(ApiError(format!("Invalid response header Further-Info for response 412 - {}", e))); + }, + }; + let response_further_info = response_further_info.0; + + let response_failure_info = match response.headers().get(HeaderName::from_static("failure-info")) { + Some(response_failure_info) => response_failure_info.clone(), + None => { + return Err(ApiError(String::from("Required response header Failure-Info for response 412 was not found."))); + } + }; + let response_failure_info = match TryInto::>::try_into(response_failure_info) { + Ok(value) => value, + Err(e) => { + return Err(ApiError(format!("Invalid response header Failure-Info for response 412 - {}", e))); + }, + }; + let response_failure_info = response_failure_info.0; + + let body = response.into_body(); + Ok( + ResponsesWithHeadersGetResponse::PreconditionFailed + { + further_info: response_further_info, + failure_info: response_failure_info, + } + ) + } + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn rfc7807_get( + async fn rfc7807_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/rfc7807", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 204 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - serde_json::from_str::(body) - .map_err(|e| e.into()) - ) - ) - .map(move |body| { - Rfc7807GetResponse::OK - (body) - }) - ) as Box + Send> - }, - 404 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - serde_json::from_str::(body) - .map_err(|e| e.into()) - ) - ) - .map(move |body| { - Rfc7807GetResponse::NotFound - (body) - }) - ) as Box + Send> - }, - 406 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - // ToDo: this will move to swagger-rs and become a standard From conversion trait - // once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream - serde_xml_rs::from_str::(body) - .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e))) - ) - ) - .map(move |body| { - Rfc7807GetResponse::NotAcceptable - (body) - }) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 204 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(body)?; + Ok(Rfc7807GetResponse::OK + (body) + ) } - })) + 404 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(body)?; + Ok(Rfc7807GetResponse::NotFound + (body) + ) + } + 406 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + // ToDo: this will move to swagger-rs and become a standard From conversion trait + // once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream + let body = serde_xml_rs::from_str::(body) + .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e)))?; + Ok(Rfc7807GetResponse::NotAcceptable + (body) + ) + } + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn untyped_property_get( + async fn untyped_property_get( &self, param_object_untyped_props: Option, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/untyped_property", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let body = param_object_untyped_props.map(|ref body| { @@ -1684,161 +1686,151 @@ impl Api for Client where let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - UntypedPropertyGetResponse::CheckThatUntypedPropertiesWorks - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + UntypedPropertyGetResponse::CheckThatUntypedPropertiesWorks + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn uuid_get( + async fn uuid_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/uuid", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - serde_json::from_str::(body) - .map_err(|e| e.into()) - ) - ) - .map(move |body| { - UuidGetResponse::DuplicateResponseLongText - (body) - }) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(body)?; + Ok(UuidGetResponse::DuplicateResponseLongText + (body) + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn xml_extra_post( + async fn xml_extra_post( &self, param_duplicate_xml_object: Option, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/xml_extra", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let body = param_duplicate_xml_object.map(|ref body| { @@ -1851,86 +1843,82 @@ impl Api for Client where let header = "application/xml"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 201 => { - let body = response.into_body(); - Box::new( - future::ok( - XmlExtraPostResponse::OK - ) - ) as Box + Send> - }, - 400 => { - let body = response.into_body(); - Box::new( - future::ok( - XmlExtraPostResponse::BadRequest - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 201 => { + let body = response.into_body(); + Ok( + XmlExtraPostResponse::OK + ) } - })) + 400 => { + let body = response.into_body(); + Ok( + XmlExtraPostResponse::BadRequest + ) + } + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn xml_other_post( + async fn xml_other_post( &self, param_another_xml_object: Option, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/xml_other", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let body = param_another_xml_object.map(|ref body| { @@ -1943,100 +1931,91 @@ impl Api for Client where let header = "text/xml"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 201 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - // ToDo: this will move to swagger-rs and become a standard From conversion trait - // once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream - serde_xml_rs::from_str::(body) - .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e))) - ) - ) - .map(move |body| { - XmlOtherPostResponse::OK - (body) - }) - ) as Box + Send> - }, - 400 => { - let body = response.into_body(); - Box::new( - future::ok( - XmlOtherPostResponse::BadRequest - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 201 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + // ToDo: this will move to swagger-rs and become a standard From conversion trait + // once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream + let body = serde_xml_rs::from_str::(body) + .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e)))?; + Ok(XmlOtherPostResponse::OK + (body) + ) } - })) + 400 => { + let body = response.into_body(); + Ok( + XmlOtherPostResponse::BadRequest + ) + } + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn xml_other_put( + async fn xml_other_put( &self, param_another_xml_array: Option, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/xml_other", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("PUT") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let body = param_another_xml_array.map(|ref body| { @@ -2049,86 +2028,82 @@ impl Api for Client where let header = "application/xml"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 201 => { - let body = response.into_body(); - Box::new( - future::ok( - XmlOtherPutResponse::OK - ) - ) as Box + Send> - }, - 400 => { - let body = response.into_body(); - Box::new( - future::ok( - XmlOtherPutResponse::BadRequest - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 201 => { + let body = response.into_body(); + Ok( + XmlOtherPutResponse::OK + ) } - })) + 400 => { + let body = response.into_body(); + Ok( + XmlOtherPutResponse::BadRequest + ) + } + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn xml_post( + async fn xml_post( &self, param_xml_array: Option, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/xml", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let body = param_xml_array.map(|ref body| { @@ -2141,86 +2116,82 @@ impl Api for Client where let header = "application/xml"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 201 => { - let body = response.into_body(); - Box::new( - future::ok( - XmlPostResponse::OK - ) - ) as Box + Send> - }, - 400 => { - let body = response.into_body(); - Box::new( - future::ok( - XmlPostResponse::BadRequest - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 201 => { + let body = response.into_body(); + Ok( + XmlPostResponse::OK + ) } - })) + 400 => { + let body = response.into_body(); + Ok( + XmlPostResponse::BadRequest + ) + } + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn xml_put( + async fn xml_put( &self, param_xml_object: Option, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/xml", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("PUT") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let body = param_xml_object.map(|ref body| { @@ -2234,87 +2205,83 @@ impl Api for Client where let header = "application/xml"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 201 => { - let body = response.into_body(); - Box::new( - future::ok( - XmlPutResponse::OK - ) - ) as Box + Send> - }, - 400 => { - let body = response.into_body(); - Box::new( - future::ok( - XmlPutResponse::BadRequest - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 201 => { + let body = response.into_body(); + Ok( + XmlPutResponse::OK + ) } - })) + 400 => { + let body = response.into_body(); + Ok( + XmlPutResponse::BadRequest + ) + } + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn create_repo( + async fn create_repo( &self, param_object_param: models::ObjectParam, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/repos", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; // Body parameter @@ -2324,54 +2291,50 @@ impl Api for Client where let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - CreateRepoResponse::Success - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + CreateRepoResponse::Success + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn get_repo_info( + async fn get_repo_info( &self, param_repo_id: String, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/repos/{repo_id}", self.base_path @@ -2379,77 +2342,68 @@ impl Api for Client where ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - serde_json::from_str::(body) - .map_err(|e| e.into()) - ) - ) - .map(move |body| { - GetRepoInfoResponse::OK - (body) - }) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(body)?; + Ok(GetRepoInfoResponse::OK + (body) + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } } diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/context.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/context.rs index 3f15f7b0a77..6f030053252 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/context.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/context.rs @@ -1,13 +1,12 @@ -use futures::Future; -use hyper; +use futures::future::BoxFuture; use hyper::header::HeaderName; -use hyper::{Error, Request, Response, StatusCode, service::Service, body::Payload}; +use hyper::{Error, Request, Response, StatusCode, service::Service}; use url::form_urlencoded; use std::default::Default; use std::io; use std::marker::PhantomData; +use std::task::{Poll, Context}; use swagger::auth::{AuthData, Authorization, Bearer, Scopes}; -use swagger::context::ContextualPayload; use swagger::{EmptyContext, Has, Pop, Push, XSpanIdString}; use crate::Api; @@ -31,58 +30,52 @@ where } // Make a service that adds context. -impl<'a, T, SC, A, B, C, D, E, ME, S, OB, F> hyper::service::MakeService<&'a SC> for +impl Service for MakeAddContext where - A: Default + Push, + Target: Send, + A: Default + Push + Send, B: Push, Result = C>, C: Push, Result = D>, D: Send + 'static, - T: hyper::service::MakeService< - &'a SC, - Error = E, - MakeError = ME, - Service = S, - ReqBody = ContextualPayload, - ResBody = OB, - Future = F - >, - S: Service< - Error = E, - ReqBody = ContextualPayload, - ResBody = OB> + 'static, - ME: swagger::ErrorBound, - E: swagger::ErrorBound, - F: Future + Send + 'static, - S::Future: Send, - OB: Payload, + T: Service + Send, + T::Future: Send + 'static { - type ReqBody = hyper::Body; - type ResBody = OB; - type Error = E; - type MakeError = ME; - type Service = AddContext; - type Future = Box + Send + 'static>; + type Error = T::Error; + type Response = AddContext; + type Future = BoxFuture<'static, Result>; - fn make_service(&mut self, ctx: &'a SC) -> Self::Future { - Box::new(self.inner.make_service(ctx).map(|s| AddContext::new(s))) + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + self.inner.poll_ready(cx) + } + + fn call(&mut self, target: Target) -> Self::Future { + let service = self.inner.call(target); + + Box::pin(async move { + Ok(AddContext::new(service.await?)) + }) } } -/// Middleware to extract authentication data from request -pub struct AddContext { +/// Middleware to add context data from the request +pub struct AddContext +where + A: Default + Push, + B: Push, Result = C>, + C: Push, Result = D> +{ inner: T, marker: PhantomData, } -impl AddContext +impl AddContext where A: Default + Push, B: Push, Result = C>, C: Push, Result = D>, - T: Service, { - pub fn new(inner: T) -> AddContext { + pub fn new(inner: T) -> Self { AddContext { inner, marker: PhantomData, @@ -90,24 +83,26 @@ where } } -impl Service for AddContext +impl Service> for AddContext where A: Default + Push, B: Push, Result=C>, C: Push, Result=D>, D: Send + 'static, - T: Service>, - T::Future: Future, Error=T::Error> + Send + 'static + T: Service<(Request, D)> { - type ReqBody = hyper::Body; - type ResBody = T::ResBody; type Error = T::Error; - type Future = Box, Error=T::Error> + Send + 'static>; + type Future = T::Future; + type Response = T::Response; - fn call(&mut self, req: Request) -> Self::Future { - let context = A::default().push(XSpanIdString::get_or_generate(&req)); - let (head, body) = req.into_parts(); - let headers = head.headers.clone(); + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + self.inner.poll_ready(cx) + } + + + fn call(&mut self, request: Request) -> Self::Future { + let context = A::default().push(XSpanIdString::get_or_generate(&request)); + let headers = request.headers(); { use swagger::auth::Bearer; @@ -117,22 +112,13 @@ impl Service for AddContext let context = context.push(Some(auth_data)); let context = context.push(None::); - let body = ContextualPayload { - inner: body, - context: context, - }; - - return Box::new(self.inner.call(hyper::Request::from_parts(head, body))); + return self.inner.call((request, context)) } } let context = context.push(None::); let context = context.push(None::); - let body = ContextualPayload { - inner: body, - context: context, - }; - Box::new(self.inner.call(hyper::Request::from_parts(head, body))) + self.inner.call((request, context)) } } diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/lib.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/lib.rs index 1f786e6fbfe..fee0011bc98 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/lib.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/lib.rs @@ -1,12 +1,12 @@ #![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)] +use async_trait::async_trait; use futures::Stream; -use std::io::Error; +use std::error::Error; +use std::task::{Poll, Context}; +use swagger::{ApiError, ContextWrapper}; -#[deprecated(note = "Import swagger-rs directly")] -pub use swagger::{ApiError, ContextWrapper}; -#[deprecated(note = "Import futures directly")] -pub use futures::Future; +type ServiceError = Box; pub const BASE_PATH: &'static str = ""; pub const API_VERSION: &'static str = "1.0.7"; @@ -225,433 +225,478 @@ pub enum GetRepoInfoResponse { } /// API -pub trait Api { - fn callback_with_header_post( +#[async_trait] +pub trait Api { + fn poll_ready(&self, _cx: &mut Context) -> Poll>> { + Poll::Ready(Ok(())) + } + + async fn callback_with_header_post( &self, url: String, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn complex_query_param_get( + async fn complex_query_param_get( &self, list_of_strings: Option<&Vec>, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn enum_in_path_path_param_get( + async fn enum_in_path_path_param_get( &self, path_param: models::StringEnum, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn mandatory_request_header_get( + async fn mandatory_request_header_get( &self, x_header: String, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn merge_patch_json_get( + async fn merge_patch_json_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Get some stuff. - fn multiget_get( + async fn multiget_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn multiple_auth_scheme_get( + async fn multiple_auth_scheme_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn override_server_get( + async fn override_server_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Get some stuff with parameters. - fn paramget_get( + async fn paramget_get( &self, uuid: Option, some_object: Option, some_list: Option, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn readonly_auth_scheme_get( + async fn readonly_auth_scheme_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn register_callback_post( + async fn register_callback_post( &self, url: String, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn required_octet_stream_put( + async fn required_octet_stream_put( &self, body: swagger::ByteArray, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn responses_with_headers_get( + async fn responses_with_headers_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn rfc7807_get( + async fn rfc7807_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn untyped_property_get( + async fn untyped_property_get( &self, object_untyped_props: Option, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn uuid_get( + async fn uuid_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn xml_extra_post( + async fn xml_extra_post( &self, duplicate_xml_object: Option, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn xml_other_post( + async fn xml_other_post( &self, another_xml_object: Option, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn xml_other_put( + async fn xml_other_put( &self, another_xml_array: Option, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Post an array - fn xml_post( + async fn xml_post( &self, xml_array: Option, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn xml_put( + async fn xml_put( &self, xml_object: Option, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn create_repo( + async fn create_repo( &self, object_param: models::ObjectParam, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn get_repo_info( + async fn get_repo_info( &self, repo_id: String, - context: &C) -> Box + Send>; + context: &C) -> Result; } -/// API without a `Context` -pub trait ApiNoContext { - fn callback_with_header_post( +/// API where `Context` isn't passed on every API call +#[async_trait] +pub trait ApiNoContext { + + fn poll_ready(&self, _cx: &mut Context) -> Poll>>; + + fn context(&self) -> &C; + + async fn callback_with_header_post( &self, url: String, - ) -> Box + Send>; + ) -> Result; - fn complex_query_param_get( + async fn complex_query_param_get( &self, list_of_strings: Option<&Vec>, - ) -> Box + Send>; + ) -> Result; - fn enum_in_path_path_param_get( + async fn enum_in_path_path_param_get( &self, path_param: models::StringEnum, - ) -> Box + Send>; + ) -> Result; - fn mandatory_request_header_get( + async fn mandatory_request_header_get( &self, x_header: String, - ) -> Box + Send>; + ) -> Result; - fn merge_patch_json_get( + async fn merge_patch_json_get( &self, - ) -> Box + Send>; + ) -> Result; /// Get some stuff. - fn multiget_get( + async fn multiget_get( &self, - ) -> Box + Send>; + ) -> Result; - fn multiple_auth_scheme_get( + async fn multiple_auth_scheme_get( &self, - ) -> Box + Send>; + ) -> Result; - fn override_server_get( + async fn override_server_get( &self, - ) -> Box + Send>; + ) -> Result; /// Get some stuff with parameters. - fn paramget_get( + async fn paramget_get( &self, uuid: Option, some_object: Option, some_list: Option, - ) -> Box + Send>; + ) -> Result; - fn readonly_auth_scheme_get( + async fn readonly_auth_scheme_get( &self, - ) -> Box + Send>; + ) -> Result; - fn register_callback_post( + async fn register_callback_post( &self, url: String, - ) -> Box + Send>; + ) -> Result; - fn required_octet_stream_put( + async fn required_octet_stream_put( &self, body: swagger::ByteArray, - ) -> Box + Send>; + ) -> Result; - fn responses_with_headers_get( + async fn responses_with_headers_get( &self, - ) -> Box + Send>; + ) -> Result; - fn rfc7807_get( + async fn rfc7807_get( &self, - ) -> Box + Send>; + ) -> Result; - fn untyped_property_get( + async fn untyped_property_get( &self, object_untyped_props: Option, - ) -> Box + Send>; + ) -> Result; - fn uuid_get( + async fn uuid_get( &self, - ) -> Box + Send>; + ) -> Result; - fn xml_extra_post( + async fn xml_extra_post( &self, duplicate_xml_object: Option, - ) -> Box + Send>; + ) -> Result; - fn xml_other_post( + async fn xml_other_post( &self, another_xml_object: Option, - ) -> Box + Send>; + ) -> Result; - fn xml_other_put( + async fn xml_other_put( &self, another_xml_array: Option, - ) -> Box + Send>; + ) -> Result; /// Post an array - fn xml_post( + async fn xml_post( &self, xml_array: Option, - ) -> Box + Send>; + ) -> Result; - fn xml_put( + async fn xml_put( &self, xml_object: Option, - ) -> Box + Send>; + ) -> Result; - fn create_repo( + async fn create_repo( &self, object_param: models::ObjectParam, - ) -> Box + Send>; + ) -> Result; - fn get_repo_info( + async fn get_repo_info( &self, repo_id: String, - ) -> Box + Send>; + ) -> Result; } /// Trait to extend an API to make it easy to bind it to a context. -pub trait ContextWrapperExt<'a, C> where Self: Sized { +pub trait ContextWrapperExt where Self: Sized +{ /// Binds this API to a context. - fn with_context(self: &'a Self, context: C) -> ContextWrapper<'a, Self, C>; + fn with_context(self: Self, context: C) -> ContextWrapper; } -impl<'a, T: Api + Sized, C> ContextWrapperExt<'a, C> for T { - fn with_context(self: &'a T, context: C) -> ContextWrapper<'a, T, C> { +impl + Send + Sync, C: Clone + Send + Sync> ContextWrapperExt for T { + fn with_context(self: T, context: C) -> ContextWrapper { ContextWrapper::::new(self, context) } } -impl<'a, T: Api, C> ApiNoContext for ContextWrapper<'a, T, C> { - fn callback_with_header_post( +#[async_trait] +impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for ContextWrapper { + fn poll_ready(&self, cx: &mut Context) -> Poll> { + self.api().poll_ready(cx) + } + + fn context(&self) -> &C { + ContextWrapper::context(self) + } + + async fn callback_with_header_post( &self, url: String, - ) -> Box + Send> + ) -> Result { - self.api().callback_with_header_post(url, &self.context()) + let context = self.context().clone(); + self.api().callback_with_header_post(url, &context).await } - fn complex_query_param_get( + async fn complex_query_param_get( &self, list_of_strings: Option<&Vec>, - ) -> Box + Send> + ) -> Result { - self.api().complex_query_param_get(list_of_strings, &self.context()) + let context = self.context().clone(); + self.api().complex_query_param_get(list_of_strings, &context).await } - fn enum_in_path_path_param_get( + async fn enum_in_path_path_param_get( &self, path_param: models::StringEnum, - ) -> Box + Send> + ) -> Result { - self.api().enum_in_path_path_param_get(path_param, &self.context()) + let context = self.context().clone(); + self.api().enum_in_path_path_param_get(path_param, &context).await } - fn mandatory_request_header_get( + async fn mandatory_request_header_get( &self, x_header: String, - ) -> Box + Send> + ) -> Result { - self.api().mandatory_request_header_get(x_header, &self.context()) + let context = self.context().clone(); + self.api().mandatory_request_header_get(x_header, &context).await } - fn merge_patch_json_get( + async fn merge_patch_json_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().merge_patch_json_get(&self.context()) + let context = self.context().clone(); + self.api().merge_patch_json_get(&context).await } /// Get some stuff. - fn multiget_get( + async fn multiget_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().multiget_get(&self.context()) + let context = self.context().clone(); + self.api().multiget_get(&context).await } - fn multiple_auth_scheme_get( + async fn multiple_auth_scheme_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().multiple_auth_scheme_get(&self.context()) + let context = self.context().clone(); + self.api().multiple_auth_scheme_get(&context).await } - fn override_server_get( + async fn override_server_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().override_server_get(&self.context()) + let context = self.context().clone(); + self.api().override_server_get(&context).await } /// Get some stuff with parameters. - fn paramget_get( + async fn paramget_get( &self, uuid: Option, some_object: Option, some_list: Option, - ) -> Box + Send> + ) -> Result { - self.api().paramget_get(uuid, some_object, some_list, &self.context()) + let context = self.context().clone(); + self.api().paramget_get(uuid, some_object, some_list, &context).await } - fn readonly_auth_scheme_get( + async fn readonly_auth_scheme_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().readonly_auth_scheme_get(&self.context()) + let context = self.context().clone(); + self.api().readonly_auth_scheme_get(&context).await } - fn register_callback_post( + async fn register_callback_post( &self, url: String, - ) -> Box + Send> + ) -> Result { - self.api().register_callback_post(url, &self.context()) + let context = self.context().clone(); + self.api().register_callback_post(url, &context).await } - fn required_octet_stream_put( + async fn required_octet_stream_put( &self, body: swagger::ByteArray, - ) -> Box + Send> + ) -> Result { - self.api().required_octet_stream_put(body, &self.context()) + let context = self.context().clone(); + self.api().required_octet_stream_put(body, &context).await } - fn responses_with_headers_get( + async fn responses_with_headers_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().responses_with_headers_get(&self.context()) + let context = self.context().clone(); + self.api().responses_with_headers_get(&context).await } - fn rfc7807_get( + async fn rfc7807_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().rfc7807_get(&self.context()) + let context = self.context().clone(); + self.api().rfc7807_get(&context).await } - fn untyped_property_get( + async fn untyped_property_get( &self, object_untyped_props: Option, - ) -> Box + Send> + ) -> Result { - self.api().untyped_property_get(object_untyped_props, &self.context()) + let context = self.context().clone(); + self.api().untyped_property_get(object_untyped_props, &context).await } - fn uuid_get( + async fn uuid_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().uuid_get(&self.context()) + let context = self.context().clone(); + self.api().uuid_get(&context).await } - fn xml_extra_post( + async fn xml_extra_post( &self, duplicate_xml_object: Option, - ) -> Box + Send> + ) -> Result { - self.api().xml_extra_post(duplicate_xml_object, &self.context()) + let context = self.context().clone(); + self.api().xml_extra_post(duplicate_xml_object, &context).await } - fn xml_other_post( + async fn xml_other_post( &self, another_xml_object: Option, - ) -> Box + Send> + ) -> Result { - self.api().xml_other_post(another_xml_object, &self.context()) + let context = self.context().clone(); + self.api().xml_other_post(another_xml_object, &context).await } - fn xml_other_put( + async fn xml_other_put( &self, another_xml_array: Option, - ) -> Box + Send> + ) -> Result { - self.api().xml_other_put(another_xml_array, &self.context()) + let context = self.context().clone(); + self.api().xml_other_put(another_xml_array, &context).await } /// Post an array - fn xml_post( + async fn xml_post( &self, xml_array: Option, - ) -> Box + Send> + ) -> Result { - self.api().xml_post(xml_array, &self.context()) + let context = self.context().clone(); + self.api().xml_post(xml_array, &context).await } - fn xml_put( + async fn xml_put( &self, xml_object: Option, - ) -> Box + Send> + ) -> Result { - self.api().xml_put(xml_object, &self.context()) + let context = self.context().clone(); + self.api().xml_put(xml_object, &context).await } - fn create_repo( + async fn create_repo( &self, object_param: models::ObjectParam, - ) -> Box + Send> + ) -> Result { - self.api().create_repo(object_param, &self.context()) + let context = self.context().clone(); + self.api().create_repo(object_param, &context).await } - fn get_repo_info( + async fn get_repo_info( &self, repo_id: String, - ) -> Box + Send> + ) -> Result { - self.api().get_repo_info(repo_id, &self.context()) + let context = self.context().clone(); + self.api().get_repo_info(repo_id, &context).await } } + #[derive(Debug, PartialEq)] pub enum CallbackCallbackWithHeaderPostResponse { /// OK @@ -666,68 +711,89 @@ pub enum CallbackCallbackPostResponse { /// Callback API -pub trait CallbackApi { - fn callback_callback_with_header_post( +#[async_trait] +pub trait CallbackApi { + fn poll_ready(&self, _cx: &mut Context) -> Poll>> { + Poll::Ready(Ok(())) + } + + async fn callback_callback_with_header_post( &self, callback_request_query_url: String, information: Option, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn callback_callback_post( + async fn callback_callback_post( &self, callback_request_query_url: String, - context: &C) -> Box + Send>; + context: &C) -> Result; } /// Callback API without a `Context` -pub trait CallbackApiNoContext { - fn callback_callback_with_header_post( +#[async_trait] +pub trait CallbackApiNoContext { + fn poll_ready(&self, _cx: &mut Context) -> Poll>>; + + fn context(&self) -> &C; + + async fn callback_callback_with_header_post( &self, callback_request_query_url: String, information: Option, - ) -> Box + Send>; + ) -> Result; - fn callback_callback_post( + async fn callback_callback_post( &self, callback_request_query_url: String, - ) -> Box + Send>; + ) -> Result; } -/// Trait to extend an API to make it easy to bind it to a context. -pub trait CallbackContextWrapperExt<'a, C> where Self: Sized { +pub trait CallbackContextWrapperExt where Self: Sized +{ /// Binds this API to a context. - fn with_context(self: &'a Self, context: C) -> ContextWrapper<'a, Self, C>; + fn with_context(self: Self, context: C) -> ContextWrapper; } -impl<'a, T: CallbackApi + Sized, C> CallbackContextWrapperExt<'a, C> for T { - fn with_context(self: &'a T, context: C) -> ContextWrapper<'a, T, C> { +impl + Send + Sync, C: Clone + Send + Sync> CallbackContextWrapperExt for T { + fn with_context(self: T, context: C) -> ContextWrapper { ContextWrapper::::new(self, context) } } -impl<'a, T: CallbackApi, C> CallbackApiNoContext for ContextWrapper<'a, T, C> { - fn callback_callback_with_header_post( +#[async_trait] +impl + Send + Sync, C: Clone + Send + Sync> CallbackApiNoContext for ContextWrapper { + fn poll_ready(&self, cx: &mut Context) -> Poll> { + self.api().poll_ready(cx) + } + + fn context(&self) -> &C { + ContextWrapper::context(self) + } + + async fn callback_callback_with_header_post( &self, callback_request_query_url: String, information: Option, - ) -> Box + Send> + ) -> Result { + let context = self.context().clone(); self.api().callback_callback_with_header_post( callback_request_query_url, information, - &self.context()) + &context).await } - fn callback_callback_post( + async fn callback_callback_post( &self, callback_request_query_url: String, - ) -> Box + Send> + ) -> Result { + let context = self.context().clone(); self.api().callback_callback_post( callback_request_query_url, - &self.context()) + &context).await } } diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/server/callbacks.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/server/callbacks.rs index 1d52c326e27..0f3ab78824a 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/server/callbacks.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/server/callbacks.rs @@ -1,68 +1,83 @@ -use futures; -use futures::{Future, Stream, future, stream}; -use hyper; -use hyper::client::HttpConnector; +use async_trait::async_trait; +use futures::{Stream, future, future::BoxFuture, stream, future::TryFutureExt, future::FutureExt, stream::StreamExt}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; -use hyper::{Body, Uri, Response}; -#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] -use hyper_openssl::HttpsConnector; -use serde_json; +use hyper::{Body, Request, Response, service::Service, Uri}; +use percent_encoding::{utf8_percent_encode, AsciiSet}; use std::borrow::Cow; use std::convert::TryInto; -use std::io::{Read, Error, ErrorKind}; -use std::error; +use std::io::{ErrorKind, Read}; +use std::error::Error; +use std::future::Future; use std::fmt; use std::path::Path; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use std::str; use std::str::FromStr; use std::string::ToString; -use swagger; -use swagger::{ApiError, Connector, client::Service, XSpanIdString, Has, AuthData}; +use std::task::{Context, Poll}; +use swagger::{ApiError, AuthData, BodyExt, Connector, Has, XSpanIdString}; use url::form_urlencoded; -use url::percent_encoding::{utf8_percent_encode, PATH_SEGMENT_ENCODE_SET, QUERY_ENCODE_SET}; -use uuid; -use serde_xml_rs; + use crate::models; use crate::header; -url::define_encode_set! { - /// This encode set is used for object IDs - /// - /// Aside from the special characters defined in the `PATH_SEGMENT_ENCODE_SET`, - /// the vertical bar (|) is encoded. - pub ID_ENCODE_SET = [PATH_SEGMENT_ENCODE_SET] | {'|'} -} +/// https://url.spec.whatwg.org/#fragment-percent-encode-set +#[allow(dead_code)] +const FRAGMENT_ENCODE_SET: &AsciiSet = &percent_encoding::CONTROLS + .add(b' ').add(b'"').add(b'<').add(b'>').add(b'`'); + +/// This encode set is used for object IDs +/// +/// Aside from the special characters defined in the `PATH_SEGMENT_ENCODE_SET`, +/// the vertical bar (|) is encoded. +#[allow(dead_code)] +const ID_ENCODE_SET: &AsciiSet = &FRAGMENT_ENCODE_SET.add(b'|'); use crate::CallbackApi; use crate::CallbackCallbackWithHeaderPostResponse; use crate::CallbackCallbackPostResponse; /// A client that implements the API by making HTTP calls out to a server. -pub struct Client +pub struct Client where + S: Service< + Request, + Response=Response, + Error=hyper::Error> + Clone + Send + Sync, + S::Future: Send + 'static, { /// Inner service - client_service: Arc + Send + Sync>>, + client_service: S, } -impl fmt::Debug for Client +impl fmt::Debug for Client where + S: Service< + Request, + Response=Response, + Error=hyper::Error> + Clone + Send + Sync, + S::Future: Send + 'static, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Client") } } -impl Clone for Client +impl Clone for Client where + S: Service< + Request, + Response=Response, + Error=hyper::Error> + Clone + Send + Sync, + S::Future: Send + 'static, { fn clone(&self) -> Self { - Client { + Self { client_service: self.client_service.clone(), } } } -impl Client +impl Client> where + C: hyper::client::connect::Connect + Clone + Send + Sync + 'static { /// Create a client with a custom implementation of hyper::client::Connect. /// @@ -76,26 +91,33 @@ impl Client /// # Arguments /// /// * `connector` - Implementation of `hyper::client::Connect` to use for the client - pub fn new_with_connector( - connector: C, - ) -> Self where - C: hyper::client::connect::Connect + 'static, - C::Transport: 'static, - C::Future: 'static, + pub fn new_with_connector(connector: C) -> Self { - let client_service = Box::new(hyper::client::Client::builder().build(connector)); + let client_service = hyper::client::Client::builder().build(connector); - Client { - client_service: Arc::new(client_service), + Self { + client_service, } } +} +impl Client> +{ /// Create an HTTP client. pub fn new_http() -> Self { let http_connector = Connector::builder().build(); Self::new_with_connector(http_connector) } +} +#[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] +type HttpConnector = hyper_tls::HttpsConnector; + +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +type HttpsConnector = hyper_openssl::HttpsConnector; + +impl Client> +{ /// Create a client with a TLS connection to the server. #[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] pub fn new_https() -> Result @@ -155,60 +177,82 @@ impl Client } } -impl Client +impl Client where + S: Service< + Request, + Response=Response, + Error=hyper::Error> + Clone + Send + Sync, + S::Future: Send + 'static, { /// Constructor for creating a `Client` by passing in a pre-made `swagger::Service` /// /// This allows adding custom wrappers around the underlying transport, for example for logging. pub fn new_with_client_service( - client_service: Arc + Send + Sync>>, + client_service: S, ) -> Self { Client { - client_service: client_service, + client_service, } } } -impl CallbackApi for Client where - C: Has + Has>, - F: Future, Error=hyper::Error> + Send + 'static +#[async_trait] +impl CallbackApi for Client where + C: Has + Has> + Send + Sync, + S: Service< + Request, + Response=Response, + Error=hyper::Error> + Clone + Send + Sync, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { - fn callback_callback_with_header_post( + fn poll_ready(&self, cx: &mut Context) -> Poll> { + match self.client_service.clone().poll_ready(cx) { + Poll::Ready(Err(e)) => Poll::Ready(Err(Box::new(e))), + Poll::Ready(Ok(o)) => Poll::Ready(Ok(o)), + Poll::Pending => Poll::Pending, + } + } + + async fn callback_callback_with_header_post( &self, callback_request_query_url: String, param_information: Option, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{request_query_url}/callback-with-header" ,request_query_url=callback_request_query_url ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); // Header parameters @@ -219,119 +263,112 @@ impl CallbackApi for Client where match header::IntoHeaderValue(param_information.clone()).try_into() { Ok(header) => header, Err(e) => { - return Box::new(future::err(ApiError(format!( - "Invalid header information - {}", e)))) as Box + Send>; + return Err(ApiError(format!( + "Invalid header information - {}", e))); }, }); }, None => {} } - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 204 => { - let body = response.into_body(); - Box::new( - future::ok( - CallbackCallbackWithHeaderPostResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 204 => { + let body = response.into_body(); + Ok( + CallbackCallbackWithHeaderPostResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn callback_callback_post( + async fn callback_callback_post( &self, callback_request_query_url: String, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{request_query_url}/callback" ,request_query_url=callback_request_query_url ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 204 => { - let body = response.into_body(); - Box::new( - future::ok( - CallbackCallbackPostResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 204 => { + let body = response.into_body(); + Ok( + CallbackCallbackPostResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } } diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/server/mod.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/server/mod.rs index c13904fe064..1244ae2af5b 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/server/mod.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/server/mod.rs @@ -1,22 +1,17 @@ -use std::marker::PhantomData; -use futures::{Future, future, Stream, stream}; -use hyper; -use hyper::{Request, Response, Error, StatusCode, Body, HeaderMap}; +use futures::{future, future::BoxFuture, Stream, stream, future::FutureExt, stream::TryStreamExt}; +use hyper::{Request, Response, StatusCode, Body, HeaderMap}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; use log::warn; -use serde_json; #[allow(unused_imports)] use std::convert::{TryFrom, TryInto}; -use std::io; -use url::form_urlencoded; -#[allow(unused_imports)] -use swagger; -use swagger::{ApiError, XSpanIdString, Has, RequestParser}; +use std::error::Error; +use std::future::Future; +use std::marker::PhantomData; +use std::task::{Context, Poll}; +use swagger::{ApiError, BodyExt, Has, RequestParser, XSpanIdString}; pub use swagger::auth::Authorization; use swagger::auth::Scopes; -use swagger::context::ContextualPayload; -use uuid; -use serde_xml_rs; +use url::form_urlencoded; #[allow(unused_imports)] use crate::models; @@ -24,6 +19,8 @@ use crate::header; pub use crate::context; +type ServiceFuture = BoxFuture<'static, Result, crate::ServiceError>>; + use crate::{Api, CallbackWithHeaderPostResponse, ComplexQueryParamGetResponse, @@ -114,15 +111,17 @@ mod paths { pub(crate) static ID_XML_OTHER: usize = 20; } -pub struct MakeService { +pub struct MakeService where + T: Api + Clone + Send + 'static, + C: Has + Has> + Send + Sync + 'static +{ api_impl: T, - marker: PhantomData, + marker: PhantomData, } -impl MakeService -where - T: Api + Clone + Send + 'static, - RC: Has + Has> + 'static +impl MakeService where + T: Api + Clone + Send + 'static, + C: Has + Has> + Send + Sync + 'static { pub fn new(api_impl: T) -> Self { MakeService { @@ -132,44 +131,45 @@ where } } -impl<'a, T, SC, RC> hyper::service::MakeService<&'a SC> for MakeService -where - T: Api + Clone + Send + 'static, - RC: Has + Has> + 'static + Send +impl hyper::service::Service for MakeService where + T: Api + Clone + Send + 'static, + C: Has + Has> + Send + Sync + 'static { - type ReqBody = ContextualPayload; - type ResBody = Body; - type Error = Error; - type Service = Service; - type Future = future::FutureResult; - type MakeError = Error; + type Response = Service; + type Error = crate::ServiceError; + type Future = future::Ready>; - fn make_service(&mut self, _ctx: &'a SC) -> Self::Future { - future::FutureResult::from(Ok(Service::new( + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn call(&mut self, target: Target) -> Self::Future { + futures::future::ok(Service::new( self.api_impl.clone(), - ))) + )) } } -type ServiceFuture = Box, Error = Error> + Send>; - -fn method_not_allowed() -> ServiceFuture { - Box::new(future::ok( +fn method_not_allowed() -> Result, crate::ServiceError> { + Ok( Response::builder().status(StatusCode::METHOD_NOT_ALLOWED) .body(Body::empty()) .expect("Unable to create Method Not Allowed response") - )) + ) } -pub struct Service { +pub struct Service where + T: Api + Clone + Send + 'static, + C: Has + Has> + Send + Sync + 'static +{ api_impl: T, - marker: PhantomData, + marker: PhantomData, } -impl Service -where - T: Api + Clone + Send + 'static, - RC: Has + Has> + 'static { +impl Service where + T: Api + Clone + Send + 'static, + C: Has + Has> + Send + Sync + 'static +{ pub fn new(api_impl: T) -> Self { Service { api_impl: api_impl, @@ -178,23 +178,38 @@ where } } -impl hyper::service::Service for Service -where +impl Clone for Service where T: Api + Clone + Send + 'static, - C: Has + Has> + 'static + Send + C: Has + Has> + Send + Sync + 'static { - type ReqBody = ContextualPayload; - type ResBody = Body; - type Error = Error; + fn clone(&self) -> Self { + Service { + api_impl: self.api_impl.clone(), + marker: self.marker.clone(), + } + } +} + +impl hyper::service::Service<(Request, C)> for Service where + T: Api + Clone + Send + Sync + 'static, + C: Has + Has> + Send + Sync + 'static +{ + type Response = Response; + type Error = crate::ServiceError; type Future = ServiceFuture; - fn call(&mut self, req: Request) -> Self::Future { - let api_impl = self.api_impl.clone(); - let (parts, body) = req.into_parts(); + fn poll_ready(&mut self, cx: &mut Context) -> Poll> { + self.api_impl.poll_ready(cx) + } + + fn call(&mut self, req: (Request, C)) -> Self::Future { async fn run(mut api_impl: T, req: (Request, C)) -> Result, crate::ServiceError> where + T: Api + Clone + Send + 'static, + C: Has + Has> + Send + Sync + 'static + { + let (request, context) = req; + let (parts, body) = request.into_parts(); let (method, uri, headers) = (parts.method, parts.uri, parts.headers); let path = paths::GLOBAL_REGEX_SET.matches(uri.path()); - let mut context = body.context; - let body = body.inner; match &method { @@ -207,26 +222,23 @@ where let param_url = match param_url { Some(param_url) => match param_url.parse::() { Ok(param_url) => param_url, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse query parameter url - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid query parameter url"))), + .expect("Unable to create Bad Request response for invalid query parameter url")), }, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required query parameter url")) - .expect("Unable to create Bad Request response for missing qeury parameter url"))), + .expect("Unable to create Bad Request response for missing qeury parameter url")), }; - Box::new({ - {{ - Box::new( - api_impl.callback_with_header_post( + let result = api_impl.callback_with_header_post( param_url, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -246,11 +258,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // ComplexQueryParamGet - GET /complex-query-param @@ -266,15 +274,12 @@ where None }; - Box::new({ - {{ - Box::new( - api_impl.complex_query_param_get( + let result = api_impl.complex_query_param_get( param_list_of_strings.as_ref(), &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -294,11 +299,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // EnumInPathPathParamGet - GET /enum_in_path/{path_param} @@ -315,26 +316,23 @@ where let param_path_param = match percent_encoding::percent_decode(path_params["path_param"].as_bytes()).decode_utf8() { Ok(param_path_param) => match param_path_param.parse::() { Ok(param_path_param) => param_path_param, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse path parameter path_param: {}", e))) - .expect("Unable to create Bad Request response for invalid path parameter"))), + .expect("Unable to create Bad Request response for invalid path parameter")), }, - Err(_) => return Box::new(future::ok(Response::builder() + Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["path_param"]))) - .expect("Unable to create Bad Request response for invalid percent decode"))) + .expect("Unable to create Bad Request response for invalid percent decode")) }; - Box::new({ - {{ - Box::new( - api_impl.enum_in_path_path_param_get( + let result = api_impl.enum_in_path_path_param_get( param_path_param, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -354,11 +352,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // MandatoryRequestHeaderGet - GET /mandatory-request-header @@ -371,30 +365,27 @@ where Ok(result) => result.0, Err(err) => { - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Invalid header X-Header - {}", err))) - .expect("Unable to create Bad Request response for invalid header X-Header"))); + .expect("Unable to create Bad Request response for invalid header X-Header")); }, }, None => { - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required header X-Header")) - .expect("Unable to create Bad Request response for missing required header X-Header"))); + .expect("Unable to create Bad Request response for missing required header X-Header")); } }; - Box::new({ - {{ - Box::new( - api_impl.mandatory_request_header_get( + let result = api_impl.mandatory_request_header_get( param_x_header, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -414,23 +405,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // MergePatchJsonGet - GET /merge-patch-json &hyper::Method::GET if path.matched(paths::ID_MERGE_PATCH_JSON) => { - Box::new({ - {{ - Box::new( - api_impl.merge_patch_json_get( + let result = api_impl.merge_patch_json_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -457,23 +441,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // MultigetGet - GET /multiget &hyper::Method::GET if path.matched(paths::ID_MULTIGET) => { - Box::new({ - {{ - Box::new( - api_impl.multiget_get( + let result = api_impl.multiget_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -566,11 +543,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // MultipleAuthSchemeGet - GET /multiple_auth_scheme @@ -578,10 +551,10 @@ where { let authorization = match (&context as &dyn Has>).get() { &Some(ref authorization) => authorization, - &None => return Box::new(future::ok(Response::builder() + &None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) .body(Body::from("Unauthenticated")) - .expect("Unable to create Authentication Forbidden response"))), + .expect("Unable to create Authentication Forbidden response")), }; // Authorization @@ -593,26 +566,23 @@ where if !required_scopes.is_subset(scopes) { let missing_scopes = required_scopes.difference(scopes); - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::FORBIDDEN) .body(Body::from(missing_scopes.fold( "Insufficient authorization, missing scopes".to_string(), |s, scope| format!("{} {}", s, scope)) )) .expect("Unable to create Authentication Insufficient response") - )); + ); } } } - Box::new({ - {{ - Box::new( - api_impl.multiple_auth_scheme_get( + let result = api_impl.multiple_auth_scheme_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -632,23 +602,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // OverrideServerGet - GET /override-server &hyper::Method::GET if path.matched(paths::ID_OVERRIDE_SERVER) => { - Box::new({ - {{ - Box::new( - api_impl.override_server_get( + let result = api_impl.override_server_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -668,11 +631,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // ParamgetGet - GET /paramget @@ -689,17 +648,14 @@ where .nth(0); let param_some_list = param_some_list.and_then(|param_some_list| param_some_list.parse::<>().ok()); - Box::new({ - {{ - Box::new( - api_impl.paramget_get( + let result = api_impl.paramget_get( param_uuid, param_some_object, param_some_list, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -726,11 +682,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // ReadonlyAuthSchemeGet - GET /readonly_auth_scheme @@ -738,10 +690,10 @@ where { let authorization = match (&context as &dyn Has>).get() { &Some(ref authorization) => authorization, - &None => return Box::new(future::ok(Response::builder() + &None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) .body(Body::from("Unauthenticated")) - .expect("Unable to create Authentication Forbidden response"))), + .expect("Unable to create Authentication Forbidden response")), }; // Authorization @@ -752,26 +704,23 @@ where if !required_scopes.is_subset(scopes) { let missing_scopes = required_scopes.difference(scopes); - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::FORBIDDEN) .body(Body::from(missing_scopes.fold( "Insufficient authorization, missing scopes".to_string(), |s, scope| format!("{} {}", s, scope)) )) .expect("Unable to create Authentication Insufficient response") - )); + ); } } } - Box::new({ - {{ - Box::new( - api_impl.readonly_auth_scheme_get( + let result = api_impl.readonly_auth_scheme_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -791,11 +740,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // RegisterCallbackPost - POST /register-callback @@ -807,26 +752,23 @@ where let param_url = match param_url { Some(param_url) => match param_url.parse::() { Ok(param_url) => param_url, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse query parameter url - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid query parameter url"))), + .expect("Unable to create Bad Request response for invalid query parameter url")), }, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required query parameter url")) - .expect("Unable to create Bad Request response for missing qeury parameter url"))), + .expect("Unable to create Bad Request response for missing qeury parameter url")), }; - Box::new({ - {{ - Box::new( - api_impl.register_callback_post( + let result = api_impl.register_callback_post( param_url, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -846,11 +788,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // RequiredOctetStreamPut - PUT /required_octet_stream @@ -858,9 +796,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let param_body: Option = if !body.is_empty() { Some(swagger::ByteArray(body.to_vec())) @@ -869,19 +806,18 @@ where }; let param_body = match param_body { Some(param_body) => param_body, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required body parameter body")) - .expect("Unable to create Bad Request response for missing body parameter body"))), + .expect("Unable to create Bad Request response for missing body parameter body")), }; - Box::new( - api_impl.required_octet_stream_put( + let result = api_impl.required_octet_stream_put( param_body, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -901,29 +837,22 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter body: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter body"))), + .expect("Unable to create Bad Request response due to unable to read body parameter body")), } - }) - ) as Self::Future }, // ResponsesWithHeadersGet - GET /responses_with_headers &hyper::Method::GET if path.matched(paths::ID_RESPONSES_WITH_HEADERS) => { - Box::new({ - {{ - Box::new( - api_impl.responses_with_headers_get( + let result = api_impl.responses_with_headers_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -941,7 +870,7 @@ where let success_info = match header::IntoHeaderValue(success_info).try_into() { Ok(val) => val, Err(e) => { - return future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) .body(Body::from(format!("An internal server error occurred handling success_info header - {}", e))) .expect("Unable to create Internal Server Error for invalid response header")) @@ -951,7 +880,7 @@ where let bool_header = match header::IntoHeaderValue(bool_header).try_into() { Ok(val) => val, Err(e) => { - return future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) .body(Body::from(format!("An internal server error occurred handling bool_header header - {}", e))) .expect("Unable to create Internal Server Error for invalid response header")) @@ -961,7 +890,7 @@ where let object_header = match header::IntoHeaderValue(object_header).try_into() { Ok(val) => val, Err(e) => { - return future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) .body(Body::from(format!("An internal server error occurred handling object_header header - {}", e))) .expect("Unable to create Internal Server Error for invalid response header")) @@ -997,7 +926,7 @@ where let further_info = match header::IntoHeaderValue(further_info).try_into() { Ok(val) => val, Err(e) => { - return future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) .body(Body::from(format!("An internal server error occurred handling further_info header - {}", e))) .expect("Unable to create Internal Server Error for invalid response header")) @@ -1007,7 +936,7 @@ where let failure_info = match header::IntoHeaderValue(failure_info).try_into() { Ok(val) => val, Err(e) => { - return future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) .body(Body::from(format!("An internal server error occurred handling failure_info header - {}", e))) .expect("Unable to create Internal Server Error for invalid response header")) @@ -1033,23 +962,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Rfc7807Get - GET /rfc7807 &hyper::Method::GET if path.matched(paths::ID_RFC7807) => { - Box::new({ - {{ - Box::new( - api_impl.rfc7807_get( + let result = api_impl.rfc7807_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1098,11 +1020,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // UntypedPropertyGet - GET /untyped_property @@ -1110,9 +1028,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_object_untyped_props: Option = if !body.is_empty() { @@ -1128,13 +1045,12 @@ where None }; - Box::new( - api_impl.untyped_property_get( + let result = api_impl.untyped_property_get( param_object_untyped_props, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1161,29 +1077,22 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter ObjectUntypedProps: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter ObjectUntypedProps"))), + .expect("Unable to create Bad Request response due to unable to read body parameter ObjectUntypedProps")), } - }) - ) as Self::Future }, // UuidGet - GET /uuid &hyper::Method::GET if path.matched(paths::ID_UUID) => { - Box::new({ - {{ - Box::new( - api_impl.uuid_get( + let result = api_impl.uuid_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1210,11 +1119,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // XmlExtraPost - POST /xml_extra @@ -1222,9 +1127,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_duplicate_xml_object: Option = if !body.is_empty() { @@ -1240,13 +1144,12 @@ where None }; - Box::new( - api_impl.xml_extra_post( + let result = api_impl.xml_extra_post( param_duplicate_xml_object, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1277,17 +1180,13 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter DuplicateXmlObject: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter DuplicateXmlObject"))), + .expect("Unable to create Bad Request response due to unable to read body parameter DuplicateXmlObject")), } - }) - ) as Self::Future }, // XmlOtherPost - POST /xml_other @@ -1295,9 +1194,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_another_xml_object: Option = if !body.is_empty() { @@ -1313,13 +1211,12 @@ where None }; - Box::new( - api_impl.xml_other_post( + let result = api_impl.xml_other_post( param_another_xml_object, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1361,17 +1258,13 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter AnotherXmlObject: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter AnotherXmlObject"))), + .expect("Unable to create Bad Request response due to unable to read body parameter AnotherXmlObject")), } - }) - ) as Self::Future }, // XmlOtherPut - PUT /xml_other @@ -1379,9 +1272,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_another_xml_array: Option = if !body.is_empty() { @@ -1397,13 +1289,12 @@ where None }; - Box::new( - api_impl.xml_other_put( + let result = api_impl.xml_other_put( param_another_xml_array, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1434,17 +1325,13 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter AnotherXmlArray: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter AnotherXmlArray"))), + .expect("Unable to create Bad Request response due to unable to read body parameter AnotherXmlArray")), } - }) - ) as Self::Future }, // XmlPost - POST /xml @@ -1452,9 +1339,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_xml_array: Option = if !body.is_empty() { @@ -1470,13 +1356,12 @@ where None }; - Box::new( - api_impl.xml_post( + let result = api_impl.xml_post( param_xml_array, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1507,17 +1392,13 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter XmlArray: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter XmlArray"))), + .expect("Unable to create Bad Request response due to unable to read body parameter XmlArray")), } - }) - ) as Self::Future }, // XmlPut - PUT /xml @@ -1525,9 +1406,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_xml_object: Option = if !body.is_empty() { @@ -1543,13 +1423,12 @@ where None }; - Box::new( - api_impl.xml_put( + let result = api_impl.xml_put( param_xml_object, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1580,17 +1459,13 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter XmlObject: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter XmlObject"))), + .expect("Unable to create Bad Request response due to unable to read body parameter XmlObject")), } - }) - ) as Self::Future }, // CreateRepo - POST /repos @@ -1598,9 +1473,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_object_param: Option = if !body.is_empty() { @@ -1610,29 +1484,28 @@ where unused_elements.push(path.to_string()); }) { Ok(param_object_param) => param_object_param, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse body parameter ObjectParam - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid body parameter ObjectParam due to schema"))), + .expect("Unable to create Bad Request response for invalid body parameter ObjectParam due to schema")), } } else { None }; let param_object_param = match param_object_param { Some(param_object_param) => param_object_param, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required body parameter ObjectParam")) - .expect("Unable to create Bad Request response for missing body parameter ObjectParam"))), + .expect("Unable to create Bad Request response for missing body parameter ObjectParam")), }; - Box::new( - api_impl.create_repo( + let result = api_impl.create_repo( param_object_param, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1659,17 +1532,13 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter ObjectParam: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter ObjectParam"))), + .expect("Unable to create Bad Request response due to unable to read body parameter ObjectParam")), } - }) - ) as Self::Future }, // GetRepoInfo - GET /repos/{repoId} @@ -1686,26 +1555,23 @@ where let param_repo_id = match percent_encoding::percent_decode(path_params["repoId"].as_bytes()).decode_utf8() { Ok(param_repo_id) => match param_repo_id.parse::() { Ok(param_repo_id) => param_repo_id, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse path parameter repoId: {}", e))) - .expect("Unable to create Bad Request response for invalid path parameter"))), + .expect("Unable to create Bad Request response for invalid path parameter")), }, - Err(_) => return Box::new(future::ok(Response::builder() + Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["repoId"]))) - .expect("Unable to create Bad Request response for invalid percent decode"))) + .expect("Unable to create Bad Request response for invalid percent decode")) }; - Box::new({ - {{ - Box::new( - api_impl.get_repo_info( + let result = api_impl.get_repo_info( param_repo_id, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1732,11 +1598,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, _ if path.matched(paths::ID_CALLBACK_WITH_HEADER) => method_not_allowed(), @@ -1760,23 +1622,11 @@ where _ if path.matched(paths::ID_XML) => method_not_allowed(), _ if path.matched(paths::ID_XML_EXTRA) => method_not_allowed(), _ if path.matched(paths::ID_XML_OTHER) => method_not_allowed(), - _ => Box::new(future::ok( - Response::builder().status(StatusCode::NOT_FOUND) + _ => Ok(Response::builder().status(StatusCode::NOT_FOUND) .body(Body::empty()) - .expect("Unable to create Not Found response") - )) as Self::Future + .expect("Unable to create Not Found response")) } - } -} - -impl Clone for Service where T: Clone -{ - fn clone(&self) -> Self { - Service { - api_impl: self.api_impl.clone(), - marker: self.marker.clone(), - } - } + } Box::pin(run(self.api_impl.clone(), req)) } } /// Request parser for `Api`. diff --git a/samples/server/petstore/rust-server/output/ops-v3/Cargo.toml b/samples/server/petstore/rust-server/output/ops-v3/Cargo.toml index 5785f23fafc..793ffbb6c00 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/Cargo.toml +++ b/samples/server/petstore/rust-server/output/ops-v3/Cargo.toml @@ -9,7 +9,7 @@ edition = "2018" [features] default = ["client", "server"] client = [ - "hyper", "hyper-openssl", "native-tls", "openssl", "url" + "hyper", "hyper-openssl", "hyper-tls", "native-tls", "openssl", "url" ] server = [ "serde_ignored", "hyper", "regex", "percent-encoding", "url", "lazy_static" @@ -18,35 +18,37 @@ conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk- [target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] native-tls = { version = "0.2", optional = true } +hyper-tls = { version = "0.4", optional = true } [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dependencies] -hyper-openssl = { version = "0.7.1", optional = true } +hyper-openssl = { version = "0.8", optional = true } openssl = {version = "0.10", optional = true } [dependencies] # Common +async-trait = "0.1.24" chrono = { version = "0.4", features = ["serde"] } -futures = "0.1" -swagger = "4.0" +futures = "0.3" +swagger = "5.0.0-alpha-1" log = "0.4.0" mime = "0.3" -serde = { version = "1.0", features = ["derive"]} +serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" # Crates included if required by the API definition # Common between server and client features -hyper = {version = "0.12", optional = true} -serde_ignored = {version = "0.0.4", optional = true} -url = {version = "1.5", optional = true} +hyper = {version = "0.13", optional = true} +serde_ignored = {version = "0.1.1", optional = true} +url = {version = "2.1", optional = true} # Client-specific # Server, and client callback-specific lazy_static = { version = "1.4", optional = true } -percent-encoding = {version = "1.0.0", optional = true} -regex = {version = "0.2", optional = true} +percent-encoding = {version = "2.1.0", optional = true} +regex = {version = "1.3", optional = true} # Conversion frunk = { version = "0.3.0", optional = true } @@ -57,13 +59,13 @@ frunk-enum-core = { version = "0.2.0", optional = true } [dev-dependencies] clap = "2.25" -error-chain = "0.12" -env_logger = "0.6" -tokio = "0.1.17" -uuid = {version = "0.7", features = ["serde", "v4"]} +env_logger = "0.7" +tokio = { version = "0.2", features = ["rt-threaded", "macros", "stream"] } +native-tls = "0.2" +tokio-tls = "0.3" [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dev-dependencies] -tokio-openssl = "0.3" +tokio-openssl = "0.4" openssl = "0.10" [[example]] diff --git a/samples/server/petstore/rust-server/output/ops-v3/examples/client/main.rs b/samples/server/petstore/rust-server/output/ops-v3/examples/client/main.rs index 9a9e8fa74ac..4b79043b5cc 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/examples/client/main.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/examples/client/main.rs @@ -2,10 +2,9 @@ #[allow(unused_imports)] -use futures::{Future, future, Stream, stream}; +use futures::{future, Stream, stream}; #[allow(unused_imports)] use ops_v3::{Api, ApiNoContext, Client, ContextWrapperExt, models, - ApiError, Op10GetResponse, Op11GetResponse, Op12GetResponse, @@ -42,7 +41,7 @@ use ops_v3::{Api, ApiNoContext, Client, ContextWrapperExt, models, Op6GetResponse, Op7GetResponse, Op8GetResponse, - Op9GetResponse + Op9GetResponse, }; use clap::{App, Arg}; @@ -51,7 +50,9 @@ use log::info; // swagger::Has may be unused if there are no examples #[allow(unused_imports)] -use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData}; +use swagger::{AuthData, ContextBuilder, EmptyContext, Has, Push, XSpanIdString}; + +type ClientContext = swagger::make_context_ty!(ContextBuilder, EmptyContext, Option, XSpanIdString); // rt may be unused if there are no examples #[allow(unused_mut)] @@ -123,21 +124,21 @@ fn main() { matches.value_of("host").unwrap(), matches.value_of("port").unwrap()); - let client = if matches.is_present("https") { - // Using Simple HTTPS - Client::try_new_https(&base_url) - .expect("Failed to create HTTPS client") - } else { - // Using HTTP - Client::try_new_http( - &base_url) - .expect("Failed to create HTTP client") - }; - - let context: swagger::make_context_ty!(ContextBuilder, EmptyContext, Option, XSpanIdString) = + let context: ClientContext = swagger::make_context!(ContextBuilder, EmptyContext, None as Option, XSpanIdString::default()); - let client = client.with_context(context); + let mut client : Box> = if matches.is_present("https") { + // Using Simple HTTPS + let client = Box::new(Client::try_new_https(&base_url) + .expect("Failed to create HTTPS client")); + Box::new(client.with_context(context)) + } else { + // Using HTTP + let client = Box::new(Client::try_new_http( + &base_url) + .expect("Failed to create HTTP client")); + Box::new(client.with_context(context)) + }; let mut rt = tokio::runtime::Runtime::new().unwrap(); diff --git a/samples/server/petstore/rust-server/output/ops-v3/examples/server/main.rs b/samples/server/petstore/rust-server/output/ops-v3/examples/server/main.rs index c6ddb834be8..2e7d3031162 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/examples/server/main.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/examples/server/main.rs @@ -9,7 +9,8 @@ mod server; /// Create custom server, wire it to the autogenerated router, /// and pass it to the web server. -fn main() { +#[tokio::main] +async fn main() { env_logger::init(); let matches = App::new("server") @@ -20,5 +21,5 @@ fn main() { let addr = "127.0.0.1:8080"; - hyper::rt::run(server::create(addr, matches.is_present("https"))); + server::create(addr, matches.is_present("https")).await; } diff --git a/samples/server/petstore/rust-server/output/ops-v3/examples/server/server.rs b/samples/server/petstore/rust-server/output/ops-v3/examples/server/server.rs index 62fb2ae73b4..144be9030d7 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/examples/server/server.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/examples/server/server.rs @@ -2,30 +2,22 @@ #![allow(unused_imports)] -mod errors { - error_chain::error_chain!{} -} - -pub use self::errors::*; - -use chrono; -use futures::{future, Future, Stream}; +use async_trait::async_trait; +use futures::{future, Stream, StreamExt, TryFutureExt, TryStreamExt}; use hyper::server::conn::Http; -use hyper::service::MakeService as _; +use hyper::service::Service; use log::info; use openssl::ssl::SslAcceptorBuilder; +use std::future::Future; use std::marker::PhantomData; use std::net::SocketAddr; use std::sync::{Arc, Mutex}; -use swagger; +use std::task::{Context, Poll}; use swagger::{Has, XSpanIdString}; use swagger::auth::MakeAllowAllAuthenticator; use swagger::EmptyContext; use tokio::net::TcpListener; - -#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] -use tokio_openssl::SslAcceptorExt; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; @@ -33,18 +25,18 @@ use ops_v3::models; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] /// Builds an SSL implementation for Simple HTTPS from some hard-coded file names -pub fn create(addr: &str, https: bool) -> Box + Send> { +pub async fn create(addr: &str, https: bool) { let addr = addr.parse().expect("Failed to parse bind address"); let server = Server::new(); - let service_fn = MakeService::new(server); + let service = MakeService::new(server); - let service_fn = MakeAllowAllAuthenticator::new(service_fn, "cosmo"); + let service = MakeAllowAllAuthenticator::new(service, "cosmo"); - let service_fn = + let mut service = ops_v3::server::context::MakeAddContext::<_, EmptyContext>::new( - service_fn + service ); if https { @@ -62,32 +54,31 @@ pub fn create(addr: &str, https: bool) -> Box ssl.set_certificate_chain_file("examples/server-chain.pem").expect("Failed to set cerificate chain"); ssl.check_private_key().expect("Failed to check private key"); - let tls_acceptor = ssl.build(); - let service_fn = Arc::new(Mutex::new(service_fn)); - let tls_listener = TcpListener::bind(&addr).unwrap().incoming().for_each(move |tcp| { - let addr = tcp.peer_addr().expect("Unable to get remote address"); + let tls_acceptor = Arc::new(ssl.build()); + let mut tcp_listener = TcpListener::bind(&addr).await.unwrap(); + let mut incoming = tcp_listener.incoming(); - let service_fn = service_fn.clone(); + while let (Some(tcp), rest) = incoming.into_future().await { + if let Ok(tcp) = tcp { + let addr = tcp.peer_addr().expect("Unable to get remote address"); + let service = service.call(addr); + let tls_acceptor = Arc::clone(&tls_acceptor); - hyper::rt::spawn(tls_acceptor.accept_async(tcp).map_err(|_| ()).and_then(move |tls| { - let ms = { - let mut service_fn = service_fn.lock().unwrap(); - service_fn.make_service(&addr) - }; + tokio::spawn(async move { + let tls = tokio_openssl::accept(&*tls_acceptor, tcp).await.map_err(|_| ())?; - ms.and_then(move |service| { - Http::new().serve_connection(tls, service) - }).map_err(|_| ()) - })); + let service = service.await.map_err(|_| ())?; - Ok(()) - }).map_err(|_| ()); + Http::new().serve_connection(tls, service).await.map_err(|_| ()) + }); + } - Box::new(tls_listener) + incoming = rest; + } } } else { // Using HTTP - Box::new(hyper::server::Server::bind(&addr).serve(service_fn).map_err(|e| panic!("{:?}", e))) + hyper::server::Server::bind(&addr).serve(service).await.unwrap() } } @@ -105,7 +96,6 @@ impl Server { use ops_v3::{ Api, - ApiError, Op10GetResponse, Op11GetResponse, Op12GetResponse, @@ -145,339 +135,343 @@ use ops_v3::{ Op9GetResponse, }; use ops_v3::server::MakeService; +use std::error::Error; +use swagger::ApiError; -impl Api for Server where C: Has{ - fn op10_get( +#[async_trait] +impl Api for Server where C: Has + Send + Sync +{ + async fn op10_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op10_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op11_get( + async fn op11_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op11_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op12_get( + async fn op12_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op12_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op13_get( + async fn op13_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op13_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op14_get( + async fn op14_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op14_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op15_get( + async fn op15_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op15_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op16_get( + async fn op16_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op16_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op17_get( + async fn op17_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op17_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op18_get( + async fn op18_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op18_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op19_get( + async fn op19_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op19_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op1_get( + async fn op1_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op1_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op20_get( + async fn op20_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op20_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op21_get( + async fn op21_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op21_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op22_get( + async fn op22_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op22_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op23_get( + async fn op23_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op23_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op24_get( + async fn op24_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op24_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op25_get( + async fn op25_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op25_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op26_get( + async fn op26_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op26_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op27_get( + async fn op27_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op27_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op28_get( + async fn op28_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op28_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op29_get( + async fn op29_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op29_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op2_get( + async fn op2_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op2_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op30_get( + async fn op30_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op30_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op31_get( + async fn op31_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op31_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op32_get( + async fn op32_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op32_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op33_get( + async fn op33_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op33_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op34_get( + async fn op34_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op34_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op35_get( + async fn op35_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op35_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op36_get( + async fn op36_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op36_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op37_get( + async fn op37_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op37_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op3_get( + async fn op3_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op3_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op4_get( + async fn op4_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op4_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op5_get( + async fn op5_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op5_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op6_get( + async fn op6_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op6_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op7_get( + async fn op7_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op7_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op8_get( + async fn op8_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op8_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn op9_get( + async fn op9_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("op9_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } } diff --git a/samples/server/petstore/rust-server/output/ops-v3/src/client/mod.rs b/samples/server/petstore/rust-server/output/ops-v3/src/client/mod.rs index 05ee715c58f..48817db8753 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/src/client/mod.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/src/client/mod.rs @@ -1,37 +1,38 @@ -use futures; -use futures::{Future, Stream, future, stream}; -use hyper; -use hyper::client::HttpConnector; +use async_trait::async_trait; +use futures::{Stream, future, future::BoxFuture, stream, future::TryFutureExt, future::FutureExt, stream::StreamExt}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; -use hyper::{Body, Uri, Response}; -#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] -use hyper_openssl::HttpsConnector; -use serde_json; +use hyper::{Body, Request, Response, service::Service, Uri}; +use percent_encoding::{utf8_percent_encode, AsciiSet}; use std::borrow::Cow; use std::convert::TryInto; -use std::io::{Read, Error, ErrorKind}; -use std::error; +use std::io::{ErrorKind, Read}; +use std::error::Error; +use std::future::Future; use std::fmt; use std::path::Path; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use std::str; use std::str::FromStr; use std::string::ToString; -use swagger; -use swagger::{ApiError, Connector, client::Service, XSpanIdString, Has, AuthData}; +use std::task::{Context, Poll}; +use swagger::{ApiError, AuthData, BodyExt, Connector, Has, XSpanIdString}; use url::form_urlencoded; -use url::percent_encoding::{utf8_percent_encode, PATH_SEGMENT_ENCODE_SET, QUERY_ENCODE_SET}; + use crate::models; use crate::header; -url::define_encode_set! { - /// This encode set is used for object IDs - /// - /// Aside from the special characters defined in the `PATH_SEGMENT_ENCODE_SET`, - /// the vertical bar (|) is encoded. - pub ID_ENCODE_SET = [PATH_SEGMENT_ENCODE_SET] | {'|'} -} +/// https://url.spec.whatwg.org/#fragment-percent-encode-set +#[allow(dead_code)] +const FRAGMENT_ENCODE_SET: &AsciiSet = &percent_encoding::CONTROLS + .add(b' ').add(b'"').add(b'<').add(b'>').add(b'`'); + +/// This encode set is used for object IDs +/// +/// Aside from the special characters defined in the `PATH_SEGMENT_ENCODE_SET`, +/// the vertical bar (|) is encoded. +#[allow(dead_code)] +const ID_ENCODE_SET: &AsciiSet = &FRAGMENT_ENCODE_SET.add(b'|'); use crate::{Api, Op10GetResponse, @@ -74,11 +75,11 @@ use crate::{Api, }; /// Convert input into a base path, e.g. "http://example:123". Also checks the scheme as it goes. -fn into_base_path(input: &str, correct_scheme: Option<&'static str>) -> Result { +fn into_base_path(input: impl TryInto, correct_scheme: Option<&'static str>) -> Result { // First convert to Uri, since a base path is a subset of Uri. - let uri = Uri::from_str(input)?; + let uri = input.try_into()?; - let scheme = uri.scheme_part().ok_or(ClientInitError::InvalidScheme)?; + let scheme = uri.scheme_str().ok_or(ClientInitError::InvalidScheme)?; // Check the scheme if necessary if let Some(correct_scheme) = correct_scheme { @@ -88,38 +89,54 @@ fn into_base_path(input: &str, correct_scheme: Option<&'static str>) -> Result +pub struct Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { /// Inner service - client_service: Arc + Send + Sync>>, + client_service: S, /// Base path of the API base_path: String, } -impl fmt::Debug for Client +impl fmt::Debug for Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Client {{ base_path: {} }}", self.base_path) } } -impl Clone for Client +impl Clone for Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { fn clone(&self) -> Self { - Client { + Self { client_service: self.client_service.clone(), base_path: self.base_path.clone(), } } } -impl Client +impl Client> where + C: hyper::client::connect::Connect + Clone + Send + Sync + 'static { /// Create a client with a custom implementation of hyper::client::Connect. /// @@ -132,30 +149,93 @@ impl Client /// /// # Arguments /// - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "http://www.my-api-implementation.com" /// * `protocol` - Which protocol to use when constructing the request url, e.g. `Some("http")` /// * `connector` - Implementation of `hyper::client::Connect` to use for the client - pub fn try_new_with_connector( + pub fn try_new_with_connector( base_path: &str, protocol: Option<&'static str>, connector: C, - ) -> Result where - C: hyper::client::connect::Connect + 'static, - C::Transport: 'static, - C::Future: 'static, + ) -> Result { - let client_service = Box::new(hyper::client::Client::builder().build(connector)); + let client_service = hyper::client::Client::builder().build(connector); - Ok(Client { - client_service: Arc::new(client_service), + Ok(Self { + client_service, base_path: into_base_path(base_path, protocol)?, }) } +} +#[derive(Debug, Clone)] +pub enum HyperClient { + Http(hyper::client::Client), + Https(hyper::client::Client), +} + +impl Service> for HyperClient { + type Response = Response; + type Error = hyper::Error; + type Future = hyper::client::ResponseFuture; + + fn poll_ready(&mut self, cx: &mut Context) -> Poll> { + match self { + HyperClient::Http(client) => client.poll_ready(cx), + HyperClient::Https(client) => client.poll_ready(cx), + } + } + + fn call(&mut self, req: Request) -> Self::Future { + match self { + HyperClient::Http(client) => client.call(req), + HyperClient::Https(client) => client.call(req) + } + } +} + +impl Client { /// Create an HTTP client. /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "http://www.my-api-implementation.com" + pub fn try_new( + base_path: &str, + ) -> Result { + let uri = Uri::from_str(base_path)?; + + let scheme = uri.scheme_str().ok_or(ClientInitError::InvalidScheme)?; + let scheme = scheme.to_ascii_lowercase(); + + let connector = Connector::builder(); + + let client_service = match scheme.as_str() { + "http" => { + HyperClient::Http(hyper::client::Client::builder().build(connector.build())) + }, + "https" => { + let connector = connector.https() + .build() + .map_err(|e| ClientInitError::SslError(e))?; + HyperClient::Https(hyper::client::Client::builder().build(connector)) + }, + _ => { + return Err(ClientInitError::InvalidScheme); + } + }; + + Ok(Self { + client_service, + base_path: into_base_path(base_path, None)?, + }) + } +} + +impl Client> +{ + /// Create an HTTP client. + /// + /// # Arguments + /// * `base_path` - base path of the client API, i.e. "http://www.my-api-implementation.com" pub fn try_new_http( base_path: &str, ) -> Result { @@ -163,11 +243,20 @@ impl Client Self::try_new_with_connector(base_path, Some("http"), http_connector) } +} +#[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] +type HttpsConnector = hyper_tls::HttpsConnector; + +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +type HttpsConnector = hyper_openssl::HttpsConnector; + +impl Client> +{ /// Create a client with a TLS connection to the server /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "https://www.my-api-implementation.com" pub fn try_new_https(base_path: &str) -> Result { let https_connector = Connector::builder() @@ -180,7 +269,7 @@ impl Client /// Create a client with a TLS connection to the server using a pinned certificate /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "https://www.my-api-implementation.com" /// * `ca_certificate` - Path to CA certificate used to authenticate the server #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] pub fn try_new_https_pinned( @@ -201,7 +290,7 @@ impl Client /// Create a client with a mutually authenticated TLS connection to the server. /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "https://www.my-api-implementation.com" /// * `ca_certificate` - Path to CA certificate used to authenticate the server /// * `client_key` - Path to the client private key /// * `client_certificate` - Path to the client's public certificate associated with the private key @@ -227,17 +316,24 @@ impl Client } } -impl Client +impl Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { - /// Constructor for creating a `Client` by passing in a pre-made `swagger::Service` + /// Constructor for creating a `Client` by passing in a pre-made `hyper::service::Service` / + /// `tower::Service` /// /// This allows adding custom wrappers around the underlying transport, for example for logging. pub fn try_new_with_client_service( - client_service: Arc + Send + Sync>>, + client_service: S, base_path: &str, - ) -> Result { - Ok(Client { - client_service: client_service, + ) -> Result + { + Ok(Self { + client_service, base_path: into_base_path(base_path, None)?, }) } @@ -277,2641 +373,2580 @@ impl fmt::Display for ClientInitError { } } -impl error::Error for ClientInitError { +impl Error for ClientInitError { fn description(&self) -> &str { "Failed to produce a hyper client." } } -impl Api for Client where - C: Has , - F: Future, Error=hyper::Error> + Send + 'static +#[async_trait] +impl Api for Client where + C: Has + Clone + Send + Sync + 'static, + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { - fn op10_get( + fn poll_ready(&self, cx: &mut Context) -> Poll> { + match self.client_service.clone().poll_ready(cx) { + Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())), + Poll::Ready(Ok(o)) => Poll::Ready(Ok(o)), + Poll::Pending => Poll::Pending, + } + } + + async fn op10_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op10", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op10GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op10GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op11_get( + async fn op11_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op11", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op11GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op11GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op12_get( + async fn op12_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op12", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op12GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op12GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op13_get( + async fn op13_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op13", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op13GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op13GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op14_get( + async fn op14_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op14", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op14GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op14GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op15_get( + async fn op15_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op15", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op15GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op15GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op16_get( + async fn op16_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op16", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op16GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op16GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op17_get( + async fn op17_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op17", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op17GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op17GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op18_get( + async fn op18_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op18", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op18GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op18GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op19_get( + async fn op19_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op19", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op19GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op19GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op1_get( + async fn op1_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op1", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op1GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op1GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op20_get( + async fn op20_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op20", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op20GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op20GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op21_get( + async fn op21_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op21", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op21GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op21GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op22_get( + async fn op22_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op22", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op22GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op22GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op23_get( + async fn op23_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op23", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op23GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op23GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op24_get( + async fn op24_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op24", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op24GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op24GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op25_get( + async fn op25_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op25", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op25GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op25GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op26_get( + async fn op26_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op26", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op26GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op26GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op27_get( + async fn op27_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op27", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op27GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op27GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op28_get( + async fn op28_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op28", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op28GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op28GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op29_get( + async fn op29_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op29", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op29GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op29GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op2_get( + async fn op2_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op2", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op2GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op2GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op30_get( + async fn op30_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op30", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op30GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op30GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op31_get( + async fn op31_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op31", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op31GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op31GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op32_get( + async fn op32_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op32", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op32GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op32GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op33_get( + async fn op33_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op33", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op33GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op33GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op34_get( + async fn op34_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op34", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op34GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op34GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op35_get( + async fn op35_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op35", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op35GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op35GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op36_get( + async fn op36_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op36", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op36GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op36GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op37_get( + async fn op37_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op37", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op37GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op37GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op3_get( + async fn op3_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op3", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op3GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op3GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op4_get( + async fn op4_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op4", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op4GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op4GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op5_get( + async fn op5_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op5", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op5GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op5GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op6_get( + async fn op6_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op6", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op6GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op6GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op7_get( + async fn op7_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op7", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op7GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op7GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op8_get( + async fn op8_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op8", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op8GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op8GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn op9_get( + async fn op9_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/op9", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Op9GetResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Op9GetResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } } diff --git a/samples/server/petstore/rust-server/output/ops-v3/src/context.rs b/samples/server/petstore/rust-server/output/ops-v3/src/context.rs index d14e73f822d..fadd880b965 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/src/context.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/src/context.rs @@ -1,13 +1,12 @@ -use futures::Future; -use hyper; +use futures::future::BoxFuture; use hyper::header::HeaderName; -use hyper::{Error, Request, Response, StatusCode, service::Service, body::Payload}; +use hyper::{Error, Request, Response, StatusCode, service::Service}; use url::form_urlencoded; use std::default::Default; use std::io; use std::marker::PhantomData; +use std::task::{Poll, Context}; use swagger::auth::{AuthData, Authorization, Bearer, Scopes}; -use swagger::context::ContextualPayload; use swagger::{EmptyContext, Has, Pop, Push, XSpanIdString}; use crate::Api; @@ -31,58 +30,52 @@ where } // Make a service that adds context. -impl<'a, T, SC, A, B, C, D, E, ME, S, OB, F> hyper::service::MakeService<&'a SC> for +impl Service for MakeAddContext where - A: Default + Push, + Target: Send, + A: Default + Push + Send, B: Push, Result = C>, C: Push, Result = D>, D: Send + 'static, - T: hyper::service::MakeService< - &'a SC, - Error = E, - MakeError = ME, - Service = S, - ReqBody = ContextualPayload, - ResBody = OB, - Future = F - >, - S: Service< - Error = E, - ReqBody = ContextualPayload, - ResBody = OB> + 'static, - ME: swagger::ErrorBound, - E: swagger::ErrorBound, - F: Future + Send + 'static, - S::Future: Send, - OB: Payload, + T: Service + Send, + T::Future: Send + 'static { - type ReqBody = hyper::Body; - type ResBody = OB; - type Error = E; - type MakeError = ME; - type Service = AddContext; - type Future = Box + Send + 'static>; + type Error = T::Error; + type Response = AddContext; + type Future = BoxFuture<'static, Result>; - fn make_service(&mut self, ctx: &'a SC) -> Self::Future { - Box::new(self.inner.make_service(ctx).map(|s| AddContext::new(s))) + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + self.inner.poll_ready(cx) + } + + fn call(&mut self, target: Target) -> Self::Future { + let service = self.inner.call(target); + + Box::pin(async move { + Ok(AddContext::new(service.await?)) + }) } } -/// Middleware to extract authentication data from request -pub struct AddContext { +/// Middleware to add context data from the request +pub struct AddContext +where + A: Default + Push, + B: Push, Result = C>, + C: Push, Result = D> +{ inner: T, marker: PhantomData, } -impl AddContext +impl AddContext where A: Default + Push, B: Push, Result = C>, C: Push, Result = D>, - T: Service, { - pub fn new(inner: T) -> AddContext { + pub fn new(inner: T) -> Self { AddContext { inner, marker: PhantomData, @@ -90,33 +83,31 @@ where } } -impl Service for AddContext +impl Service> for AddContext where A: Default + Push, B: Push, Result=C>, C: Push, Result=D>, D: Send + 'static, - T: Service>, - T::Future: Future, Error=T::Error> + Send + 'static + T: Service<(Request, D)> { - type ReqBody = hyper::Body; - type ResBody = T::ResBody; type Error = T::Error; - type Future = Box, Error=T::Error> + Send + 'static>; + type Future = T::Future; + type Response = T::Response; - fn call(&mut self, req: Request) -> Self::Future { - let context = A::default().push(XSpanIdString::get_or_generate(&req)); - let (head, body) = req.into_parts(); - let headers = head.headers.clone(); + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + self.inner.poll_ready(cx) + } + + + fn call(&mut self, request: Request) -> Self::Future { + let context = A::default().push(XSpanIdString::get_or_generate(&request)); + let headers = request.headers(); let context = context.push(None::); let context = context.push(None::); - let body = ContextualPayload { - inner: body, - context: context, - }; - Box::new(self.inner.call(hyper::Request::from_parts(head, body))) + self.inner.call((request, context)) } } diff --git a/samples/server/petstore/rust-server/output/ops-v3/src/lib.rs b/samples/server/petstore/rust-server/output/ops-v3/src/lib.rs index 6cb9e0f31c2..11ba5e4a64a 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/src/lib.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/src/lib.rs @@ -1,12 +1,12 @@ #![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)] +use async_trait::async_trait; use futures::Stream; -use std::io::Error; +use std::error::Error; +use std::task::{Poll, Context}; +use swagger::{ApiError, ContextWrapper}; -#[deprecated(note = "Import swagger-rs directly")] -pub use swagger::{ApiError, ContextWrapper}; -#[deprecated(note = "Import futures directly")] -pub use futures::Future; +type ServiceError = Box; pub const BASE_PATH: &'static str = ""; pub const API_VERSION: &'static str = "0.0.1"; @@ -234,583 +234,642 @@ pub enum Op9GetResponse { } /// API -pub trait Api { - fn op10_get( - &self, - context: &C) -> Box + Send>; +#[async_trait] +pub trait Api { + fn poll_ready(&self, _cx: &mut Context) -> Poll>> { + Poll::Ready(Ok(())) + } - fn op11_get( + async fn op10_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op12_get( + async fn op11_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op13_get( + async fn op12_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op14_get( + async fn op13_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op15_get( + async fn op14_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op16_get( + async fn op15_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op17_get( + async fn op16_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op18_get( + async fn op17_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op19_get( + async fn op18_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op1_get( + async fn op19_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op20_get( + async fn op1_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op21_get( + async fn op20_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op22_get( + async fn op21_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op23_get( + async fn op22_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op24_get( + async fn op23_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op25_get( + async fn op24_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op26_get( + async fn op25_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op27_get( + async fn op26_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op28_get( + async fn op27_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op29_get( + async fn op28_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op2_get( + async fn op29_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op30_get( + async fn op2_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op31_get( + async fn op30_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op32_get( + async fn op31_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op33_get( + async fn op32_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op34_get( + async fn op33_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op35_get( + async fn op34_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op36_get( + async fn op35_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op37_get( + async fn op36_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op3_get( + async fn op37_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op4_get( + async fn op3_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op5_get( + async fn op4_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op6_get( + async fn op5_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op7_get( + async fn op6_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op8_get( + async fn op7_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn op9_get( + async fn op8_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; + + async fn op9_get( + &self, + context: &C) -> Result; } -/// API without a `Context` -pub trait ApiNoContext { - fn op10_get( - &self, - ) -> Box + Send>; +/// API where `Context` isn't passed on every API call +#[async_trait] +pub trait ApiNoContext { - fn op11_get( - &self, - ) -> Box + Send>; + fn poll_ready(&self, _cx: &mut Context) -> Poll>>; - fn op12_get( - &self, - ) -> Box + Send>; + fn context(&self) -> &C; - fn op13_get( + async fn op10_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op14_get( + async fn op11_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op15_get( + async fn op12_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op16_get( + async fn op13_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op17_get( + async fn op14_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op18_get( + async fn op15_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op19_get( + async fn op16_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op1_get( + async fn op17_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op20_get( + async fn op18_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op21_get( + async fn op19_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op22_get( + async fn op1_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op23_get( + async fn op20_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op24_get( + async fn op21_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op25_get( + async fn op22_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op26_get( + async fn op23_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op27_get( + async fn op24_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op28_get( + async fn op25_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op29_get( + async fn op26_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op2_get( + async fn op27_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op30_get( + async fn op28_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op31_get( + async fn op29_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op32_get( + async fn op2_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op33_get( + async fn op30_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op34_get( + async fn op31_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op35_get( + async fn op32_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op36_get( + async fn op33_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op37_get( + async fn op34_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op3_get( + async fn op35_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op4_get( + async fn op36_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op5_get( + async fn op37_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op6_get( + async fn op3_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op7_get( + async fn op4_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op8_get( + async fn op5_get( &self, - ) -> Box + Send>; + ) -> Result; - fn op9_get( + async fn op6_get( &self, - ) -> Box + Send>; + ) -> Result; + + async fn op7_get( + &self, + ) -> Result; + + async fn op8_get( + &self, + ) -> Result; + + async fn op9_get( + &self, + ) -> Result; } /// Trait to extend an API to make it easy to bind it to a context. -pub trait ContextWrapperExt<'a, C> where Self: Sized { +pub trait ContextWrapperExt where Self: Sized +{ /// Binds this API to a context. - fn with_context(self: &'a Self, context: C) -> ContextWrapper<'a, Self, C>; + fn with_context(self: Self, context: C) -> ContextWrapper; } -impl<'a, T: Api + Sized, C> ContextWrapperExt<'a, C> for T { - fn with_context(self: &'a T, context: C) -> ContextWrapper<'a, T, C> { +impl + Send + Sync, C: Clone + Send + Sync> ContextWrapperExt for T { + fn with_context(self: T, context: C) -> ContextWrapper { ContextWrapper::::new(self, context) } } -impl<'a, T: Api, C> ApiNoContext for ContextWrapper<'a, T, C> { - fn op10_get( - &self, - ) -> Box + Send> - { - self.api().op10_get(&self.context()) +#[async_trait] +impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for ContextWrapper { + fn poll_ready(&self, cx: &mut Context) -> Poll> { + self.api().poll_ready(cx) } - fn op11_get( - &self, - ) -> Box + Send> - { - self.api().op11_get(&self.context()) + fn context(&self) -> &C { + ContextWrapper::context(self) } - fn op12_get( + async fn op10_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op12_get(&self.context()) + let context = self.context().clone(); + self.api().op10_get(&context).await } - fn op13_get( + async fn op11_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op13_get(&self.context()) + let context = self.context().clone(); + self.api().op11_get(&context).await } - fn op14_get( + async fn op12_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op14_get(&self.context()) + let context = self.context().clone(); + self.api().op12_get(&context).await } - fn op15_get( + async fn op13_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op15_get(&self.context()) + let context = self.context().clone(); + self.api().op13_get(&context).await } - fn op16_get( + async fn op14_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op16_get(&self.context()) + let context = self.context().clone(); + self.api().op14_get(&context).await } - fn op17_get( + async fn op15_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op17_get(&self.context()) + let context = self.context().clone(); + self.api().op15_get(&context).await } - fn op18_get( + async fn op16_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op18_get(&self.context()) + let context = self.context().clone(); + self.api().op16_get(&context).await } - fn op19_get( + async fn op17_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op19_get(&self.context()) + let context = self.context().clone(); + self.api().op17_get(&context).await } - fn op1_get( + async fn op18_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op1_get(&self.context()) + let context = self.context().clone(); + self.api().op18_get(&context).await } - fn op20_get( + async fn op19_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op20_get(&self.context()) + let context = self.context().clone(); + self.api().op19_get(&context).await } - fn op21_get( + async fn op1_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op21_get(&self.context()) + let context = self.context().clone(); + self.api().op1_get(&context).await } - fn op22_get( + async fn op20_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op22_get(&self.context()) + let context = self.context().clone(); + self.api().op20_get(&context).await } - fn op23_get( + async fn op21_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op23_get(&self.context()) + let context = self.context().clone(); + self.api().op21_get(&context).await } - fn op24_get( + async fn op22_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op24_get(&self.context()) + let context = self.context().clone(); + self.api().op22_get(&context).await } - fn op25_get( + async fn op23_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op25_get(&self.context()) + let context = self.context().clone(); + self.api().op23_get(&context).await } - fn op26_get( + async fn op24_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op26_get(&self.context()) + let context = self.context().clone(); + self.api().op24_get(&context).await } - fn op27_get( + async fn op25_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op27_get(&self.context()) + let context = self.context().clone(); + self.api().op25_get(&context).await } - fn op28_get( + async fn op26_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op28_get(&self.context()) + let context = self.context().clone(); + self.api().op26_get(&context).await } - fn op29_get( + async fn op27_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op29_get(&self.context()) + let context = self.context().clone(); + self.api().op27_get(&context).await } - fn op2_get( + async fn op28_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op2_get(&self.context()) + let context = self.context().clone(); + self.api().op28_get(&context).await } - fn op30_get( + async fn op29_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op30_get(&self.context()) + let context = self.context().clone(); + self.api().op29_get(&context).await } - fn op31_get( + async fn op2_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op31_get(&self.context()) + let context = self.context().clone(); + self.api().op2_get(&context).await } - fn op32_get( + async fn op30_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op32_get(&self.context()) + let context = self.context().clone(); + self.api().op30_get(&context).await } - fn op33_get( + async fn op31_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op33_get(&self.context()) + let context = self.context().clone(); + self.api().op31_get(&context).await } - fn op34_get( + async fn op32_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op34_get(&self.context()) + let context = self.context().clone(); + self.api().op32_get(&context).await } - fn op35_get( + async fn op33_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op35_get(&self.context()) + let context = self.context().clone(); + self.api().op33_get(&context).await } - fn op36_get( + async fn op34_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op36_get(&self.context()) + let context = self.context().clone(); + self.api().op34_get(&context).await } - fn op37_get( + async fn op35_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op37_get(&self.context()) + let context = self.context().clone(); + self.api().op35_get(&context).await } - fn op3_get( + async fn op36_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op3_get(&self.context()) + let context = self.context().clone(); + self.api().op36_get(&context).await } - fn op4_get( + async fn op37_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op4_get(&self.context()) + let context = self.context().clone(); + self.api().op37_get(&context).await } - fn op5_get( + async fn op3_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op5_get(&self.context()) + let context = self.context().clone(); + self.api().op3_get(&context).await } - fn op6_get( + async fn op4_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op6_get(&self.context()) + let context = self.context().clone(); + self.api().op4_get(&context).await } - fn op7_get( + async fn op5_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op7_get(&self.context()) + let context = self.context().clone(); + self.api().op5_get(&context).await } - fn op8_get( + async fn op6_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op8_get(&self.context()) + let context = self.context().clone(); + self.api().op6_get(&context).await } - fn op9_get( + async fn op7_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().op9_get(&self.context()) + let context = self.context().clone(); + self.api().op7_get(&context).await + } + + async fn op8_get( + &self, + ) -> Result + { + let context = self.context().clone(); + self.api().op8_get(&context).await + } + + async fn op9_get( + &self, + ) -> Result + { + let context = self.context().clone(); + self.api().op9_get(&context).await } } + #[cfg(feature = "client")] pub mod client; diff --git a/samples/server/petstore/rust-server/output/ops-v3/src/server/mod.rs b/samples/server/petstore/rust-server/output/ops-v3/src/server/mod.rs index 39fc3172378..12ea69e707f 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/src/server/mod.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/src/server/mod.rs @@ -1,20 +1,17 @@ -use std::marker::PhantomData; -use futures::{Future, future, Stream, stream}; -use hyper; -use hyper::{Request, Response, Error, StatusCode, Body, HeaderMap}; +use futures::{future, future::BoxFuture, Stream, stream, future::FutureExt, stream::TryStreamExt}; +use hyper::{Request, Response, StatusCode, Body, HeaderMap}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; use log::warn; -use serde_json; #[allow(unused_imports)] use std::convert::{TryFrom, TryInto}; -use std::io; -use url::form_urlencoded; -#[allow(unused_imports)] -use swagger; -use swagger::{ApiError, XSpanIdString, Has, RequestParser}; +use std::error::Error; +use std::future::Future; +use std::marker::PhantomData; +use std::task::{Context, Poll}; +use swagger::{ApiError, BodyExt, Has, RequestParser, XSpanIdString}; pub use swagger::auth::Authorization; use swagger::auth::Scopes; -use swagger::context::ContextualPayload; +use url::form_urlencoded; #[allow(unused_imports)] use crate::models; @@ -22,6 +19,8 @@ use crate::header; pub use crate::context; +type ServiceFuture = BoxFuture<'static, Result, crate::ServiceError>>; + use crate::{Api, Op10GetResponse, Op11GetResponse, @@ -146,15 +145,17 @@ mod paths { pub(crate) static ID_OP9: usize = 36; } -pub struct MakeService { +pub struct MakeService where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static +{ api_impl: T, - marker: PhantomData, + marker: PhantomData, } -impl MakeService -where - T: Api + Clone + Send + 'static, - RC: Has + 'static +impl MakeService where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static { pub fn new(api_impl: T) -> Self { MakeService { @@ -164,44 +165,45 @@ where } } -impl<'a, T, SC, RC> hyper::service::MakeService<&'a SC> for MakeService -where - T: Api + Clone + Send + 'static, - RC: Has + 'static + Send +impl hyper::service::Service for MakeService where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static { - type ReqBody = ContextualPayload; - type ResBody = Body; - type Error = Error; - type Service = Service; - type Future = future::FutureResult; - type MakeError = Error; + type Response = Service; + type Error = crate::ServiceError; + type Future = future::Ready>; - fn make_service(&mut self, _ctx: &'a SC) -> Self::Future { - future::FutureResult::from(Ok(Service::new( + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn call(&mut self, target: Target) -> Self::Future { + futures::future::ok(Service::new( self.api_impl.clone(), - ))) + )) } } -type ServiceFuture = Box, Error = Error> + Send>; - -fn method_not_allowed() -> ServiceFuture { - Box::new(future::ok( +fn method_not_allowed() -> Result, crate::ServiceError> { + Ok( Response::builder().status(StatusCode::METHOD_NOT_ALLOWED) .body(Body::empty()) .expect("Unable to create Method Not Allowed response") - )) + ) } -pub struct Service { +pub struct Service where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static +{ api_impl: T, - marker: PhantomData, + marker: PhantomData, } -impl Service -where - T: Api + Clone + Send + 'static, - RC: Has + 'static { +impl Service where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static +{ pub fn new(api_impl: T) -> Self { Service { api_impl: api_impl, @@ -210,36 +212,48 @@ where } } -impl hyper::service::Service for Service -where +impl Clone for Service where T: Api + Clone + Send + 'static, - C: Has + 'static + Send + C: Has + Send + Sync + 'static { - type ReqBody = ContextualPayload; - type ResBody = Body; - type Error = Error; + fn clone(&self) -> Self { + Service { + api_impl: self.api_impl.clone(), + marker: self.marker.clone(), + } + } +} + +impl hyper::service::Service<(Request, C)> for Service where + T: Api + Clone + Send + Sync + 'static, + C: Has + Send + Sync + 'static +{ + type Response = Response; + type Error = crate::ServiceError; type Future = ServiceFuture; - fn call(&mut self, req: Request) -> Self::Future { - let api_impl = self.api_impl.clone(); - let (parts, body) = req.into_parts(); + fn poll_ready(&mut self, cx: &mut Context) -> Poll> { + self.api_impl.poll_ready(cx) + } + + fn call(&mut self, req: (Request, C)) -> Self::Future { async fn run(mut api_impl: T, req: (Request, C)) -> Result, crate::ServiceError> where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static + { + let (request, context) = req; + let (parts, body) = request.into_parts(); let (method, uri, headers) = (parts.method, parts.uri, parts.headers); let path = paths::GLOBAL_REGEX_SET.matches(uri.path()); - let mut context = body.context; - let body = body.inner; match &method { // Op10Get - GET /op10 &hyper::Method::GET if path.matched(paths::ID_OP10) => { - Box::new({ - {{ - Box::new( - api_impl.op10_get( + let result = api_impl.op10_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -259,23 +273,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op11Get - GET /op11 &hyper::Method::GET if path.matched(paths::ID_OP11) => { - Box::new({ - {{ - Box::new( - api_impl.op11_get( + let result = api_impl.op11_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -295,23 +302,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op12Get - GET /op12 &hyper::Method::GET if path.matched(paths::ID_OP12) => { - Box::new({ - {{ - Box::new( - api_impl.op12_get( + let result = api_impl.op12_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -331,23 +331,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op13Get - GET /op13 &hyper::Method::GET if path.matched(paths::ID_OP13) => { - Box::new({ - {{ - Box::new( - api_impl.op13_get( + let result = api_impl.op13_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -367,23 +360,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op14Get - GET /op14 &hyper::Method::GET if path.matched(paths::ID_OP14) => { - Box::new({ - {{ - Box::new( - api_impl.op14_get( + let result = api_impl.op14_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -403,23 +389,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op15Get - GET /op15 &hyper::Method::GET if path.matched(paths::ID_OP15) => { - Box::new({ - {{ - Box::new( - api_impl.op15_get( + let result = api_impl.op15_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -439,23 +418,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op16Get - GET /op16 &hyper::Method::GET if path.matched(paths::ID_OP16) => { - Box::new({ - {{ - Box::new( - api_impl.op16_get( + let result = api_impl.op16_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -475,23 +447,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op17Get - GET /op17 &hyper::Method::GET if path.matched(paths::ID_OP17) => { - Box::new({ - {{ - Box::new( - api_impl.op17_get( + let result = api_impl.op17_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -511,23 +476,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op18Get - GET /op18 &hyper::Method::GET if path.matched(paths::ID_OP18) => { - Box::new({ - {{ - Box::new( - api_impl.op18_get( + let result = api_impl.op18_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -547,23 +505,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op19Get - GET /op19 &hyper::Method::GET if path.matched(paths::ID_OP19) => { - Box::new({ - {{ - Box::new( - api_impl.op19_get( + let result = api_impl.op19_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -583,23 +534,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op1Get - GET /op1 &hyper::Method::GET if path.matched(paths::ID_OP1) => { - Box::new({ - {{ - Box::new( - api_impl.op1_get( + let result = api_impl.op1_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -619,23 +563,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op20Get - GET /op20 &hyper::Method::GET if path.matched(paths::ID_OP20) => { - Box::new({ - {{ - Box::new( - api_impl.op20_get( + let result = api_impl.op20_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -655,23 +592,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op21Get - GET /op21 &hyper::Method::GET if path.matched(paths::ID_OP21) => { - Box::new({ - {{ - Box::new( - api_impl.op21_get( + let result = api_impl.op21_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -691,23 +621,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op22Get - GET /op22 &hyper::Method::GET if path.matched(paths::ID_OP22) => { - Box::new({ - {{ - Box::new( - api_impl.op22_get( + let result = api_impl.op22_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -727,23 +650,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op23Get - GET /op23 &hyper::Method::GET if path.matched(paths::ID_OP23) => { - Box::new({ - {{ - Box::new( - api_impl.op23_get( + let result = api_impl.op23_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -763,23 +679,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op24Get - GET /op24 &hyper::Method::GET if path.matched(paths::ID_OP24) => { - Box::new({ - {{ - Box::new( - api_impl.op24_get( + let result = api_impl.op24_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -799,23 +708,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op25Get - GET /op25 &hyper::Method::GET if path.matched(paths::ID_OP25) => { - Box::new({ - {{ - Box::new( - api_impl.op25_get( + let result = api_impl.op25_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -835,23 +737,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op26Get - GET /op26 &hyper::Method::GET if path.matched(paths::ID_OP26) => { - Box::new({ - {{ - Box::new( - api_impl.op26_get( + let result = api_impl.op26_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -871,23 +766,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op27Get - GET /op27 &hyper::Method::GET if path.matched(paths::ID_OP27) => { - Box::new({ - {{ - Box::new( - api_impl.op27_get( + let result = api_impl.op27_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -907,23 +795,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op28Get - GET /op28 &hyper::Method::GET if path.matched(paths::ID_OP28) => { - Box::new({ - {{ - Box::new( - api_impl.op28_get( + let result = api_impl.op28_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -943,23 +824,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op29Get - GET /op29 &hyper::Method::GET if path.matched(paths::ID_OP29) => { - Box::new({ - {{ - Box::new( - api_impl.op29_get( + let result = api_impl.op29_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -979,23 +853,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op2Get - GET /op2 &hyper::Method::GET if path.matched(paths::ID_OP2) => { - Box::new({ - {{ - Box::new( - api_impl.op2_get( + let result = api_impl.op2_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1015,23 +882,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op30Get - GET /op30 &hyper::Method::GET if path.matched(paths::ID_OP30) => { - Box::new({ - {{ - Box::new( - api_impl.op30_get( + let result = api_impl.op30_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1051,23 +911,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op31Get - GET /op31 &hyper::Method::GET if path.matched(paths::ID_OP31) => { - Box::new({ - {{ - Box::new( - api_impl.op31_get( + let result = api_impl.op31_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1087,23 +940,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op32Get - GET /op32 &hyper::Method::GET if path.matched(paths::ID_OP32) => { - Box::new({ - {{ - Box::new( - api_impl.op32_get( + let result = api_impl.op32_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1123,23 +969,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op33Get - GET /op33 &hyper::Method::GET if path.matched(paths::ID_OP33) => { - Box::new({ - {{ - Box::new( - api_impl.op33_get( + let result = api_impl.op33_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1159,23 +998,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op34Get - GET /op34 &hyper::Method::GET if path.matched(paths::ID_OP34) => { - Box::new({ - {{ - Box::new( - api_impl.op34_get( + let result = api_impl.op34_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1195,23 +1027,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op35Get - GET /op35 &hyper::Method::GET if path.matched(paths::ID_OP35) => { - Box::new({ - {{ - Box::new( - api_impl.op35_get( + let result = api_impl.op35_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1231,23 +1056,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op36Get - GET /op36 &hyper::Method::GET if path.matched(paths::ID_OP36) => { - Box::new({ - {{ - Box::new( - api_impl.op36_get( + let result = api_impl.op36_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1267,23 +1085,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op37Get - GET /op37 &hyper::Method::GET if path.matched(paths::ID_OP37) => { - Box::new({ - {{ - Box::new( - api_impl.op37_get( + let result = api_impl.op37_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1303,23 +1114,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op3Get - GET /op3 &hyper::Method::GET if path.matched(paths::ID_OP3) => { - Box::new({ - {{ - Box::new( - api_impl.op3_get( + let result = api_impl.op3_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1339,23 +1143,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op4Get - GET /op4 &hyper::Method::GET if path.matched(paths::ID_OP4) => { - Box::new({ - {{ - Box::new( - api_impl.op4_get( + let result = api_impl.op4_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1375,23 +1172,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op5Get - GET /op5 &hyper::Method::GET if path.matched(paths::ID_OP5) => { - Box::new({ - {{ - Box::new( - api_impl.op5_get( + let result = api_impl.op5_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1411,23 +1201,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op6Get - GET /op6 &hyper::Method::GET if path.matched(paths::ID_OP6) => { - Box::new({ - {{ - Box::new( - api_impl.op6_get( + let result = api_impl.op6_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1447,23 +1230,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op7Get - GET /op7 &hyper::Method::GET if path.matched(paths::ID_OP7) => { - Box::new({ - {{ - Box::new( - api_impl.op7_get( + let result = api_impl.op7_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1483,23 +1259,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op8Get - GET /op8 &hyper::Method::GET if path.matched(paths::ID_OP8) => { - Box::new({ - {{ - Box::new( - api_impl.op8_get( + let result = api_impl.op8_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1519,23 +1288,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // Op9Get - GET /op9 &hyper::Method::GET if path.matched(paths::ID_OP9) => { - Box::new({ - {{ - Box::new( - api_impl.op9_get( + let result = api_impl.op9_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1555,11 +1317,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, _ if path.matched(paths::ID_OP1) => method_not_allowed(), @@ -1599,23 +1357,11 @@ where _ if path.matched(paths::ID_OP7) => method_not_allowed(), _ if path.matched(paths::ID_OP8) => method_not_allowed(), _ if path.matched(paths::ID_OP9) => method_not_allowed(), - _ => Box::new(future::ok( - Response::builder().status(StatusCode::NOT_FOUND) + _ => Ok(Response::builder().status(StatusCode::NOT_FOUND) .body(Body::empty()) - .expect("Unable to create Not Found response") - )) as Self::Future + .expect("Unable to create Not Found response")) } - } -} - -impl Clone for Service where T: Clone -{ - fn clone(&self) -> Self { - Service { - api_impl: self.api_impl.clone(), - marker: self.marker.clone(), - } - } + } Box::pin(run(self.api_impl.clone(), req)) } } /// Request parser for `Api`. diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/Cargo.toml b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/Cargo.toml index 1ee9b478cdb..869f0b722d7 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/Cargo.toml +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/Cargo.toml @@ -12,7 +12,7 @@ client = [ "mime_0_2", "multipart", "multipart/client", "swagger/multipart", "serde_urlencoded", - "hyper", "hyper-openssl", "native-tls", "openssl", "url" + "hyper", "hyper-openssl", "hyper-tls", "native-tls", "openssl", "url" ] server = [ "mime_0_2", @@ -23,20 +23,22 @@ conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk- [target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] native-tls = { version = "0.2", optional = true } +hyper-tls = { version = "0.4", optional = true } [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dependencies] -hyper-openssl = { version = "0.7.1", optional = true } +hyper-openssl = { version = "0.8", optional = true } openssl = {version = "0.10", optional = true } [dependencies] # Common +async-trait = "0.1.24" chrono = { version = "0.4", features = ["serde"] } -futures = "0.1" -swagger = "4.0" +futures = "0.3" +swagger = "5.0.0-alpha-1" log = "0.4.0" mime = "0.3" -serde = { version = "1.0", features = ["derive"]} +serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" # Crates included if required by the API definition @@ -45,20 +47,20 @@ serde_json = "1.0" serde-xml-rs = {git = "git://github.com/Metaswitch/serde-xml-rs.git" , branch = "master"} mime_0_2 = { package = "mime", version = "0.2.6", optional = true } multipart = { version = "0.16", default-features = false, optional = true } -uuid = {version = "0.7", features = ["serde", "v4"]} +uuid = {version = "0.8", features = ["serde", "v4"]} # Common between server and client features -hyper = {version = "0.12", optional = true} -serde_ignored = {version = "0.0.4", optional = true} -url = {version = "1.5", optional = true} +hyper = {version = "0.13", optional = true} +serde_ignored = {version = "0.1.1", optional = true} +url = {version = "2.1", optional = true} # Client-specific -serde_urlencoded = {version = "0.5.1", optional = true} +serde_urlencoded = {version = "0.6.1", optional = true} # Server, and client callback-specific lazy_static = { version = "1.4", optional = true } -percent-encoding = {version = "1.0.0", optional = true} -regex = {version = "0.2", optional = true} +percent-encoding = {version = "2.1.0", optional = true} +regex = {version = "1.3", optional = true} # Conversion frunk = { version = "0.3.0", optional = true } @@ -69,12 +71,13 @@ frunk-enum-core = { version = "0.2.0", optional = true } [dev-dependencies] clap = "2.25" -error-chain = "0.12" -env_logger = "0.6" -tokio = "0.1.17" +env_logger = "0.7" +tokio = { version = "0.2", features = ["rt-threaded", "macros", "stream"] } +native-tls = "0.2" +tokio-tls = "0.3" [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dev-dependencies] -tokio-openssl = "0.3" +tokio-openssl = "0.4" openssl = "0.10" [[example]] diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/client/main.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/client/main.rs index 289c8b8ed58..27bf15f0c0a 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/client/main.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/client/main.rs @@ -2,10 +2,9 @@ #[allow(unused_imports)] -use futures::{Future, future, Stream, stream}; +use futures::{future, Stream, stream}; #[allow(unused_imports)] use petstore_with_fake_endpoints_models_for_testing::{Api, ApiNoContext, Client, ContextWrapperExt, models, - ApiError, TestSpecialTagsResponse, Call123exampleResponse, FakeOuterBooleanSerializeResponse, @@ -40,7 +39,7 @@ use petstore_with_fake_endpoints_models_for_testing::{Api, ApiNoContext, Client, GetUserByNameResponse, LoginUserResponse, LogoutUserResponse, - UpdateUserResponse + UpdateUserResponse, }; use clap::{App, Arg}; @@ -49,7 +48,9 @@ use log::info; // swagger::Has may be unused if there are no examples #[allow(unused_imports)] -use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData}; +use swagger::{AuthData, ContextBuilder, EmptyContext, Has, Push, XSpanIdString}; + +type ClientContext = swagger::make_context_ty!(ContextBuilder, EmptyContext, Option, XSpanIdString); // rt may be unused if there are no examples #[allow(unused_mut)] @@ -109,21 +110,21 @@ fn main() { matches.value_of("host").unwrap(), matches.value_of("port").unwrap()); - let client = if matches.is_present("https") { - // Using Simple HTTPS - Client::try_new_https(&base_url) - .expect("Failed to create HTTPS client") - } else { - // Using HTTP - Client::try_new_http( - &base_url) - .expect("Failed to create HTTP client") - }; - - let context: swagger::make_context_ty!(ContextBuilder, EmptyContext, Option, XSpanIdString) = + let context: ClientContext = swagger::make_context!(ContextBuilder, EmptyContext, None as Option, XSpanIdString::default()); - let client = client.with_context(context); + let mut client : Box> = if matches.is_present("https") { + // Using Simple HTTPS + let client = Box::new(Client::try_new_https(&base_url) + .expect("Failed to create HTTPS client")); + Box::new(client.with_context(context)) + } else { + // Using HTTP + let client = Box::new(Client::try_new_http( + &base_url) + .expect("Failed to create HTTP client")); + Box::new(client.with_context(context)) + }; let mut rt = tokio::runtime::Runtime::new().unwrap(); diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/main.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/main.rs index dd00042a44b..89c605578a1 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/main.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/main.rs @@ -9,7 +9,8 @@ mod server; /// Create custom server, wire it to the autogenerated router, /// and pass it to the web server. -fn main() { +#[tokio::main] +async fn main() { env_logger::init(); let matches = App::new("server") @@ -20,5 +21,5 @@ fn main() { let addr = "127.0.0.1:80"; - hyper::rt::run(server::create(addr, matches.is_present("https"))); + server::create(addr, matches.is_present("https")).await; } diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/server.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/server.rs index d80bdcd6d25..76d906cb18d 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/server.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/server.rs @@ -2,30 +2,22 @@ #![allow(unused_imports)] -mod errors { - error_chain::error_chain!{} -} - -pub use self::errors::*; - -use chrono; -use futures::{future, Future, Stream}; +use async_trait::async_trait; +use futures::{future, Stream, StreamExt, TryFutureExt, TryStreamExt}; use hyper::server::conn::Http; -use hyper::service::MakeService as _; +use hyper::service::Service; use log::info; use openssl::ssl::SslAcceptorBuilder; +use std::future::Future; use std::marker::PhantomData; use std::net::SocketAddr; use std::sync::{Arc, Mutex}; -use swagger; +use std::task::{Context, Poll}; use swagger::{Has, XSpanIdString}; use swagger::auth::MakeAllowAllAuthenticator; use swagger::EmptyContext; use tokio::net::TcpListener; -use uuid; -#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] -use tokio_openssl::SslAcceptorExt; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; @@ -33,18 +25,18 @@ use petstore_with_fake_endpoints_models_for_testing::models; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] /// Builds an SSL implementation for Simple HTTPS from some hard-coded file names -pub fn create(addr: &str, https: bool) -> Box + Send> { +pub async fn create(addr: &str, https: bool) { let addr = addr.parse().expect("Failed to parse bind address"); let server = Server::new(); - let service_fn = MakeService::new(server); + let service = MakeService::new(server); - let service_fn = MakeAllowAllAuthenticator::new(service_fn, "cosmo"); + let service = MakeAllowAllAuthenticator::new(service, "cosmo"); - let service_fn = + let mut service = petstore_with_fake_endpoints_models_for_testing::server::context::MakeAddContext::<_, EmptyContext>::new( - service_fn + service ); if https { @@ -62,32 +54,31 @@ pub fn create(addr: &str, https: bool) -> Box ssl.set_certificate_chain_file("examples/server-chain.pem").expect("Failed to set cerificate chain"); ssl.check_private_key().expect("Failed to check private key"); - let tls_acceptor = ssl.build(); - let service_fn = Arc::new(Mutex::new(service_fn)); - let tls_listener = TcpListener::bind(&addr).unwrap().incoming().for_each(move |tcp| { - let addr = tcp.peer_addr().expect("Unable to get remote address"); + let tls_acceptor = Arc::new(ssl.build()); + let mut tcp_listener = TcpListener::bind(&addr).await.unwrap(); + let mut incoming = tcp_listener.incoming(); - let service_fn = service_fn.clone(); + while let (Some(tcp), rest) = incoming.into_future().await { + if let Ok(tcp) = tcp { + let addr = tcp.peer_addr().expect("Unable to get remote address"); + let service = service.call(addr); + let tls_acceptor = Arc::clone(&tls_acceptor); - hyper::rt::spawn(tls_acceptor.accept_async(tcp).map_err(|_| ()).and_then(move |tls| { - let ms = { - let mut service_fn = service_fn.lock().unwrap(); - service_fn.make_service(&addr) - }; + tokio::spawn(async move { + let tls = tokio_openssl::accept(&*tls_acceptor, tcp).await.map_err(|_| ())?; - ms.and_then(move |service| { - Http::new().serve_connection(tls, service) - }).map_err(|_| ()) - })); + let service = service.await.map_err(|_| ())?; - Ok(()) - }).map_err(|_| ()); + Http::new().serve_connection(tls, service).await.map_err(|_| ()) + }); + } - Box::new(tls_listener) + incoming = rest; + } } } else { // Using HTTP - Box::new(hyper::server::Server::bind(&addr).serve(service_fn).map_err(|e| panic!("{:?}", e))) + hyper::server::Server::bind(&addr).serve(service).await.unwrap() } } @@ -105,7 +96,6 @@ impl Server { use petstore_with_fake_endpoints_models_for_testing::{ Api, - ApiError, TestSpecialTagsResponse, Call123exampleResponse, FakeOuterBooleanSerializeResponse, @@ -143,111 +133,115 @@ use petstore_with_fake_endpoints_models_for_testing::{ UpdateUserResponse, }; use petstore_with_fake_endpoints_models_for_testing::server::MakeService; +use std::error::Error; +use swagger::ApiError; -impl Api for Server where C: Has{ +#[async_trait] +impl Api for Server where C: Has + Send + Sync +{ /// To test special tags - fn test_special_tags( + async fn test_special_tags( &self, body: models::Client, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("test_special_tags({:?}) - X-Span-ID: {:?}", body, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn call123example( + async fn call123example( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("call123example() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn fake_outer_boolean_serialize( + async fn fake_outer_boolean_serialize( &self, body: Option, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("fake_outer_boolean_serialize({:?}) - X-Span-ID: {:?}", body, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn fake_outer_composite_serialize( + async fn fake_outer_composite_serialize( &self, body: Option, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("fake_outer_composite_serialize({:?}) - X-Span-ID: {:?}", body, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn fake_outer_number_serialize( + async fn fake_outer_number_serialize( &self, body: Option, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("fake_outer_number_serialize({:?}) - X-Span-ID: {:?}", body, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn fake_outer_string_serialize( + async fn fake_outer_string_serialize( &self, body: Option, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("fake_outer_string_serialize({:?}) - X-Span-ID: {:?}", body, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn fake_response_with_numerical_description( + async fn fake_response_with_numerical_description( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("fake_response_with_numerical_description() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn hyphen_param( + async fn hyphen_param( &self, hyphen_param: String, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("hyphen_param(\"{}\") - X-Span-ID: {:?}", hyphen_param, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn test_body_with_query_params( + async fn test_body_with_query_params( &self, query: String, body: models::User, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("test_body_with_query_params(\"{}\", {:?}) - X-Span-ID: {:?}", query, body, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// To test \"client\" model - fn test_client_model( + async fn test_client_model( &self, body: models::Client, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("test_client_model({:?}) - X-Span-ID: {:?}", body, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트 - fn test_endpoint_parameters( + async fn test_endpoint_parameters( &self, number: f64, double: f64, @@ -263,15 +257,15 @@ impl Api for Server where C: Has{ date_time: Option>, password: Option, callback: Option, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("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(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// To test enum parameters - fn test_enum_parameters( + async fn test_enum_parameters( &self, enum_header_string_array: Option<&Vec>, enum_header_string: Option, @@ -280,270 +274,270 @@ impl Api for Server where C: Has{ enum_query_integer: Option, enum_query_double: Option, enum_form_string: Option, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("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(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// test inline additionalProperties - fn test_inline_additional_properties( + async fn test_inline_additional_properties( &self, param: std::collections::HashMap, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("test_inline_additional_properties({:?}) - X-Span-ID: {:?}", param, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// test json serialization of form data - fn test_json_form_data( + async fn test_json_form_data( &self, param: String, param2: String, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("test_json_form_data(\"{}\", \"{}\") - X-Span-ID: {:?}", param, param2, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// To test class name in snake case - fn test_classname( + async fn test_classname( &self, body: models::Client, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("test_classname({:?}) - X-Span-ID: {:?}", body, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Add a new pet to the store - fn add_pet( + async fn add_pet( &self, body: models::Pet, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("add_pet({:?}) - X-Span-ID: {:?}", body, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Deletes a pet - fn delete_pet( + async fn delete_pet( &self, pet_id: i64, api_key: Option, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("delete_pet({}, {:?}) - X-Span-ID: {:?}", pet_id, api_key, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Finds Pets by status - fn find_pets_by_status( + async fn find_pets_by_status( &self, status: &Vec, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("find_pets_by_status({:?}) - X-Span-ID: {:?}", status, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Finds Pets by tags - fn find_pets_by_tags( + async fn find_pets_by_tags( &self, tags: &Vec, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("find_pets_by_tags({:?}) - X-Span-ID: {:?}", tags, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Find pet by ID - fn get_pet_by_id( + async fn get_pet_by_id( &self, pet_id: i64, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("get_pet_by_id({}) - X-Span-ID: {:?}", pet_id, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Update an existing pet - fn update_pet( + async fn update_pet( &self, body: models::Pet, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("update_pet({:?}) - X-Span-ID: {:?}", body, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Updates a pet in the store with form data - fn update_pet_with_form( + async fn update_pet_with_form( &self, pet_id: i64, name: Option, status: Option, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("update_pet_with_form({}, {:?}, {:?}) - X-Span-ID: {:?}", pet_id, name, status, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// uploads an image - fn upload_file( + async fn upload_file( &self, pet_id: i64, additional_metadata: Option, file: Option, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("upload_file({}, {:?}, {:?}) - X-Span-ID: {:?}", pet_id, additional_metadata, file, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Delete purchase order by ID - fn delete_order( + async fn delete_order( &self, order_id: String, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("delete_order(\"{}\") - X-Span-ID: {:?}", order_id, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Returns pet inventories by status - fn get_inventory( + async fn get_inventory( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("get_inventory() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Find purchase order by ID - fn get_order_by_id( + async fn get_order_by_id( &self, order_id: i64, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("get_order_by_id({}) - X-Span-ID: {:?}", order_id, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Place an order for a pet - fn place_order( + async fn place_order( &self, body: models::Order, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("place_order({:?}) - X-Span-ID: {:?}", body, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Create user - fn create_user( + async fn create_user( &self, body: models::User, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("create_user({:?}) - X-Span-ID: {:?}", body, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Creates list of users with given input array - fn create_users_with_array_input( + async fn create_users_with_array_input( &self, body: &Vec, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("create_users_with_array_input({:?}) - X-Span-ID: {:?}", body, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Creates list of users with given input array - fn create_users_with_list_input( + async fn create_users_with_list_input( &self, body: &Vec, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("create_users_with_list_input({:?}) - X-Span-ID: {:?}", body, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Delete user - fn delete_user( + async fn delete_user( &self, username: String, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("delete_user(\"{}\") - X-Span-ID: {:?}", username, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Get user by user name - fn get_user_by_name( + async fn get_user_by_name( &self, username: String, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("get_user_by_name(\"{}\") - X-Span-ID: {:?}", username, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Logs user into the system - fn login_user( + async fn login_user( &self, username: String, password: String, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("login_user(\"{}\", \"{}\") - X-Span-ID: {:?}", username, password, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Logs out current logged in user session - fn logout_user( + async fn logout_user( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("logout_user() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Updated user - fn update_user( + async fn update_user( &self, username: String, body: models::User, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("update_user(\"{}\", {:?}) - X-Span-ID: {:?}", username, body, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } } diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/client/mod.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/client/mod.rs index a6fd7282c34..f6e3986c318 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/client/mod.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/client/mod.rs @@ -1,42 +1,41 @@ -use futures; -use futures::{Future, Stream, future, stream}; -use hyper; -use hyper::client::HttpConnector; +use async_trait::async_trait; +use futures::{Stream, future, future::BoxFuture, stream, future::TryFutureExt, future::FutureExt, stream::StreamExt}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; -use hyper::{Body, Uri, Response}; -#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] -use hyper_openssl::HttpsConnector; -use serde_json; +use hyper::{Body, Request, Response, service::Service, Uri}; +use percent_encoding::{utf8_percent_encode, AsciiSet}; use std::borrow::Cow; use std::convert::TryInto; -use std::io::{Read, Error, ErrorKind}; -use std::error; +use std::io::{ErrorKind, Read}; +use std::error::Error; +use std::future::Future; use std::fmt; use std::path::Path; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use std::str; use std::str::FromStr; use std::string::ToString; -use swagger; -use swagger::{ApiError, Connector, client::Service, XSpanIdString, Has, AuthData}; +use std::task::{Context, Poll}; +use swagger::{ApiError, AuthData, BodyExt, Connector, Has, XSpanIdString}; use url::form_urlencoded; -use url::percent_encoding::{utf8_percent_encode, PATH_SEGMENT_ENCODE_SET, QUERY_ENCODE_SET}; + use mime::Mime; use std::io::Cursor; use multipart::client::lazy::Multipart; -use uuid; -use serde_xml_rs; use crate::models; use crate::header; -url::define_encode_set! { - /// This encode set is used for object IDs - /// - /// Aside from the special characters defined in the `PATH_SEGMENT_ENCODE_SET`, - /// the vertical bar (|) is encoded. - pub ID_ENCODE_SET = [PATH_SEGMENT_ENCODE_SET] | {'|'} -} +/// https://url.spec.whatwg.org/#fragment-percent-encode-set +#[allow(dead_code)] +const FRAGMENT_ENCODE_SET: &AsciiSet = &percent_encoding::CONTROLS + .add(b' ').add(b'"').add(b'<').add(b'>').add(b'`'); + +/// This encode set is used for object IDs +/// +/// Aside from the special characters defined in the `PATH_SEGMENT_ENCODE_SET`, +/// the vertical bar (|) is encoded. +#[allow(dead_code)] +const ID_ENCODE_SET: &AsciiSet = &FRAGMENT_ENCODE_SET.add(b'|'); use crate::{Api, TestSpecialTagsResponse, @@ -77,11 +76,11 @@ use crate::{Api, }; /// Convert input into a base path, e.g. "http://example:123". Also checks the scheme as it goes. -fn into_base_path(input: &str, correct_scheme: Option<&'static str>) -> Result { +fn into_base_path(input: impl TryInto, correct_scheme: Option<&'static str>) -> Result { // First convert to Uri, since a base path is a subset of Uri. - let uri = Uri::from_str(input)?; + let uri = input.try_into()?; - let scheme = uri.scheme_part().ok_or(ClientInitError::InvalidScheme)?; + let scheme = uri.scheme_str().ok_or(ClientInitError::InvalidScheme)?; // Check the scheme if necessary if let Some(correct_scheme) = correct_scheme { @@ -91,38 +90,54 @@ fn into_base_path(input: &str, correct_scheme: Option<&'static str>) -> Result +pub struct Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { /// Inner service - client_service: Arc + Send + Sync>>, + client_service: S, /// Base path of the API base_path: String, } -impl fmt::Debug for Client +impl fmt::Debug for Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Client {{ base_path: {} }}", self.base_path) } } -impl Clone for Client +impl Clone for Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { fn clone(&self) -> Self { - Client { + Self { client_service: self.client_service.clone(), base_path: self.base_path.clone(), } } } -impl Client +impl Client> where + C: hyper::client::connect::Connect + Clone + Send + Sync + 'static { /// Create a client with a custom implementation of hyper::client::Connect. /// @@ -135,30 +150,93 @@ impl Client /// /// # Arguments /// - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "http://www.my-api-implementation.com" /// * `protocol` - Which protocol to use when constructing the request url, e.g. `Some("http")` /// * `connector` - Implementation of `hyper::client::Connect` to use for the client - pub fn try_new_with_connector( + pub fn try_new_with_connector( base_path: &str, protocol: Option<&'static str>, connector: C, - ) -> Result where - C: hyper::client::connect::Connect + 'static, - C::Transport: 'static, - C::Future: 'static, + ) -> Result { - let client_service = Box::new(hyper::client::Client::builder().build(connector)); + let client_service = hyper::client::Client::builder().build(connector); - Ok(Client { - client_service: Arc::new(client_service), + Ok(Self { + client_service, base_path: into_base_path(base_path, protocol)?, }) } +} +#[derive(Debug, Clone)] +pub enum HyperClient { + Http(hyper::client::Client), + Https(hyper::client::Client), +} + +impl Service> for HyperClient { + type Response = Response; + type Error = hyper::Error; + type Future = hyper::client::ResponseFuture; + + fn poll_ready(&mut self, cx: &mut Context) -> Poll> { + match self { + HyperClient::Http(client) => client.poll_ready(cx), + HyperClient::Https(client) => client.poll_ready(cx), + } + } + + fn call(&mut self, req: Request) -> Self::Future { + match self { + HyperClient::Http(client) => client.call(req), + HyperClient::Https(client) => client.call(req) + } + } +} + +impl Client { /// Create an HTTP client. /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "http://www.my-api-implementation.com" + pub fn try_new( + base_path: &str, + ) -> Result { + let uri = Uri::from_str(base_path)?; + + let scheme = uri.scheme_str().ok_or(ClientInitError::InvalidScheme)?; + let scheme = scheme.to_ascii_lowercase(); + + let connector = Connector::builder(); + + let client_service = match scheme.as_str() { + "http" => { + HyperClient::Http(hyper::client::Client::builder().build(connector.build())) + }, + "https" => { + let connector = connector.https() + .build() + .map_err(|e| ClientInitError::SslError(e))?; + HyperClient::Https(hyper::client::Client::builder().build(connector)) + }, + _ => { + return Err(ClientInitError::InvalidScheme); + } + }; + + Ok(Self { + client_service, + base_path: into_base_path(base_path, None)?, + }) + } +} + +impl Client> +{ + /// Create an HTTP client. + /// + /// # Arguments + /// * `base_path` - base path of the client API, i.e. "http://www.my-api-implementation.com" pub fn try_new_http( base_path: &str, ) -> Result { @@ -166,11 +244,20 @@ impl Client Self::try_new_with_connector(base_path, Some("http"), http_connector) } +} +#[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] +type HttpsConnector = hyper_tls::HttpsConnector; + +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +type HttpsConnector = hyper_openssl::HttpsConnector; + +impl Client> +{ /// Create a client with a TLS connection to the server /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "https://www.my-api-implementation.com" pub fn try_new_https(base_path: &str) -> Result { let https_connector = Connector::builder() @@ -183,7 +270,7 @@ impl Client /// Create a client with a TLS connection to the server using a pinned certificate /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "https://www.my-api-implementation.com" /// * `ca_certificate` - Path to CA certificate used to authenticate the server #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] pub fn try_new_https_pinned( @@ -204,7 +291,7 @@ impl Client /// Create a client with a mutually authenticated TLS connection to the server. /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "https://www.my-api-implementation.com" /// * `ca_certificate` - Path to CA certificate used to authenticate the server /// * `client_key` - Path to the client private key /// * `client_certificate` - Path to the client's public certificate associated with the private key @@ -230,17 +317,24 @@ impl Client } } -impl Client +impl Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { - /// Constructor for creating a `Client` by passing in a pre-made `swagger::Service` + /// Constructor for creating a `Client` by passing in a pre-made `hyper::service::Service` / + /// `tower::Service` /// /// This allows adding custom wrappers around the underlying transport, for example for logging. pub fn try_new_with_client_service( - client_service: Arc + Send + Sync>>, + client_service: S, base_path: &str, - ) -> Result { - Ok(Client { - client_service: client_service, + ) -> Result + { + Ok(Self { + client_service, base_path: into_base_path(base_path, None)?, }) } @@ -280,45 +374,61 @@ impl fmt::Display for ClientInitError { } } -impl error::Error for ClientInitError { +impl Error for ClientInitError { fn description(&self) -> &str { "Failed to produce a hyper client." } } -impl Api for Client where - C: Has + Has>, - F: Future, Error=hyper::Error> + Send + 'static +#[async_trait] +impl Api for Client where + C: Has + Has> + Clone + Send + Sync + 'static, + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { - fn test_special_tags( + fn poll_ready(&self, cx: &mut Context) -> Poll> { + match self.client_service.clone().poll_ready(cx) { + Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())), + Poll::Ready(Ok(o)) => Poll::Ready(Ok(o)), + Poll::Pending => Poll::Pending, + } + } + + async fn test_special_tags( &self, param_body: models::Client, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/another-fake/dummy", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("PATCH") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; // Body parameter @@ -329,162 +439,152 @@ impl Api for Client where let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - serde_json::from_str::(body) - .map_err(|e| e.into()) - ) - ) - .map(move |body| { - TestSpecialTagsResponse::SuccessfulOperation - (body) - }) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(body)?; + Ok(TestSpecialTagsResponse::SuccessfulOperation + (body) + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn call123example( + async fn call123example( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/fake/operation-with-numeric-id", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - Call123exampleResponse::Success - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + Call123exampleResponse::Success + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn fake_outer_boolean_serialize( + async fn fake_outer_boolean_serialize( &self, param_body: Option, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/fake/outer/boolean", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let body = param_body.map(|ref body| { @@ -497,90 +597,82 @@ impl Api for Client where let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - serde_json::from_str::(body) - .map_err(|e| e.into()) - ) - ) - .map(move |body| { - FakeOuterBooleanSerializeResponse::OutputBoolean - (body) - }) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(body)?; + Ok(FakeOuterBooleanSerializeResponse::OutputBoolean + (body) + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn fake_outer_composite_serialize( + async fn fake_outer_composite_serialize( &self, param_body: Option, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/fake/outer/composite", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let body = param_body.map(|ref body| { @@ -593,90 +685,82 @@ impl Api for Client where let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - serde_json::from_str::(body) - .map_err(|e| e.into()) - ) - ) - .map(move |body| { - FakeOuterCompositeSerializeResponse::OutputComposite - (body) - }) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(body)?; + Ok(FakeOuterCompositeSerializeResponse::OutputComposite + (body) + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn fake_outer_number_serialize( + async fn fake_outer_number_serialize( &self, param_body: Option, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/fake/outer/number", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let body = param_body.map(|ref body| { @@ -689,90 +773,82 @@ impl Api for Client where let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - serde_json::from_str::(body) - .map_err(|e| e.into()) - ) - ) - .map(move |body| { - FakeOuterNumberSerializeResponse::OutputNumber - (body) - }) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(body)?; + Ok(FakeOuterNumberSerializeResponse::OutputNumber + (body) + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn fake_outer_string_serialize( + async fn fake_outer_string_serialize( &self, param_body: Option, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/fake/outer/string", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let body = param_body.map(|ref body| { @@ -785,137 +861,125 @@ impl Api for Client where let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - serde_json::from_str::(body) - .map_err(|e| e.into()) - ) - ) - .map(move |body| { - FakeOuterStringSerializeResponse::OutputString - (body) - }) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(body)?; + Ok(FakeOuterStringSerializeResponse::OutputString + (body) + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn fake_response_with_numerical_description( + async fn fake_response_with_numerical_description( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/fake/response-with-numerical-description", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - FakeResponseWithNumericalDescriptionResponse::Status200 - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + FakeResponseWithNumericalDescriptionResponse::Status200 + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn hyphen_param( + async fn hyphen_param( &self, param_hyphen_param: String, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/fake/hyphenParam/{hyphen_param}", self.base_path @@ -923,98 +987,98 @@ impl Api for Client where ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - HyphenParamResponse::Success - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + HyphenParamResponse::Success + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn test_body_with_query_params( + async fn test_body_with_query_params( &self, param_query: String, param_body: models::User, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/fake/body-with-query-params", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - query_string.append_pair("query", ¶m_query.to_string()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.append_pair("query", ¶m_query.to_string()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("PUT") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); @@ -1023,78 +1087,76 @@ impl Api for Client where let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - TestBodyWithQueryParamsResponse::Success - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + TestBodyWithQueryParamsResponse::Success + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn test_client_model( + async fn test_client_model( &self, param_body: models::Client, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/fake", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("PATCH") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); @@ -1103,62 +1165,51 @@ impl Api for Client where let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - serde_json::from_str::(body) - .map_err(|e| e.into()) - ) - ) - .map(move |body| { - TestClientModelResponse::SuccessfulOperation - (body) - }) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(body)?; + Ok(TestClientModelResponse::SuccessfulOperation + (body) + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn test_endpoint_parameters( + async fn test_endpoint_parameters( &self, param_number: f64, param_double: f64, @@ -1174,32 +1225,35 @@ impl Api for Client where param_date_time: Option>, param_password: Option, param_callback: Option, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/fake", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let params = &[ @@ -1223,23 +1277,23 @@ impl Api for Client where let header = "application/x-www-form-urlencoded"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); *request.body_mut() = Body::from(body.into_bytes()); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - if let Some(auth_data) = (context as &dyn Has>).get().as_ref() { + if let Some(auth_data) = Has::>::get(context).as_ref() { // Currently only authentication with Basic and Bearer are supported match auth_data { &AuthData::Basic(ref basic_header) => { let auth = swagger::auth::Header(basic_header.clone()); let header = match HeaderValue::from_str(&format!("{}", auth)) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create Authorization header: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create Authorization header: {}", e))) }; request.headers_mut().insert( hyper::header::AUTHORIZATION, @@ -1249,50 +1303,43 @@ impl Api for Client where } } - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 400 => { - let body = response.into_body(); - Box::new( - future::ok( - TestEndpointParametersResponse::InvalidUsernameSupplied - ) - ) as Box + Send> - }, - 404 => { - let body = response.into_body(); - Box::new( - future::ok( - TestEndpointParametersResponse::UserNotFound - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 400 => { + let body = response.into_body(); + Ok( + TestEndpointParametersResponse::InvalidUsernameSupplied + ) } - })) + 404 => { + let body = response.into_body(); + Ok( + TestEndpointParametersResponse::UserNotFound + ) + } + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn test_enum_parameters( + async fn test_enum_parameters( &self, param_enum_header_string_array: Option<&Vec>, param_enum_header_string: Option, @@ -1301,44 +1348,47 @@ impl Api for Client where param_enum_query_integer: Option, param_enum_query_double: Option, param_enum_form_string: Option, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/fake", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - if let Some(param_enum_query_string_array) = param_enum_query_string_array { - query_string.append_pair("enum_query_string_array", ¶m_enum_query_string_array.iter().map(ToString::to_string).collect::>().join(",")); - } - if let Some(param_enum_query_string) = param_enum_query_string { - query_string.append_pair("enum_query_string", ¶m_enum_query_string.to_string()); - } - if let Some(param_enum_query_integer) = param_enum_query_integer { - query_string.append_pair("enum_query_integer", ¶m_enum_query_integer.to_string()); - } - if let Some(param_enum_query_double) = param_enum_query_double { - query_string.append_pair("enum_query_double", ¶m_enum_query_double.to_string()); - } - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + if let Some(param_enum_query_string_array) = param_enum_query_string_array { + query_string.append_pair("enum_query_string_array", ¶m_enum_query_string_array.iter().map(ToString::to_string).collect::>().join(",")); + } + if let Some(param_enum_query_string) = param_enum_query_string { + query_string.append_pair("enum_query_string", ¶m_enum_query_string.to_string()); + } + if let Some(param_enum_query_integer) = param_enum_query_integer { + query_string.append_pair("enum_query_integer", ¶m_enum_query_integer.to_string()); + } + if let Some(param_enum_query_double) = param_enum_query_double { + query_string.append_pair("enum_query_double", ¶m_enum_query_double.to_string()); + } + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let params = &[ @@ -1349,13 +1399,13 @@ impl Api for Client where let header = "application/x-www-form-urlencoded"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); *request.body_mut() = Body::from(body.into_bytes()); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); // Header parameters @@ -1366,8 +1416,8 @@ impl Api for Client where match header::IntoHeaderValue(param_enum_header_string_array.clone()).try_into() { Ok(header) => header, Err(e) => { - return Box::new(future::err(ApiError(format!( - "Invalid header enum_header_string_array - {}", e)))) as Box + Send>; + return Err(ApiError(format!( + "Invalid header enum_header_string_array - {}", e))); }, }); }, @@ -1381,86 +1431,82 @@ impl Api for Client where match header::IntoHeaderValue(param_enum_header_string.clone()).try_into() { Ok(header) => header, Err(e) => { - return Box::new(future::err(ApiError(format!( - "Invalid header enum_header_string - {}", e)))) as Box + Send>; + return Err(ApiError(format!( + "Invalid header enum_header_string - {}", e))); }, }); }, None => {} } - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 400 => { - let body = response.into_body(); - Box::new( - future::ok( - TestEnumParametersResponse::InvalidRequest - ) - ) as Box + Send> - }, - 404 => { - let body = response.into_body(); - Box::new( - future::ok( - TestEnumParametersResponse::NotFound - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 400 => { + let body = response.into_body(); + Ok( + TestEnumParametersResponse::InvalidRequest + ) } - })) + 404 => { + let body = response.into_body(); + Ok( + TestEnumParametersResponse::NotFound + ) + } + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn test_inline_additional_properties( + async fn test_inline_additional_properties( &self, param_param: std::collections::HashMap, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/fake/inline-additionalProperties", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let body = serde_json::to_string(¶m_param).expect("impossible to fail to serialize"); @@ -1469,79 +1515,77 @@ impl Api for Client where let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - TestInlineAdditionalPropertiesResponse::SuccessfulOperation - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + TestInlineAdditionalPropertiesResponse::SuccessfulOperation + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn test_json_form_data( + async fn test_json_form_data( &self, param_param: String, param_param2: String, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/fake/jsonFormData", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let params = &[ @@ -1553,84 +1597,82 @@ impl Api for Client where let header = "application/x-www-form-urlencoded"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); *request.body_mut() = Body::from(body.into_bytes()); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - TestJsonFormDataResponse::SuccessfulOperation - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + TestJsonFormDataResponse::SuccessfulOperation + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn test_classname( + async fn test_classname( &self, param_body: models::Client, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/fake_classname_test", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - if let Some(auth_data) = (context as &dyn Has>).get().as_ref() { - if let AuthData::ApiKey(ref api_key) = *auth_data { - query_string.append_pair("api_key_query", api_key); + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + if let Some(auth_data) = (context as &dyn Has>).get().as_ref() { + if let AuthData::ApiKey(ref api_key) = *auth_data { + query_string.append_pair("api_key_query", api_key); + } } - } - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("PATCH") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; // Body parameter @@ -1641,98 +1683,90 @@ impl Api for Client where let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - if let Some(auth_data) = (context as &dyn Has>).get().as_ref() { + if let Some(auth_data) = Has::>::get(context).as_ref() { // Currently only authentication with Basic and Bearer are supported match auth_data { _ => {} } } - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - serde_json::from_str::(body) - .map_err(|e| e.into()) - ) - ) - .map(move |body| { - TestClassnameResponse::SuccessfulOperation - (body) - }) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(body)?; + Ok(TestClassnameResponse::SuccessfulOperation + (body) + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn add_pet( + async fn add_pet( &self, param_body: models::Pet, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/pet", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; // Body parameter @@ -1742,22 +1776,22 @@ impl Api for Client where let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - if let Some(auth_data) = (context as &dyn Has>).get().as_ref() { + if let Some(auth_data) = Has::>::get(context).as_ref() { // Currently only authentication with Basic and Bearer are supported match auth_data { &AuthData::Bearer(ref bearer_header) => { let auth = swagger::auth::Header(bearer_header.clone()); let header = match HeaderValue::from_str(&format!("{}", auth)) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create Authorization header: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create Authorization header: {}", e))) }; request.headers_mut().insert( hyper::header::AUTHORIZATION, @@ -1767,47 +1801,43 @@ impl Api for Client where } } - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 405 => { - let body = response.into_body(); - Box::new( - future::ok( - AddPetResponse::InvalidInput - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 405 => { + let body = response.into_body(); + Ok( + AddPetResponse::InvalidInput + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn delete_pet( + async fn delete_pet( &self, param_pet_id: i64, param_api_key: Option, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/pet/{pet_id}", self.base_path @@ -1815,40 +1845,42 @@ impl Api for Client where ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("DELETE") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - if let Some(auth_data) = (context as &dyn Has>).get().as_ref() { + if let Some(auth_data) = Has::>::get(context).as_ref() { // Currently only authentication with Basic and Bearer are supported match auth_data { &AuthData::Bearer(ref bearer_header) => { let auth = swagger::auth::Header(bearer_header.clone()); let header = match HeaderValue::from_str(&format!("{}", auth)) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create Authorization header: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create Authorization header: {}", e))) }; request.headers_mut().insert( hyper::header::AUTHORIZATION, @@ -1866,95 +1898,93 @@ impl Api for Client where match header::IntoHeaderValue(param_api_key.clone()).try_into() { Ok(header) => header, Err(e) => { - return Box::new(future::err(ApiError(format!( - "Invalid header api_key - {}", e)))) as Box + Send>; + return Err(ApiError(format!( + "Invalid header api_key - {}", e))); }, }); }, None => {} } - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 400 => { - let body = response.into_body(); - Box::new( - future::ok( - DeletePetResponse::InvalidPetValue - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 400 => { + let body = response.into_body(); + Ok( + DeletePetResponse::InvalidPetValue + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn find_pets_by_status( + async fn find_pets_by_status( &self, param_status: &Vec, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/pet/findByStatus", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - query_string.append_pair("status", ¶m_status.iter().map(ToString::to_string).collect::>().join(",")); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.append_pair("status", ¶m_status.iter().map(ToString::to_string).collect::>().join(",")); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - if let Some(auth_data) = (context as &dyn Has>).get().as_ref() { + if let Some(auth_data) = Has::>::get(context).as_ref() { // Currently only authentication with Basic and Bearer are supported match auth_data { &AuthData::Bearer(ref bearer_header) => { let auth = swagger::auth::Header(bearer_header.clone()); let header = match HeaderValue::from_str(&format!("{}", auth)) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create Authorization header: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create Authorization header: {}", e))) }; request.headers_mut().insert( hyper::header::AUTHORIZATION, @@ -1964,109 +1994,100 @@ impl Api for Client where } } - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - // ToDo: this will move to swagger-rs and become a standard From conversion trait - // once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream - serde_xml_rs::from_str::>(body) - .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e))) - ) - ) - .map(move |body| { - FindPetsByStatusResponse::SuccessfulOperation - (body) - }) - ) as Box + Send> - }, - 400 => { - let body = response.into_body(); - Box::new( - future::ok( - FindPetsByStatusResponse::InvalidStatusValue - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + // ToDo: this will move to swagger-rs and become a standard From conversion trait + // once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream + let body = serde_xml_rs::from_str::>(body) + .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e)))?; + Ok(FindPetsByStatusResponse::SuccessfulOperation + (body) + ) } - })) + 400 => { + let body = response.into_body(); + Ok( + FindPetsByStatusResponse::InvalidStatusValue + ) + } + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn find_pets_by_tags( + async fn find_pets_by_tags( &self, param_tags: &Vec, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/pet/findByTags", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - query_string.append_pair("tags", ¶m_tags.iter().map(ToString::to_string).collect::>().join(",")); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.append_pair("tags", ¶m_tags.iter().map(ToString::to_string).collect::>().join(",")); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - if let Some(auth_data) = (context as &dyn Has>).get().as_ref() { + if let Some(auth_data) = Has::>::get(context).as_ref() { // Currently only authentication with Basic and Bearer are supported match auth_data { &AuthData::Bearer(ref bearer_header) => { let auth = swagger::auth::Header(bearer_header.clone()); let header = match HeaderValue::from_str(&format!("{}", auth)) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create Authorization header: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create Authorization header: {}", e))) }; request.headers_mut().insert( hyper::header::AUTHORIZATION, @@ -2076,68 +2097,57 @@ impl Api for Client where } } - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - // ToDo: this will move to swagger-rs and become a standard From conversion trait - // once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream - serde_xml_rs::from_str::>(body) - .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e))) - ) - ) - .map(move |body| { - FindPetsByTagsResponse::SuccessfulOperation - (body) - }) - ) as Box + Send> - }, - 400 => { - let body = response.into_body(); - Box::new( - future::ok( - FindPetsByTagsResponse::InvalidTagValue - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + // ToDo: this will move to swagger-rs and become a standard From conversion trait + // once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream + let body = serde_xml_rs::from_str::>(body) + .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e)))?; + Ok(FindPetsByTagsResponse::SuccessfulOperation + (body) + ) } - })) + 400 => { + let body = response.into_body(); + Ok( + FindPetsByTagsResponse::InvalidTagValue + ) + } + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn get_pet_by_id( + async fn get_pet_by_id( &self, param_pet_id: i64, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/pet/{pet_id}", self.base_path @@ -2145,133 +2155,124 @@ impl Api for Client where ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - if let Some(auth_data) = (context as &dyn Has>).get().as_ref() { + if let Some(auth_data) = Has::>::get(context).as_ref() { // Currently only authentication with Basic and Bearer are supported match auth_data { _ => {} } } - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - // ToDo: this will move to swagger-rs and become a standard From conversion trait - // once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream - serde_xml_rs::from_str::(body) - .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e))) - ) - ) - .map(move |body| { - GetPetByIdResponse::SuccessfulOperation - (body) - }) - ) as Box + Send> - }, - 400 => { - let body = response.into_body(); - Box::new( - future::ok( - GetPetByIdResponse::InvalidIDSupplied - ) - ) as Box + Send> - }, - 404 => { - let body = response.into_body(); - Box::new( - future::ok( - GetPetByIdResponse::PetNotFound - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + // ToDo: this will move to swagger-rs and become a standard From conversion trait + // once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream + let body = serde_xml_rs::from_str::(body) + .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e)))?; + Ok(GetPetByIdResponse::SuccessfulOperation + (body) + ) } - })) + 400 => { + let body = response.into_body(); + Ok( + GetPetByIdResponse::InvalidIDSupplied + ) + } + 404 => { + let body = response.into_body(); + Ok( + GetPetByIdResponse::PetNotFound + ) + } + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn update_pet( + async fn update_pet( &self, param_body: models::Pet, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/pet", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("PUT") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let body = param_body.to_xml(); @@ -2280,22 +2281,22 @@ impl Api for Client where let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - if let Some(auth_data) = (context as &dyn Has>).get().as_ref() { + if let Some(auth_data) = Has::>::get(context).as_ref() { // Currently only authentication with Basic and Bearer are supported match auth_data { &AuthData::Bearer(ref bearer_header) => { let auth = swagger::auth::Header(bearer_header.clone()); let header = match HeaderValue::from_str(&format!("{}", auth)) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create Authorization header: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create Authorization header: {}", e))) }; request.headers_mut().insert( hyper::header::AUTHORIZATION, @@ -2305,64 +2306,56 @@ impl Api for Client where } } - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 400 => { - let body = response.into_body(); - Box::new( - future::ok( - UpdatePetResponse::InvalidIDSupplied - ) - ) as Box + Send> - }, - 404 => { - let body = response.into_body(); - Box::new( - future::ok( - UpdatePetResponse::PetNotFound - ) - ) as Box + Send> - }, - 405 => { - let body = response.into_body(); - Box::new( - future::ok( - UpdatePetResponse::ValidationException - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 400 => { + let body = response.into_body(); + Ok( + UpdatePetResponse::InvalidIDSupplied + ) } - })) + 404 => { + let body = response.into_body(); + Ok( + UpdatePetResponse::PetNotFound + ) + } + 405 => { + let body = response.into_body(); + Ok( + UpdatePetResponse::ValidationException + ) + } + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn update_pet_with_form( + async fn update_pet_with_form( &self, param_pet_id: i64, param_name: Option, param_status: Option, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/pet/{pet_id}", self.base_path @@ -2370,24 +2363,26 @@ impl Api for Client where ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let params = &[ @@ -2399,23 +2394,23 @@ impl Api for Client where let header = "application/x-www-form-urlencoded"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); *request.body_mut() = Body::from(body.into_bytes()); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - if let Some(auth_data) = (context as &dyn Has>).get().as_ref() { + if let Some(auth_data) = Has::>::get(context).as_ref() { // Currently only authentication with Basic and Bearer are supported match auth_data { &AuthData::Bearer(ref bearer_header) => { let auth = swagger::auth::Header(bearer_header.clone()); let header = match HeaderValue::from_str(&format!("{}", auth)) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create Authorization header: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create Authorization header: {}", e))) }; request.headers_mut().insert( hyper::header::AUTHORIZATION, @@ -2425,48 +2420,44 @@ impl Api for Client where } } - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 405 => { - let body = response.into_body(); - Box::new( - future::ok( - UpdatePetWithFormResponse::InvalidInput - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 405 => { + let body = response.into_body(); + Ok( + UpdatePetWithFormResponse::InvalidInput + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn upload_file( + async fn upload_file( &self, param_pet_id: i64, param_additional_metadata: Option, param_file: Option, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/pet/{pet_id}/uploadImage", self.base_path @@ -2474,89 +2465,96 @@ impl Api for Client where ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let mut multipart = Multipart::new(); + let (body_string, multipart_header) = { + let mut multipart = Multipart::new(); - // For each parameter, encode as appropriate and add to the multipart body as a stream. + // For each parameter, encode as appropriate and add to the multipart body as a stream. - let additional_metadata_str = match serde_json::to_string(¶m_additional_metadata) { - Ok(str) => str, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to parse additional_metadata to string: {}", e)))), + let additional_metadata_str = match serde_json::to_string(¶m_additional_metadata) { + Ok(str) => str, + Err(e) => return Err(ApiError(format!("Unable to parse additional_metadata to string: {}", e))), + }; + + let additional_metadata_vec = additional_metadata_str.as_bytes().to_vec(); + let additional_metadata_mime = mime_0_2::Mime::from_str("application/json").expect("impossible to fail to parse"); + let additional_metadata_cursor = Cursor::new(additional_metadata_vec); + + multipart.add_stream("additional_metadata", additional_metadata_cursor, None as Option<&str>, Some(additional_metadata_mime)); + + + let file_str = match serde_json::to_string(¶m_file) { + Ok(str) => str, + Err(e) => return Err(ApiError(format!("Unable to parse file to string: {}", e))), + }; + + let file_vec = file_str.as_bytes().to_vec(); + let file_mime = mime_0_2::Mime::from_str("application/json").expect("impossible to fail to parse"); + let file_cursor = Cursor::new(file_vec); + + multipart.add_stream("file", file_cursor, None as Option<&str>, Some(file_mime)); + + + let mut fields = match multipart.prepare() { + Ok(fields) => fields, + Err(err) => return Err(ApiError(format!("Unable to build request: {}", err))), + }; + + let mut body_string = String::new(); + + match fields.read_to_string(&mut body_string) { + Ok(_) => (), + Err(err) => return Err(ApiError(format!("Unable to build body: {}", err))), + } + + let boundary = fields.boundary(); + + let multipart_header = format!("multipart/form-data;boundary={}", boundary); + + (body_string, multipart_header) }; - let additional_metadata_vec = additional_metadata_str.as_bytes().to_vec(); - - let additional_metadata_mime = mime_0_2::Mime::from_str("application/json").expect("impossible to fail to parse"); - - let additional_metadata_cursor = Cursor::new(additional_metadata_vec); - - multipart.add_stream("additional_metadata", additional_metadata_cursor, None as Option<&str>, Some(additional_metadata_mime)); - - let file_str = match serde_json::to_string(¶m_file) { - Ok(str) => str, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to parse file to string: {}", e)))), - }; - - let file_vec = file_str.as_bytes().to_vec(); - - let file_mime = mime_0_2::Mime::from_str("application/json").expect("impossible to fail to parse"); - - let file_cursor = Cursor::new(file_vec); - - multipart.add_stream("file", file_cursor, None as Option<&str>, Some(file_mime)); - let mut fields = match multipart.prepare() { - Ok(fields) => fields, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build request: {}", err)))), - }; - - let mut body_string = String::new(); - match fields.read_to_string(&mut body_string) { - Ok(_) => (), - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build body: {}", err)))), - } - let boundary = fields.boundary(); - - let multipart_header = format!("multipart/form-data;boundary={}", boundary); - *request.body_mut() = Body::from(body_string); request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(&multipart_header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", multipart_header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", multipart_header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - if let Some(auth_data) = (context as &dyn Has>).get().as_ref() { + if let Some(auth_data) = Has::>::get(context).as_ref() { // Currently only authentication with Basic and Bearer are supported match auth_data { &AuthData::Bearer(ref bearer_header) => { let auth = swagger::auth::Header(bearer_header.clone()); let header = match HeaderValue::from_str(&format!("{}", auth)) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create Authorization header: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create Authorization header: {}", e))) }; request.headers_mut().insert( hyper::header::AUTHORIZATION, @@ -2566,58 +2564,48 @@ impl Api for Client where } } - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - serde_json::from_str::(body) - .map_err(|e| e.into()) - ) - ) - .map(move |body| { - UploadFileResponse::SuccessfulOperation - (body) - }) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(body)?; + Ok(UploadFileResponse::SuccessfulOperation + (body) + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn delete_order( + async fn delete_order( &self, param_order_id: String, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/store/order/{order_id}", self.base_path @@ -2625,170 +2613,158 @@ impl Api for Client where ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("DELETE") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 400 => { - let body = response.into_body(); - Box::new( - future::ok( - DeleteOrderResponse::InvalidIDSupplied - ) - ) as Box + Send> - }, - 404 => { - let body = response.into_body(); - Box::new( - future::ok( - DeleteOrderResponse::OrderNotFound - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 400 => { + let body = response.into_body(); + Ok( + DeleteOrderResponse::InvalidIDSupplied + ) } - })) + 404 => { + let body = response.into_body(); + Ok( + DeleteOrderResponse::OrderNotFound + ) + } + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn get_inventory( + async fn get_inventory( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/store/inventory", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - if let Some(auth_data) = (context as &dyn Has>).get().as_ref() { + if let Some(auth_data) = Has::>::get(context).as_ref() { // Currently only authentication with Basic and Bearer are supported match auth_data { _ => {} } } - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - serde_json::from_str::>(body) - .map_err(|e| e.into()) - ) - ) - .map(move |body| { - GetInventoryResponse::SuccessfulOperation - (body) - }) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::>(body)?; + Ok(GetInventoryResponse::SuccessfulOperation + (body) + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn get_order_by_id( + async fn get_order_by_id( &self, param_order_id: i64, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/store/order/{order_id}", self.base_path @@ -2796,126 +2772,117 @@ impl Api for Client where ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - // ToDo: this will move to swagger-rs and become a standard From conversion trait - // once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream - serde_xml_rs::from_str::(body) - .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e))) - ) - ) - .map(move |body| { - GetOrderByIdResponse::SuccessfulOperation - (body) - }) - ) as Box + Send> - }, - 400 => { - let body = response.into_body(); - Box::new( - future::ok( - GetOrderByIdResponse::InvalidIDSupplied - ) - ) as Box + Send> - }, - 404 => { - let body = response.into_body(); - Box::new( - future::ok( - GetOrderByIdResponse::OrderNotFound - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + // ToDo: this will move to swagger-rs and become a standard From conversion trait + // once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream + let body = serde_xml_rs::from_str::(body) + .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e)))?; + Ok(GetOrderByIdResponse::SuccessfulOperation + (body) + ) } - })) + 400 => { + let body = response.into_body(); + Ok( + GetOrderByIdResponse::InvalidIDSupplied + ) + } + 404 => { + let body = response.into_body(); + Ok( + GetOrderByIdResponse::OrderNotFound + ) + } + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn place_order( + async fn place_order( &self, param_body: models::Order, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/store/order", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); @@ -2925,101 +2892,92 @@ impl Api for Client where let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - // ToDo: this will move to swagger-rs and become a standard From conversion trait - // once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream - serde_xml_rs::from_str::(body) - .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e))) - ) - ) - .map(move |body| { - PlaceOrderResponse::SuccessfulOperation - (body) - }) - ) as Box + Send> - }, - 400 => { - let body = response.into_body(); - Box::new( - future::ok( - PlaceOrderResponse::InvalidOrder - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + // ToDo: this will move to swagger-rs and become a standard From conversion trait + // once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream + let body = serde_xml_rs::from_str::(body) + .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e)))?; + Ok(PlaceOrderResponse::SuccessfulOperation + (body) + ) } - })) + 400 => { + let body = response.into_body(); + Ok( + PlaceOrderResponse::InvalidOrder + ) + } + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn create_user( + async fn create_user( &self, param_body: models::User, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/user", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; // Body parameter @@ -3029,78 +2987,76 @@ impl Api for Client where let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 0 => { - let body = response.into_body(); - Box::new( - future::ok( - CreateUserResponse::SuccessfulOperation - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 0 => { + let body = response.into_body(); + Ok( + CreateUserResponse::SuccessfulOperation + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn create_users_with_array_input( + async fn create_users_with_array_input( &self, param_body: &Vec, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/user/createWithArray", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); @@ -3109,78 +3065,76 @@ impl Api for Client where let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 0 => { - let body = response.into_body(); - Box::new( - future::ok( - CreateUsersWithArrayInputResponse::SuccessfulOperation - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 0 => { + let body = response.into_body(); + Ok( + CreateUsersWithArrayInputResponse::SuccessfulOperation + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn create_users_with_list_input( + async fn create_users_with_list_input( &self, param_body: &Vec, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/user/createWithList", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); @@ -3189,54 +3143,50 @@ impl Api for Client where let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 0 => { - let body = response.into_body(); - Box::new( - future::ok( - CreateUsersWithListInputResponse::SuccessfulOperation - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 0 => { + let body = response.into_body(); + Ok( + CreateUsersWithListInputResponse::SuccessfulOperation + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn delete_user( + async fn delete_user( &self, param_username: String, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/user/{username}", self.base_path @@ -3244,80 +3194,76 @@ impl Api for Client where ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("DELETE") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 400 => { - let body = response.into_body(); - Box::new( - future::ok( - DeleteUserResponse::InvalidUsernameSupplied - ) - ) as Box + Send> - }, - 404 => { - let body = response.into_body(); - Box::new( - future::ok( - DeleteUserResponse::UserNotFound - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 400 => { + let body = response.into_body(); + Ok( + DeleteUserResponse::InvalidUsernameSupplied + ) } - })) + 404 => { + let body = response.into_body(); + Ok( + DeleteUserResponse::UserNotFound + ) + } + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn get_user_by_name( + async fn get_user_by_name( &self, param_username: String, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/user/{username}", self.base_path @@ -3325,299 +3271,281 @@ impl Api for Client where ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - // ToDo: this will move to swagger-rs and become a standard From conversion trait - // once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream - serde_xml_rs::from_str::(body) - .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e))) - ) - ) - .map(move |body| { - GetUserByNameResponse::SuccessfulOperation - (body) - }) - ) as Box + Send> - }, - 400 => { - let body = response.into_body(); - Box::new( - future::ok( - GetUserByNameResponse::InvalidUsernameSupplied - ) - ) as Box + Send> - }, - 404 => { - let body = response.into_body(); - Box::new( - future::ok( - GetUserByNameResponse::UserNotFound - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + // ToDo: this will move to swagger-rs and become a standard From conversion trait + // once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream + let body = serde_xml_rs::from_str::(body) + .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e)))?; + Ok(GetUserByNameResponse::SuccessfulOperation + (body) + ) } - })) + 400 => { + let body = response.into_body(); + Ok( + GetUserByNameResponse::InvalidUsernameSupplied + ) + } + 404 => { + let body = response.into_body(); + Ok( + GetUserByNameResponse::UserNotFound + ) + } + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn login_user( + async fn login_user( &self, param_username: String, param_password: String, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/user/login", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - query_string.append_pair("username", ¶m_username.to_string()); - query_string.append_pair("password", ¶m_password.to_string()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.append_pair("username", ¶m_username.to_string()); + query_string.append_pair("password", ¶m_password.to_string()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let response_x_rate_limit = match response.headers().get(HeaderName::from_static("x-rate-limit")) { - Some(response_x_rate_limit) => response_x_rate_limit.clone(), - None => return Box::new(future::err(ApiError(String::from("Required response header X-Rate-Limit for response 200 was not found.")))) as Box + Send>, - }; - let response_x_rate_limit = match TryInto::>::try_into(response_x_rate_limit) { - Ok(value) => value, - Err(e) => { - return Box::new(future::err(ApiError(format!("Invalid response header X-Rate-Limit for response 200 - {}", e)))) as Box + Send>; - }, - }; - let response_x_rate_limit = response_x_rate_limit.0; + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; - let response_x_expires_after = match response.headers().get(HeaderName::from_static("x-expires-after")) { - Some(response_x_expires_after) => response_x_expires_after.clone(), - None => return Box::new(future::err(ApiError(String::from("Required response header X-Expires-After for response 200 was not found.")))) as Box + Send>, - }; - let response_x_expires_after = match TryInto::>>::try_into(response_x_expires_after) { - Ok(value) => value, - Err(e) => { - return Box::new(future::err(ApiError(format!("Invalid response header X-Expires-After for response 200 - {}", e)))) as Box + Send>; - }, - }; - let response_x_expires_after = response_x_expires_after.0; + match response.status().as_u16() { + 200 => { + let response_x_rate_limit = match response.headers().get(HeaderName::from_static("x-rate-limit")) { + Some(response_x_rate_limit) => response_x_rate_limit.clone(), + None => { + return Err(ApiError(String::from("Required response header X-Rate-Limit for response 200 was not found."))); + } + }; + let response_x_rate_limit = match TryInto::>::try_into(response_x_rate_limit) { + Ok(value) => value, + Err(e) => { + return Err(ApiError(format!("Invalid response header X-Rate-Limit for response 200 - {}", e))); + }, + }; + let response_x_rate_limit = response_x_rate_limit.0; - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - // ToDo: this will move to swagger-rs and become a standard From conversion trait - // once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream - serde_xml_rs::from_str::(body) - .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e))) - ) - ) - .map(move |body| { - LoginUserResponse::SuccessfulOperation - { - body: body, - x_rate_limit: response_x_rate_limit, - x_expires_after: response_x_expires_after, - } - }) - ) as Box + Send> - }, - 400 => { - let body = response.into_body(); - Box::new( - future::ok( - LoginUserResponse::InvalidUsername - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let response_x_expires_after = match response.headers().get(HeaderName::from_static("x-expires-after")) { + Some(response_x_expires_after) => response_x_expires_after.clone(), + None => { + return Err(ApiError(String::from("Required response header X-Expires-After for response 200 was not found."))); + } + }; + let response_x_expires_after = match TryInto::>>::try_into(response_x_expires_after) { + Ok(value) => value, + Err(e) => { + return Err(ApiError(format!("Invalid response header X-Expires-After for response 200 - {}", e))); + }, + }; + let response_x_expires_after = response_x_expires_after.0; + + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + // ToDo: this will move to swagger-rs and become a standard From conversion trait + // once https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream + let body = serde_xml_rs::from_str::(body) + .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e)))?; + Ok(LoginUserResponse::SuccessfulOperation + { + body: body, + x_rate_limit: response_x_rate_limit, + x_expires_after: response_x_expires_after, + } + ) } - })) + 400 => { + let body = response.into_body(); + Ok( + LoginUserResponse::InvalidUsername + ) + } + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn logout_user( + async fn logout_user( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/user/logout", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 0 => { - let body = response.into_body(); - Box::new( - future::ok( - LogoutUserResponse::SuccessfulOperation - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 0 => { + let body = response.into_body(); + Ok( + LogoutUserResponse::SuccessfulOperation + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn update_user( + async fn update_user( &self, param_username: String, param_body: models::User, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/v2/user/{username}", self.base_path @@ -3625,24 +3553,26 @@ impl Api for Client where ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("PUT") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); @@ -3652,56 +3582,49 @@ impl Api for Client where let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 400 => { - let body = response.into_body(); - Box::new( - future::ok( - UpdateUserResponse::InvalidUserSupplied - ) - ) as Box + Send> - }, - 404 => { - let body = response.into_body(); - Box::new( - future::ok( - UpdateUserResponse::UserNotFound - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 400 => { + let body = response.into_body(); + Ok( + UpdateUserResponse::InvalidUserSupplied + ) } - })) + 404 => { + let body = response.into_body(); + Ok( + UpdateUserResponse::UserNotFound + ) + } + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } } diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/context.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/context.rs index 0ea1fbb6ac8..d9b71134176 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/context.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/context.rs @@ -1,13 +1,12 @@ -use futures::Future; -use hyper; +use futures::future::BoxFuture; use hyper::header::HeaderName; -use hyper::{Error, Request, Response, StatusCode, service::Service, body::Payload}; +use hyper::{Error, Request, Response, StatusCode, service::Service}; use url::form_urlencoded; use std::default::Default; use std::io; use std::marker::PhantomData; +use std::task::{Poll, Context}; use swagger::auth::{AuthData, Authorization, Bearer, Scopes}; -use swagger::context::ContextualPayload; use swagger::{EmptyContext, Has, Pop, Push, XSpanIdString}; use crate::Api; @@ -31,58 +30,52 @@ where } // Make a service that adds context. -impl<'a, T, SC, A, B, C, D, E, ME, S, OB, F> hyper::service::MakeService<&'a SC> for +impl Service for MakeAddContext where - A: Default + Push, + Target: Send, + A: Default + Push + Send, B: Push, Result = C>, C: Push, Result = D>, D: Send + 'static, - T: hyper::service::MakeService< - &'a SC, - Error = E, - MakeError = ME, - Service = S, - ReqBody = ContextualPayload, - ResBody = OB, - Future = F - >, - S: Service< - Error = E, - ReqBody = ContextualPayload, - ResBody = OB> + 'static, - ME: swagger::ErrorBound, - E: swagger::ErrorBound, - F: Future + Send + 'static, - S::Future: Send, - OB: Payload, + T: Service + Send, + T::Future: Send + 'static { - type ReqBody = hyper::Body; - type ResBody = OB; - type Error = E; - type MakeError = ME; - type Service = AddContext; - type Future = Box + Send + 'static>; + type Error = T::Error; + type Response = AddContext; + type Future = BoxFuture<'static, Result>; - fn make_service(&mut self, ctx: &'a SC) -> Self::Future { - Box::new(self.inner.make_service(ctx).map(|s| AddContext::new(s))) + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + self.inner.poll_ready(cx) + } + + fn call(&mut self, target: Target) -> Self::Future { + let service = self.inner.call(target); + + Box::pin(async move { + Ok(AddContext::new(service.await?)) + }) } } -/// Middleware to extract authentication data from request -pub struct AddContext { +/// Middleware to add context data from the request +pub struct AddContext +where + A: Default + Push, + B: Push, Result = C>, + C: Push, Result = D> +{ inner: T, marker: PhantomData, } -impl AddContext +impl AddContext where A: Default + Push, B: Push, Result = C>, C: Push, Result = D>, - T: Service, { - pub fn new(inner: T) -> AddContext { + pub fn new(inner: T) -> Self { AddContext { inner, marker: PhantomData, @@ -90,24 +83,26 @@ where } } -impl Service for AddContext +impl Service> for AddContext where A: Default + Push, B: Push, Result=C>, C: Push, Result=D>, D: Send + 'static, - T: Service>, - T::Future: Future, Error=T::Error> + Send + 'static + T: Service<(Request, D)> { - type ReqBody = hyper::Body; - type ResBody = T::ResBody; type Error = T::Error; - type Future = Box, Error=T::Error> + Send + 'static>; + type Future = T::Future; + type Response = T::Response; - fn call(&mut self, req: Request) -> Self::Future { - let context = A::default().push(XSpanIdString::get_or_generate(&req)); - let (head, body) = req.into_parts(); - let headers = head.headers.clone(); + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + self.inner.poll_ready(cx) + } + + + fn call(&mut self, request: Request) -> Self::Future { + let context = A::default().push(XSpanIdString::get_or_generate(&request)); + let headers = request.headers(); { use swagger::auth::api_key_from_header; @@ -117,16 +112,11 @@ impl Service for AddContext let context = context.push(Some(auth_data)); let context = context.push(None::); - let body = ContextualPayload { - inner: body, - context: context, - }; - - return Box::new(self.inner.call(hyper::Request::from_parts(head, body))); + return self.inner.call((request, context)) } } { - let key = form_urlencoded::parse(head.uri.query().unwrap_or_default().as_bytes()) + let key = form_urlencoded::parse(request.uri().query().unwrap_or_default().as_bytes()) .filter(|e| e.0 == "api_key_query") .map(|e| e.1.clone().into_owned()) .nth(0); @@ -135,11 +125,7 @@ impl Service for AddContext let context = context.push(Some(auth_data)); let context = context.push(None::); - let body = ContextualPayload { - inner: body, - context: context, - }; - return Box::new(self.inner.call(hyper::Request::from_parts(head, body))); + return self.inner.call((request, context)) } } { @@ -150,12 +136,7 @@ impl Service for AddContext let context = context.push(Some(auth_data)); let context = context.push(None::); - let body = ContextualPayload { - inner: body, - context: context, - }; - - return Box::new(self.inner.call(hyper::Request::from_parts(head, body))); + return self.inner.call((request, context)) } } { @@ -166,22 +147,13 @@ impl Service for AddContext let context = context.push(Some(auth_data)); let context = context.push(None::); - let body = ContextualPayload { - inner: body, - context: context, - }; - - return Box::new(self.inner.call(hyper::Request::from_parts(head, body))); + return self.inner.call((request, context)) } } let context = context.push(None::); let context = context.push(None::); - let body = ContextualPayload { - inner: body, - context: context, - }; - Box::new(self.inner.call(hyper::Request::from_parts(head, body))) + self.inner.call((request, context)) } } diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/lib.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/lib.rs index 3fecf3101cb..03eae5fb765 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/lib.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/lib.rs @@ -1,12 +1,12 @@ #![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)] +use async_trait::async_trait; use futures::Stream; -use std::io::Error; +use std::error::Error; +use std::task::{Poll, Context}; +use swagger::{ApiError, ContextWrapper}; -#[deprecated(note = "Import swagger-rs directly")] -pub use swagger::{ApiError, ContextWrapper}; -#[deprecated(note = "Import futures directly")] -pub use futures::Future; +type ServiceError = Box; pub const BASE_PATH: &'static str = "/v2"; pub const API_VERSION: &'static str = "1.0.0"; @@ -306,60 +306,65 @@ pub enum UpdateUserResponse { } /// API -pub trait Api { +#[async_trait] +pub trait Api { + fn poll_ready(&self, _cx: &mut Context) -> Poll>> { + Poll::Ready(Ok(())) + } + /// To test special tags - fn test_special_tags( + async fn test_special_tags( &self, body: models::Client, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn call123example( + async fn call123example( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn fake_outer_boolean_serialize( + async fn fake_outer_boolean_serialize( &self, body: Option, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn fake_outer_composite_serialize( + async fn fake_outer_composite_serialize( &self, body: Option, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn fake_outer_number_serialize( + async fn fake_outer_number_serialize( &self, body: Option, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn fake_outer_string_serialize( + async fn fake_outer_string_serialize( &self, body: Option, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn fake_response_with_numerical_description( + async fn fake_response_with_numerical_description( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn hyphen_param( + async fn hyphen_param( &self, hyphen_param: String, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn test_body_with_query_params( + async fn test_body_with_query_params( &self, query: String, body: models::User, - context: &C) -> Box + Send>; + context: &C) -> Result; /// To test \"client\" model - fn test_client_model( + async fn test_client_model( &self, body: models::Client, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트 - fn test_endpoint_parameters( + async fn test_endpoint_parameters( &self, number: f64, double: f64, @@ -375,10 +380,10 @@ pub trait Api { date_time: Option>, password: Option, callback: Option, - context: &C) -> Box + Send>; + context: &C) -> Result; /// To test enum parameters - fn test_enum_parameters( + async fn test_enum_parameters( &self, enum_header_string_array: Option<&Vec>, enum_header_string: Option, @@ -387,209 +392,215 @@ pub trait Api { enum_query_integer: Option, enum_query_double: Option, enum_form_string: Option, - context: &C) -> Box + Send>; + context: &C) -> Result; /// test inline additionalProperties - fn test_inline_additional_properties( + async fn test_inline_additional_properties( &self, param: std::collections::HashMap, - context: &C) -> Box + Send>; + context: &C) -> Result; /// test json serialization of form data - fn test_json_form_data( + async fn test_json_form_data( &self, param: String, param2: String, - context: &C) -> Box + Send>; + context: &C) -> Result; /// To test class name in snake case - fn test_classname( + async fn test_classname( &self, body: models::Client, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Add a new pet to the store - fn add_pet( + async fn add_pet( &self, body: models::Pet, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Deletes a pet - fn delete_pet( + async fn delete_pet( &self, pet_id: i64, api_key: Option, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Finds Pets by status - fn find_pets_by_status( + async fn find_pets_by_status( &self, status: &Vec, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Finds Pets by tags - fn find_pets_by_tags( + async fn find_pets_by_tags( &self, tags: &Vec, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Find pet by ID - fn get_pet_by_id( + async fn get_pet_by_id( &self, pet_id: i64, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Update an existing pet - fn update_pet( + async fn update_pet( &self, body: models::Pet, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Updates a pet in the store with form data - fn update_pet_with_form( + async fn update_pet_with_form( &self, pet_id: i64, name: Option, status: Option, - context: &C) -> Box + Send>; + context: &C) -> Result; /// uploads an image - fn upload_file( + async fn upload_file( &self, pet_id: i64, additional_metadata: Option, file: Option, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Delete purchase order by ID - fn delete_order( + async fn delete_order( &self, order_id: String, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Returns pet inventories by status - fn get_inventory( + async fn get_inventory( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Find purchase order by ID - fn get_order_by_id( + async fn get_order_by_id( &self, order_id: i64, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Place an order for a pet - fn place_order( + async fn place_order( &self, body: models::Order, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Create user - fn create_user( + async fn create_user( &self, body: models::User, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Creates list of users with given input array - fn create_users_with_array_input( + async fn create_users_with_array_input( &self, body: &Vec, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Creates list of users with given input array - fn create_users_with_list_input( + async fn create_users_with_list_input( &self, body: &Vec, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Delete user - fn delete_user( + async fn delete_user( &self, username: String, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Get user by user name - fn get_user_by_name( + async fn get_user_by_name( &self, username: String, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Logs user into the system - fn login_user( + async fn login_user( &self, username: String, password: String, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Logs out current logged in user session - fn logout_user( + async fn logout_user( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Updated user - fn update_user( + async fn update_user( &self, username: String, body: models::User, - context: &C) -> Box + Send>; + context: &C) -> Result; } -/// API without a `Context` -pub trait ApiNoContext { +/// API where `Context` isn't passed on every API call +#[async_trait] +pub trait ApiNoContext { + + fn poll_ready(&self, _cx: &mut Context) -> Poll>>; + + fn context(&self) -> &C; + /// To test special tags - fn test_special_tags( + async fn test_special_tags( &self, body: models::Client, - ) -> Box + Send>; + ) -> Result; - fn call123example( + async fn call123example( &self, - ) -> Box + Send>; + ) -> Result; - fn fake_outer_boolean_serialize( + async fn fake_outer_boolean_serialize( &self, body: Option, - ) -> Box + Send>; + ) -> Result; - fn fake_outer_composite_serialize( + async fn fake_outer_composite_serialize( &self, body: Option, - ) -> Box + Send>; + ) -> Result; - fn fake_outer_number_serialize( + async fn fake_outer_number_serialize( &self, body: Option, - ) -> Box + Send>; + ) -> Result; - fn fake_outer_string_serialize( + async fn fake_outer_string_serialize( &self, body: Option, - ) -> Box + Send>; + ) -> Result; - fn fake_response_with_numerical_description( + async fn fake_response_with_numerical_description( &self, - ) -> Box + Send>; + ) -> Result; - fn hyphen_param( + async fn hyphen_param( &self, hyphen_param: String, - ) -> Box + Send>; + ) -> Result; - fn test_body_with_query_params( + async fn test_body_with_query_params( &self, query: String, body: models::User, - ) -> Box + Send>; + ) -> Result; /// To test \"client\" model - fn test_client_model( + async fn test_client_model( &self, body: models::Client, - ) -> Box + Send>; + ) -> Result; /// Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트 - fn test_endpoint_parameters( + async fn test_endpoint_parameters( &self, number: f64, double: f64, @@ -605,10 +616,10 @@ pub trait ApiNoContext { date_time: Option>, password: Option, callback: Option, - ) -> Box + Send>; + ) -> Result; /// To test enum parameters - fn test_enum_parameters( + async fn test_enum_parameters( &self, enum_header_string_array: Option<&Vec>, enum_header_string: Option, @@ -617,250 +628,270 @@ pub trait ApiNoContext { enum_query_integer: Option, enum_query_double: Option, enum_form_string: Option, - ) -> Box + Send>; + ) -> Result; /// test inline additionalProperties - fn test_inline_additional_properties( + async fn test_inline_additional_properties( &self, param: std::collections::HashMap, - ) -> Box + Send>; + ) -> Result; /// test json serialization of form data - fn test_json_form_data( + async fn test_json_form_data( &self, param: String, param2: String, - ) -> Box + Send>; + ) -> Result; /// To test class name in snake case - fn test_classname( + async fn test_classname( &self, body: models::Client, - ) -> Box + Send>; + ) -> Result; /// Add a new pet to the store - fn add_pet( + async fn add_pet( &self, body: models::Pet, - ) -> Box + Send>; + ) -> Result; /// Deletes a pet - fn delete_pet( + async fn delete_pet( &self, pet_id: i64, api_key: Option, - ) -> Box + Send>; + ) -> Result; /// Finds Pets by status - fn find_pets_by_status( + async fn find_pets_by_status( &self, status: &Vec, - ) -> Box + Send>; + ) -> Result; /// Finds Pets by tags - fn find_pets_by_tags( + async fn find_pets_by_tags( &self, tags: &Vec, - ) -> Box + Send>; + ) -> Result; /// Find pet by ID - fn get_pet_by_id( + async fn get_pet_by_id( &self, pet_id: i64, - ) -> Box + Send>; + ) -> Result; /// Update an existing pet - fn update_pet( + async fn update_pet( &self, body: models::Pet, - ) -> Box + Send>; + ) -> Result; /// Updates a pet in the store with form data - fn update_pet_with_form( + async fn update_pet_with_form( &self, pet_id: i64, name: Option, status: Option, - ) -> Box + Send>; + ) -> Result; /// uploads an image - fn upload_file( + async fn upload_file( &self, pet_id: i64, additional_metadata: Option, file: Option, - ) -> Box + Send>; + ) -> Result; /// Delete purchase order by ID - fn delete_order( + async fn delete_order( &self, order_id: String, - ) -> Box + Send>; + ) -> Result; /// Returns pet inventories by status - fn get_inventory( + async fn get_inventory( &self, - ) -> Box + Send>; + ) -> Result; /// Find purchase order by ID - fn get_order_by_id( + async fn get_order_by_id( &self, order_id: i64, - ) -> Box + Send>; + ) -> Result; /// Place an order for a pet - fn place_order( + async fn place_order( &self, body: models::Order, - ) -> Box + Send>; + ) -> Result; /// Create user - fn create_user( + async fn create_user( &self, body: models::User, - ) -> Box + Send>; + ) -> Result; /// Creates list of users with given input array - fn create_users_with_array_input( + async fn create_users_with_array_input( &self, body: &Vec, - ) -> Box + Send>; + ) -> Result; /// Creates list of users with given input array - fn create_users_with_list_input( + async fn create_users_with_list_input( &self, body: &Vec, - ) -> Box + Send>; + ) -> Result; /// Delete user - fn delete_user( + async fn delete_user( &self, username: String, - ) -> Box + Send>; + ) -> Result; /// Get user by user name - fn get_user_by_name( + async fn get_user_by_name( &self, username: String, - ) -> Box + Send>; + ) -> Result; /// Logs user into the system - fn login_user( + async fn login_user( &self, username: String, password: String, - ) -> Box + Send>; + ) -> Result; /// Logs out current logged in user session - fn logout_user( + async fn logout_user( &self, - ) -> Box + Send>; + ) -> Result; /// Updated user - fn update_user( + async fn update_user( &self, username: String, body: models::User, - ) -> Box + Send>; + ) -> Result; } /// Trait to extend an API to make it easy to bind it to a context. -pub trait ContextWrapperExt<'a, C> where Self: Sized { +pub trait ContextWrapperExt where Self: Sized +{ /// Binds this API to a context. - fn with_context(self: &'a Self, context: C) -> ContextWrapper<'a, Self, C>; + fn with_context(self: Self, context: C) -> ContextWrapper; } -impl<'a, T: Api + Sized, C> ContextWrapperExt<'a, C> for T { - fn with_context(self: &'a T, context: C) -> ContextWrapper<'a, T, C> { +impl + Send + Sync, C: Clone + Send + Sync> ContextWrapperExt for T { + fn with_context(self: T, context: C) -> ContextWrapper { ContextWrapper::::new(self, context) } } -impl<'a, T: Api, C> ApiNoContext for ContextWrapper<'a, T, C> { +#[async_trait] +impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for ContextWrapper { + fn poll_ready(&self, cx: &mut Context) -> Poll> { + self.api().poll_ready(cx) + } + + fn context(&self) -> &C { + ContextWrapper::context(self) + } + /// To test special tags - fn test_special_tags( + async fn test_special_tags( &self, body: models::Client, - ) -> Box + Send> + ) -> Result { - self.api().test_special_tags(body, &self.context()) + let context = self.context().clone(); + self.api().test_special_tags(body, &context).await } - fn call123example( + async fn call123example( &self, - ) -> Box + Send> + ) -> Result { - self.api().call123example(&self.context()) + let context = self.context().clone(); + self.api().call123example(&context).await } - fn fake_outer_boolean_serialize( + async fn fake_outer_boolean_serialize( &self, body: Option, - ) -> Box + Send> + ) -> Result { - self.api().fake_outer_boolean_serialize(body, &self.context()) + let context = self.context().clone(); + self.api().fake_outer_boolean_serialize(body, &context).await } - fn fake_outer_composite_serialize( + async fn fake_outer_composite_serialize( &self, body: Option, - ) -> Box + Send> + ) -> Result { - self.api().fake_outer_composite_serialize(body, &self.context()) + let context = self.context().clone(); + self.api().fake_outer_composite_serialize(body, &context).await } - fn fake_outer_number_serialize( + async fn fake_outer_number_serialize( &self, body: Option, - ) -> Box + Send> + ) -> Result { - self.api().fake_outer_number_serialize(body, &self.context()) + let context = self.context().clone(); + self.api().fake_outer_number_serialize(body, &context).await } - fn fake_outer_string_serialize( + async fn fake_outer_string_serialize( &self, body: Option, - ) -> Box + Send> + ) -> Result { - self.api().fake_outer_string_serialize(body, &self.context()) + let context = self.context().clone(); + self.api().fake_outer_string_serialize(body, &context).await } - fn fake_response_with_numerical_description( + async fn fake_response_with_numerical_description( &self, - ) -> Box + Send> + ) -> Result { - self.api().fake_response_with_numerical_description(&self.context()) + let context = self.context().clone(); + self.api().fake_response_with_numerical_description(&context).await } - fn hyphen_param( + async fn hyphen_param( &self, hyphen_param: String, - ) -> Box + Send> + ) -> Result { - self.api().hyphen_param(hyphen_param, &self.context()) + let context = self.context().clone(); + self.api().hyphen_param(hyphen_param, &context).await } - fn test_body_with_query_params( + async fn test_body_with_query_params( &self, query: String, body: models::User, - ) -> Box + Send> + ) -> Result { - self.api().test_body_with_query_params(query, body, &self.context()) + let context = self.context().clone(); + self.api().test_body_with_query_params(query, body, &context).await } /// To test \"client\" model - fn test_client_model( + async fn test_client_model( &self, body: models::Client, - ) -> Box + Send> + ) -> Result { - self.api().test_client_model(body, &self.context()) + let context = self.context().clone(); + self.api().test_client_model(body, &context).await } /// Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트 - fn test_endpoint_parameters( + async fn test_endpoint_parameters( &self, number: f64, double: f64, @@ -876,13 +907,14 @@ impl<'a, T: Api, C> ApiNoContext for ContextWrapper<'a, T, C> { date_time: Option>, password: Option, callback: Option, - ) -> Box + Send> + ) -> Result { - self.api().test_endpoint_parameters(number, double, pattern_without_delimiter, byte, integer, int32, int64, float, string, binary, date, date_time, password, callback, &self.context()) + let context = self.context().clone(); + self.api().test_endpoint_parameters(number, double, pattern_without_delimiter, byte, integer, int32, int64, float, string, binary, date, date_time, password, callback, &context).await } /// To test enum parameters - fn test_enum_parameters( + async fn test_enum_parameters( &self, enum_header_string_array: Option<&Vec>, enum_header_string: Option, @@ -891,226 +923,251 @@ impl<'a, T: Api, C> ApiNoContext for ContextWrapper<'a, T, C> { enum_query_integer: Option, enum_query_double: Option, enum_form_string: Option, - ) -> Box + Send> + ) -> Result { - 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()) + let context = self.context().clone(); + 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, &context).await } /// test inline additionalProperties - fn test_inline_additional_properties( + async fn test_inline_additional_properties( &self, param: std::collections::HashMap, - ) -> Box + Send> + ) -> Result { - self.api().test_inline_additional_properties(param, &self.context()) + let context = self.context().clone(); + self.api().test_inline_additional_properties(param, &context).await } /// test json serialization of form data - fn test_json_form_data( + async fn test_json_form_data( &self, param: String, param2: String, - ) -> Box + Send> + ) -> Result { - self.api().test_json_form_data(param, param2, &self.context()) + let context = self.context().clone(); + self.api().test_json_form_data(param, param2, &context).await } /// To test class name in snake case - fn test_classname( + async fn test_classname( &self, body: models::Client, - ) -> Box + Send> + ) -> Result { - self.api().test_classname(body, &self.context()) + let context = self.context().clone(); + self.api().test_classname(body, &context).await } /// Add a new pet to the store - fn add_pet( + async fn add_pet( &self, body: models::Pet, - ) -> Box + Send> + ) -> Result { - self.api().add_pet(body, &self.context()) + let context = self.context().clone(); + self.api().add_pet(body, &context).await } /// Deletes a pet - fn delete_pet( + async fn delete_pet( &self, pet_id: i64, api_key: Option, - ) -> Box + Send> + ) -> Result { - self.api().delete_pet(pet_id, api_key, &self.context()) + let context = self.context().clone(); + self.api().delete_pet(pet_id, api_key, &context).await } /// Finds Pets by status - fn find_pets_by_status( + async fn find_pets_by_status( &self, status: &Vec, - ) -> Box + Send> + ) -> Result { - self.api().find_pets_by_status(status, &self.context()) + let context = self.context().clone(); + self.api().find_pets_by_status(status, &context).await } /// Finds Pets by tags - fn find_pets_by_tags( + async fn find_pets_by_tags( &self, tags: &Vec, - ) -> Box + Send> + ) -> Result { - self.api().find_pets_by_tags(tags, &self.context()) + let context = self.context().clone(); + self.api().find_pets_by_tags(tags, &context).await } /// Find pet by ID - fn get_pet_by_id( + async fn get_pet_by_id( &self, pet_id: i64, - ) -> Box + Send> + ) -> Result { - self.api().get_pet_by_id(pet_id, &self.context()) + let context = self.context().clone(); + self.api().get_pet_by_id(pet_id, &context).await } /// Update an existing pet - fn update_pet( + async fn update_pet( &self, body: models::Pet, - ) -> Box + Send> + ) -> Result { - self.api().update_pet(body, &self.context()) + let context = self.context().clone(); + self.api().update_pet(body, &context).await } /// Updates a pet in the store with form data - fn update_pet_with_form( + async fn update_pet_with_form( &self, pet_id: i64, name: Option, status: Option, - ) -> Box + Send> + ) -> Result { - self.api().update_pet_with_form(pet_id, name, status, &self.context()) + let context = self.context().clone(); + self.api().update_pet_with_form(pet_id, name, status, &context).await } /// uploads an image - fn upload_file( + async fn upload_file( &self, pet_id: i64, additional_metadata: Option, file: Option, - ) -> Box + Send> + ) -> Result { - self.api().upload_file(pet_id, additional_metadata, file, &self.context()) + let context = self.context().clone(); + self.api().upload_file(pet_id, additional_metadata, file, &context).await } /// Delete purchase order by ID - fn delete_order( + async fn delete_order( &self, order_id: String, - ) -> Box + Send> + ) -> Result { - self.api().delete_order(order_id, &self.context()) + let context = self.context().clone(); + self.api().delete_order(order_id, &context).await } /// Returns pet inventories by status - fn get_inventory( + async fn get_inventory( &self, - ) -> Box + Send> + ) -> Result { - self.api().get_inventory(&self.context()) + let context = self.context().clone(); + self.api().get_inventory(&context).await } /// Find purchase order by ID - fn get_order_by_id( + async fn get_order_by_id( &self, order_id: i64, - ) -> Box + Send> + ) -> Result { - self.api().get_order_by_id(order_id, &self.context()) + let context = self.context().clone(); + self.api().get_order_by_id(order_id, &context).await } /// Place an order for a pet - fn place_order( + async fn place_order( &self, body: models::Order, - ) -> Box + Send> + ) -> Result { - self.api().place_order(body, &self.context()) + let context = self.context().clone(); + self.api().place_order(body, &context).await } /// Create user - fn create_user( + async fn create_user( &self, body: models::User, - ) -> Box + Send> + ) -> Result { - self.api().create_user(body, &self.context()) + let context = self.context().clone(); + self.api().create_user(body, &context).await } /// Creates list of users with given input array - fn create_users_with_array_input( + async fn create_users_with_array_input( &self, body: &Vec, - ) -> Box + Send> + ) -> Result { - self.api().create_users_with_array_input(body, &self.context()) + let context = self.context().clone(); + self.api().create_users_with_array_input(body, &context).await } /// Creates list of users with given input array - fn create_users_with_list_input( + async fn create_users_with_list_input( &self, body: &Vec, - ) -> Box + Send> + ) -> Result { - self.api().create_users_with_list_input(body, &self.context()) + let context = self.context().clone(); + self.api().create_users_with_list_input(body, &context).await } /// Delete user - fn delete_user( + async fn delete_user( &self, username: String, - ) -> Box + Send> + ) -> Result { - self.api().delete_user(username, &self.context()) + let context = self.context().clone(); + self.api().delete_user(username, &context).await } /// Get user by user name - fn get_user_by_name( + async fn get_user_by_name( &self, username: String, - ) -> Box + Send> + ) -> Result { - self.api().get_user_by_name(username, &self.context()) + let context = self.context().clone(); + self.api().get_user_by_name(username, &context).await } /// Logs user into the system - fn login_user( + async fn login_user( &self, username: String, password: String, - ) -> Box + Send> + ) -> Result { - self.api().login_user(username, password, &self.context()) + let context = self.context().clone(); + self.api().login_user(username, password, &context).await } /// Logs out current logged in user session - fn logout_user( + async fn logout_user( &self, - ) -> Box + Send> + ) -> Result { - self.api().logout_user(&self.context()) + let context = self.context().clone(); + self.api().logout_user(&context).await } /// Updated user - fn update_user( + async fn update_user( &self, username: String, body: models::User, - ) -> Box + Send> + ) -> Result { - self.api().update_user(username, body, &self.context()) + let context = self.context().clone(); + self.api().update_user(username, body, &context).await } } + #[cfg(feature = "client")] pub mod client; diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/server/mod.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/server/mod.rs index 723ac064003..1cbdc1fda25 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/server/mod.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/server/mod.rs @@ -1,24 +1,19 @@ -use std::marker::PhantomData; -use futures::{Future, future, Stream, stream}; -use hyper; -use hyper::{Request, Response, Error, StatusCode, Body, HeaderMap}; +use futures::{future, future::BoxFuture, Stream, stream, future::FutureExt, stream::TryStreamExt}; +use hyper::{Request, Response, StatusCode, Body, HeaderMap}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; use log::warn; -use serde_json; #[allow(unused_imports)] use std::convert::{TryFrom, TryInto}; -use std::io; -use url::form_urlencoded; -#[allow(unused_imports)] -use swagger; -use swagger::{ApiError, XSpanIdString, Has, RequestParser}; +use std::error::Error; +use std::future::Future; +use std::marker::PhantomData; +use std::task::{Context, Poll}; +use swagger::{ApiError, BodyExt, Has, RequestParser, XSpanIdString}; pub use swagger::auth::Authorization; use swagger::auth::Scopes; -use swagger::context::ContextualPayload; -use uuid; +use url::form_urlencoded; use multipart::server::Multipart; use multipart::server::save::SaveResult; -use serde_xml_rs; #[allow(unused_imports)] use crate::models; @@ -26,6 +21,8 @@ use crate::header; pub use crate::context; +type ServiceFuture = BoxFuture<'static, Result, crate::ServiceError>>; + use crate::{Api, TestSpecialTagsResponse, Call123exampleResponse, @@ -153,15 +150,17 @@ mod paths { } } -pub struct MakeService { +pub struct MakeService where + T: Api + Clone + Send + 'static, + C: Has + Has> + Send + Sync + 'static +{ api_impl: T, - marker: PhantomData, + marker: PhantomData, } -impl MakeService -where - T: Api + Clone + Send + 'static, - RC: Has + Has> + 'static +impl MakeService where + T: Api + Clone + Send + 'static, + C: Has + Has> + Send + Sync + 'static { pub fn new(api_impl: T) -> Self { MakeService { @@ -171,44 +170,45 @@ where } } -impl<'a, T, SC, RC> hyper::service::MakeService<&'a SC> for MakeService -where - T: Api + Clone + Send + 'static, - RC: Has + Has> + 'static + Send +impl hyper::service::Service for MakeService where + T: Api + Clone + Send + 'static, + C: Has + Has> + Send + Sync + 'static { - type ReqBody = ContextualPayload; - type ResBody = Body; - type Error = Error; - type Service = Service; - type Future = future::FutureResult; - type MakeError = Error; + type Response = Service; + type Error = crate::ServiceError; + type Future = future::Ready>; - fn make_service(&mut self, _ctx: &'a SC) -> Self::Future { - future::FutureResult::from(Ok(Service::new( + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn call(&mut self, target: Target) -> Self::Future { + futures::future::ok(Service::new( self.api_impl.clone(), - ))) + )) } } -type ServiceFuture = Box, Error = Error> + Send>; - -fn method_not_allowed() -> ServiceFuture { - Box::new(future::ok( +fn method_not_allowed() -> Result, crate::ServiceError> { + Ok( Response::builder().status(StatusCode::METHOD_NOT_ALLOWED) .body(Body::empty()) .expect("Unable to create Method Not Allowed response") - )) + ) } -pub struct Service { +pub struct Service where + T: Api + Clone + Send + 'static, + C: Has + Has> + Send + Sync + 'static +{ api_impl: T, - marker: PhantomData, + marker: PhantomData, } -impl Service -where - T: Api + Clone + Send + 'static, - RC: Has + Has> + 'static { +impl Service where + T: Api + Clone + Send + 'static, + C: Has + Has> + Send + Sync + 'static +{ pub fn new(api_impl: T) -> Self { Service { api_impl: api_impl, @@ -217,23 +217,38 @@ where } } -impl hyper::service::Service for Service -where +impl Clone for Service where T: Api + Clone + Send + 'static, - C: Has + Has> + 'static + Send + C: Has + Has> + Send + Sync + 'static { - type ReqBody = ContextualPayload; - type ResBody = Body; - type Error = Error; + fn clone(&self) -> Self { + Service { + api_impl: self.api_impl.clone(), + marker: self.marker.clone(), + } + } +} + +impl hyper::service::Service<(Request, C)> for Service where + T: Api + Clone + Send + Sync + 'static, + C: Has + Has> + Send + Sync + 'static +{ + type Response = Response; + type Error = crate::ServiceError; type Future = ServiceFuture; - fn call(&mut self, req: Request) -> Self::Future { - let api_impl = self.api_impl.clone(); - let (parts, body) = req.into_parts(); + fn poll_ready(&mut self, cx: &mut Context) -> Poll> { + self.api_impl.poll_ready(cx) + } + + fn call(&mut self, req: (Request, C)) -> Self::Future { async fn run(mut api_impl: T, req: (Request, C)) -> Result, crate::ServiceError> where + T: Api + Clone + Send + 'static, + C: Has + Has> + Send + Sync + 'static + { + let (request, context) = req; + let (parts, body) = request.into_parts(); let (method, uri, headers) = (parts.method, parts.uri, parts.headers); let path = paths::GLOBAL_REGEX_SET.matches(uri.path()); - let mut context = body.context; - let body = body.inner; match &method { @@ -242,9 +257,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_body: Option = if !body.is_empty() { @@ -254,29 +268,28 @@ where unused_elements.push(path.to_string()); }) { Ok(param_body) => param_body, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid body parameter body due to schema"))), + .expect("Unable to create Bad Request response for invalid body parameter body due to schema")), } } else { None }; let param_body = match param_body { Some(param_body) => param_body, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required body parameter body")) - .expect("Unable to create Bad Request response for missing body parameter body"))), + .expect("Unable to create Bad Request response for missing body parameter body")), }; - Box::new( - api_impl.test_special_tags( + let result = api_impl.test_special_tags( param_body, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -310,29 +323,22 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter body: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter body"))), + .expect("Unable to create Bad Request response due to unable to read body parameter body")), } - }) - ) as Self::Future }, // Call123example - GET /fake/operation-with-numeric-id &hyper::Method::GET if path.matched(paths::ID_FAKE_OPERATION_WITH_NUMERIC_ID) => { - Box::new({ - {{ - Box::new( - api_impl.call123example( + let result = api_impl.call123example( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -352,11 +358,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // FakeOuterBooleanSerialize - POST /fake/outer/boolean @@ -364,9 +366,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_body: Option = if !body.is_empty() { @@ -382,13 +383,12 @@ where None }; - Box::new( - api_impl.fake_outer_boolean_serialize( + let result = api_impl.fake_outer_boolean_serialize( param_body, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -422,17 +422,13 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter body: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter body"))), + .expect("Unable to create Bad Request response due to unable to read body parameter body")), } - }) - ) as Self::Future }, // FakeOuterCompositeSerialize - POST /fake/outer/composite @@ -440,9 +436,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_body: Option = if !body.is_empty() { @@ -458,13 +453,12 @@ where None }; - Box::new( - api_impl.fake_outer_composite_serialize( + let result = api_impl.fake_outer_composite_serialize( param_body, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -498,17 +492,13 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter body: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter body"))), + .expect("Unable to create Bad Request response due to unable to read body parameter body")), } - }) - ) as Self::Future }, // FakeOuterNumberSerialize - POST /fake/outer/number @@ -516,9 +506,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_body: Option = if !body.is_empty() { @@ -534,13 +523,12 @@ where None }; - Box::new( - api_impl.fake_outer_number_serialize( + let result = api_impl.fake_outer_number_serialize( param_body, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -574,17 +562,13 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter body: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter body"))), + .expect("Unable to create Bad Request response due to unable to read body parameter body")), } - }) - ) as Self::Future }, // FakeOuterStringSerialize - POST /fake/outer/string @@ -592,9 +576,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_body: Option = if !body.is_empty() { @@ -610,13 +593,12 @@ where None }; - Box::new( - api_impl.fake_outer_string_serialize( + let result = api_impl.fake_outer_string_serialize( param_body, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -650,29 +632,22 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter body: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter body"))), + .expect("Unable to create Bad Request response due to unable to read body parameter body")), } - }) - ) as Self::Future }, // FakeResponseWithNumericalDescription - GET /fake/response-with-numerical-description &hyper::Method::GET if path.matched(paths::ID_FAKE_RESPONSE_WITH_NUMERICAL_DESCRIPTION) => { - Box::new({ - {{ - Box::new( - api_impl.fake_response_with_numerical_description( + let result = api_impl.fake_response_with_numerical_description( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -692,11 +667,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // HyphenParam - GET /fake/hyphenParam/{hyphen-param} @@ -713,26 +684,23 @@ where let param_hyphen_param = match percent_encoding::percent_decode(path_params["hyphen-param"].as_bytes()).decode_utf8() { Ok(param_hyphen_param) => match param_hyphen_param.parse::() { Ok(param_hyphen_param) => param_hyphen_param, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse path parameter hyphen-param: {}", e))) - .expect("Unable to create Bad Request response for invalid path parameter"))), + .expect("Unable to create Bad Request response for invalid path parameter")), }, - Err(_) => return Box::new(future::ok(Response::builder() + Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["hyphen-param"]))) - .expect("Unable to create Bad Request response for invalid percent decode"))) + .expect("Unable to create Bad Request response for invalid percent decode")) }; - Box::new({ - {{ - Box::new( - api_impl.hyphen_param( + let result = api_impl.hyphen_param( param_hyphen_param, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -752,11 +720,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // TestBodyWithQueryParams - PUT /fake/body-with-query-params @@ -768,23 +732,22 @@ where let param_query = match param_query { Some(param_query) => match param_query.parse::() { Ok(param_query) => param_query, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse query parameter query - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid query parameter query"))), + .expect("Unable to create Bad Request response for invalid query parameter query")), }, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required query parameter query")) - .expect("Unable to create Bad Request response for missing qeury parameter query"))), + .expect("Unable to create Bad Request response for missing qeury parameter query")), }; // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_body: Option = if !body.is_empty() { @@ -794,30 +757,29 @@ where unused_elements.push(path.to_string()); }) { Ok(param_body) => param_body, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid body parameter body due to schema"))), + .expect("Unable to create Bad Request response for invalid body parameter body due to schema")), } } else { None }; let param_body = match param_body { Some(param_body) => param_body, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required body parameter body")) - .expect("Unable to create Bad Request response for missing body parameter body"))), + .expect("Unable to create Bad Request response for missing body parameter body")), }; - Box::new( - api_impl.test_body_with_query_params( + let result = api_impl.test_body_with_query_params( param_query, param_body, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -844,17 +806,13 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter body: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter body"))), + .expect("Unable to create Bad Request response due to unable to read body parameter body")), } - }) - ) as Self::Future }, // TestClientModel - PATCH /fake @@ -862,9 +820,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_body: Option = if !body.is_empty() { @@ -874,29 +831,28 @@ where unused_elements.push(path.to_string()); }) { Ok(param_body) => param_body, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid body parameter body due to schema"))), + .expect("Unable to create Bad Request response for invalid body parameter body due to schema")), } } else { None }; let param_body = match param_body { Some(param_body) => param_body, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required body parameter body")) - .expect("Unable to create Bad Request response for missing body parameter body"))), + .expect("Unable to create Bad Request response for missing body parameter body")), }; - Box::new( - api_impl.test_client_model( + let result = api_impl.test_client_model( param_body, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -930,17 +886,13 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter body: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter body"))), + .expect("Unable to create Bad Request response due to unable to read body parameter body")), } - }) - ) as Self::Future }, // TestEndpointParameters - POST /fake @@ -948,15 +900,13 @@ where { let authorization = match (&context as &dyn Has>).get() { &Some(ref authorization) => authorization, - &None => return Box::new(future::ok(Response::builder() + &None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) .body(Body::from("Unauthenticated")) - .expect("Unable to create Authentication Forbidden response"))), + .expect("Unable to create Authentication Forbidden response")), }; } - Box::new({ - {{ // Form parameters let param_integer = Some(56); let param_int32 = Some(56); @@ -973,8 +923,7 @@ where let param_password = Some("password_example".to_string()); let param_callback = Some("callback_example".to_string()); - Box::new( - api_impl.test_endpoint_parameters( + let result = api_impl.test_endpoint_parameters( param_number, param_double, param_pattern_without_delimiter, @@ -990,9 +939,9 @@ where param_password, param_callback, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1016,11 +965,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // TestEnumParameters - GET /fake @@ -1033,10 +978,10 @@ where Ok(result) => Some(result.0), Err(err) => { - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Invalid header enum_header_string_array - {}", err))) - .expect("Unable to create Bad Request response for invalid header enum_header_string_array"))); + .expect("Unable to create Bad Request response for invalid header enum_header_string_array")); }, }, @@ -1051,10 +996,10 @@ where Ok(result) => Some(result.0), Err(err) => { - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Invalid header enum_header_string - {}", err))) - .expect("Unable to create Bad Request response for invalid header enum_header_string"))); + .expect("Unable to create Bad Request response for invalid header enum_header_string")); }, }, @@ -1083,13 +1028,10 @@ where .nth(0); let param_enum_query_double = param_enum_query_double.and_then(|param_enum_query_double| param_enum_query_double.parse::<>().ok()); - Box::new({ - {{ // Form parameters let param_enum_form_string = Some("enum_form_string_example".to_string()); - Box::new( - api_impl.test_enum_parameters( + let result = api_impl.test_enum_parameters( param_enum_header_string_array.as_ref(), param_enum_header_string, param_enum_query_string_array.as_ref(), @@ -1098,9 +1040,9 @@ where param_enum_query_double, param_enum_form_string, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1124,11 +1066,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // TestInlineAdditionalProperties - POST /fake/inline-additionalProperties @@ -1136,9 +1074,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_param: Option> = if !body.is_empty() { @@ -1148,29 +1085,28 @@ where unused_elements.push(path.to_string()); }) { Ok(param_param) => param_param, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse body parameter param - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid body parameter param due to schema"))), + .expect("Unable to create Bad Request response for invalid body parameter param due to schema")), } } else { None }; let param_param = match param_param { Some(param_param) => param_param, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required body parameter param")) - .expect("Unable to create Bad Request response for missing body parameter param"))), + .expect("Unable to create Bad Request response for missing body parameter param")), }; - Box::new( - api_impl.test_inline_additional_properties( + let result = api_impl.test_inline_additional_properties( param_param, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1197,35 +1133,28 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter param: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter param"))), + .expect("Unable to create Bad Request response due to unable to read body parameter param")), } - }) - ) as Self::Future }, // TestJsonFormData - GET /fake/jsonFormData &hyper::Method::GET if path.matched(paths::ID_FAKE_JSONFORMDATA) => { - Box::new({ - {{ // Form parameters let param_param = "param_example".to_string(); let param_param2 = "param2_example".to_string(); - Box::new( - api_impl.test_json_form_data( + let result = api_impl.test_json_form_data( param_param, param_param2, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1245,11 +1174,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // TestClassname - PATCH /fake_classname_test @@ -1257,19 +1182,18 @@ where { let authorization = match (&context as &dyn Has>).get() { &Some(ref authorization) => authorization, - &None => return Box::new(future::ok(Response::builder() + &None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) .body(Body::from("Unauthenticated")) - .expect("Unable to create Authentication Forbidden response"))), + .expect("Unable to create Authentication Forbidden response")), }; } // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_body: Option = if !body.is_empty() { @@ -1279,29 +1203,28 @@ where unused_elements.push(path.to_string()); }) { Ok(param_body) => param_body, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid body parameter body due to schema"))), + .expect("Unable to create Bad Request response for invalid body parameter body due to schema")), } } else { None }; let param_body = match param_body { Some(param_body) => param_body, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required body parameter body")) - .expect("Unable to create Bad Request response for missing body parameter body"))), + .expect("Unable to create Bad Request response for missing body parameter body")), }; - Box::new( - api_impl.test_classname( + let result = api_impl.test_classname( param_body, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1335,17 +1258,13 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter body: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter body"))), + .expect("Unable to create Bad Request response due to unable to read body parameter body")), } - }) - ) as Self::Future }, // AddPet - POST /pet @@ -1353,10 +1272,10 @@ where { let authorization = match (&context as &dyn Has>).get() { &Some(ref authorization) => authorization, - &None => return Box::new(future::ok(Response::builder() + &None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) .body(Body::from("Unauthenticated")) - .expect("Unable to create Authentication Forbidden response"))), + .expect("Unable to create Authentication Forbidden response")), }; // Authorization @@ -1368,14 +1287,14 @@ where if !required_scopes.is_subset(scopes) { let missing_scopes = required_scopes.difference(scopes); - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::FORBIDDEN) .body(Body::from(missing_scopes.fold( "Insufficient authorization, missing scopes".to_string(), |s, scope| format!("{} {}", s, scope)) )) .expect("Unable to create Authentication Insufficient response") - )); + ); } } } @@ -1383,9 +1302,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_body: Option = if !body.is_empty() { @@ -1395,29 +1313,28 @@ where unused_elements.push(path.to_string()); }) { Ok(param_body) => param_body, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid body parameter body due to schema"))), + .expect("Unable to create Bad Request response for invalid body parameter body due to schema")), } } else { None }; let param_body = match param_body { Some(param_body) => param_body, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required body parameter body")) - .expect("Unable to create Bad Request response for missing body parameter body"))), + .expect("Unable to create Bad Request response for missing body parameter body")), }; - Box::new( - api_impl.add_pet( + let result = api_impl.add_pet( param_body, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1444,17 +1361,13 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter body: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter body"))), + .expect("Unable to create Bad Request response due to unable to read body parameter body")), } - }) - ) as Self::Future }, // DeletePet - DELETE /pet/{petId} @@ -1462,10 +1375,10 @@ where { let authorization = match (&context as &dyn Has>).get() { &Some(ref authorization) => authorization, - &None => return Box::new(future::ok(Response::builder() + &None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) .body(Body::from("Unauthenticated")) - .expect("Unable to create Authentication Forbidden response"))), + .expect("Unable to create Authentication Forbidden response")), }; // Authorization @@ -1477,14 +1390,14 @@ where if !required_scopes.is_subset(scopes) { let missing_scopes = required_scopes.difference(scopes); - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::FORBIDDEN) .body(Body::from(missing_scopes.fold( "Insufficient authorization, missing scopes".to_string(), |s, scope| format!("{} {}", s, scope)) )) .expect("Unable to create Authentication Insufficient response") - )); + ); } } } @@ -1501,15 +1414,15 @@ where let param_pet_id = match percent_encoding::percent_decode(path_params["petId"].as_bytes()).decode_utf8() { Ok(param_pet_id) => match param_pet_id.parse::() { Ok(param_pet_id) => param_pet_id, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse path parameter petId: {}", e))) - .expect("Unable to create Bad Request response for invalid path parameter"))), + .expect("Unable to create Bad Request response for invalid path parameter")), }, - Err(_) => return Box::new(future::ok(Response::builder() + Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["petId"]))) - .expect("Unable to create Bad Request response for invalid percent decode"))) + .expect("Unable to create Bad Request response for invalid percent decode")) }; // Header parameters @@ -1520,10 +1433,10 @@ where Ok(result) => Some(result.0), Err(err) => { - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Invalid header api_key - {}", err))) - .expect("Unable to create Bad Request response for invalid header api_key"))); + .expect("Unable to create Bad Request response for invalid header api_key")); }, }, @@ -1532,16 +1445,13 @@ where } }; - Box::new({ - {{ - Box::new( - api_impl.delete_pet( + let result = api_impl.delete_pet( param_pet_id, param_api_key, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1561,11 +1471,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // FindPetsByStatus - GET /pet/findByStatus @@ -1573,10 +1479,10 @@ where { let authorization = match (&context as &dyn Has>).get() { &Some(ref authorization) => authorization, - &None => return Box::new(future::ok(Response::builder() + &None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) .body(Body::from("Unauthenticated")) - .expect("Unable to create Authentication Forbidden response"))), + .expect("Unable to create Authentication Forbidden response")), }; // Authorization @@ -1588,14 +1494,14 @@ where if !required_scopes.is_subset(scopes) { let missing_scopes = required_scopes.difference(scopes); - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::FORBIDDEN) .body(Body::from(missing_scopes.fold( "Insufficient authorization, missing scopes".to_string(), |s, scope| format!("{} {}", s, scope)) )) .expect("Unable to create Authentication Insufficient response") - )); + ); } } } @@ -1606,15 +1512,12 @@ where .filter_map(|param_status| param_status.parse().ok()) .collect::>(); - Box::new({ - {{ - Box::new( - api_impl.find_pets_by_status( + let result = api_impl.find_pets_by_status( param_status.as_ref(), &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1645,11 +1548,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // FindPetsByTags - GET /pet/findByTags @@ -1657,10 +1556,10 @@ where { let authorization = match (&context as &dyn Has>).get() { &Some(ref authorization) => authorization, - &None => return Box::new(future::ok(Response::builder() + &None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) .body(Body::from("Unauthenticated")) - .expect("Unable to create Authentication Forbidden response"))), + .expect("Unable to create Authentication Forbidden response")), }; // Authorization @@ -1672,14 +1571,14 @@ where if !required_scopes.is_subset(scopes) { let missing_scopes = required_scopes.difference(scopes); - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::FORBIDDEN) .body(Body::from(missing_scopes.fold( "Insufficient authorization, missing scopes".to_string(), |s, scope| format!("{} {}", s, scope)) )) .expect("Unable to create Authentication Insufficient response") - )); + ); } } } @@ -1690,15 +1589,12 @@ where .filter_map(|param_tags| param_tags.parse().ok()) .collect::>(); - Box::new({ - {{ - Box::new( - api_impl.find_pets_by_tags( + let result = api_impl.find_pets_by_tags( param_tags.as_ref(), &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1729,11 +1625,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // GetPetById - GET /pet/{petId} @@ -1741,10 +1633,10 @@ where { let authorization = match (&context as &dyn Has>).get() { &Some(ref authorization) => authorization, - &None => return Box::new(future::ok(Response::builder() + &None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) .body(Body::from("Unauthenticated")) - .expect("Unable to create Authentication Forbidden response"))), + .expect("Unable to create Authentication Forbidden response")), }; } @@ -1760,26 +1652,23 @@ where let param_pet_id = match percent_encoding::percent_decode(path_params["petId"].as_bytes()).decode_utf8() { Ok(param_pet_id) => match param_pet_id.parse::() { Ok(param_pet_id) => param_pet_id, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse path parameter petId: {}", e))) - .expect("Unable to create Bad Request response for invalid path parameter"))), + .expect("Unable to create Bad Request response for invalid path parameter")), }, - Err(_) => return Box::new(future::ok(Response::builder() + Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["petId"]))) - .expect("Unable to create Bad Request response for invalid percent decode"))) + .expect("Unable to create Bad Request response for invalid percent decode")) }; - Box::new({ - {{ - Box::new( - api_impl.get_pet_by_id( + let result = api_impl.get_pet_by_id( param_pet_id, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1814,11 +1703,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // UpdatePet - PUT /pet @@ -1826,10 +1711,10 @@ where { let authorization = match (&context as &dyn Has>).get() { &Some(ref authorization) => authorization, - &None => return Box::new(future::ok(Response::builder() + &None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) .body(Body::from("Unauthenticated")) - .expect("Unable to create Authentication Forbidden response"))), + .expect("Unable to create Authentication Forbidden response")), }; // Authorization @@ -1841,14 +1726,14 @@ where if !required_scopes.is_subset(scopes) { let missing_scopes = required_scopes.difference(scopes); - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::FORBIDDEN) .body(Body::from(missing_scopes.fold( "Insufficient authorization, missing scopes".to_string(), |s, scope| format!("{} {}", s, scope)) )) .expect("Unable to create Authentication Insufficient response") - )); + ); } } } @@ -1856,9 +1741,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_body: Option = if !body.is_empty() { @@ -1868,29 +1752,28 @@ where unused_elements.push(path.to_string()); }) { Ok(param_body) => param_body, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid body parameter body due to schema"))), + .expect("Unable to create Bad Request response for invalid body parameter body due to schema")), } } else { None }; let param_body = match param_body { Some(param_body) => param_body, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required body parameter body")) - .expect("Unable to create Bad Request response for missing body parameter body"))), + .expect("Unable to create Bad Request response for missing body parameter body")), }; - Box::new( - api_impl.update_pet( + let result = api_impl.update_pet( param_body, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -1925,17 +1808,13 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter body: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter body"))), + .expect("Unable to create Bad Request response due to unable to read body parameter body")), } - }) - ) as Self::Future }, // UpdatePetWithForm - POST /pet/{petId} @@ -1943,10 +1822,10 @@ where { let authorization = match (&context as &dyn Has>).get() { &Some(ref authorization) => authorization, - &None => return Box::new(future::ok(Response::builder() + &None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) .body(Body::from("Unauthenticated")) - .expect("Unable to create Authentication Forbidden response"))), + .expect("Unable to create Authentication Forbidden response")), }; // Authorization @@ -1958,14 +1837,14 @@ where if !required_scopes.is_subset(scopes) { let missing_scopes = required_scopes.difference(scopes); - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::FORBIDDEN) .body(Body::from(missing_scopes.fold( "Insufficient authorization, missing scopes".to_string(), |s, scope| format!("{} {}", s, scope)) )) .expect("Unable to create Authentication Insufficient response") - )); + ); } } } @@ -1982,32 +1861,29 @@ where let param_pet_id = match percent_encoding::percent_decode(path_params["petId"].as_bytes()).decode_utf8() { Ok(param_pet_id) => match param_pet_id.parse::() { Ok(param_pet_id) => param_pet_id, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse path parameter petId: {}", e))) - .expect("Unable to create Bad Request response for invalid path parameter"))), + .expect("Unable to create Bad Request response for invalid path parameter")), }, - Err(_) => return Box::new(future::ok(Response::builder() + Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["petId"]))) - .expect("Unable to create Bad Request response for invalid percent decode"))) + .expect("Unable to create Bad Request response for invalid percent decode")) }; - Box::new({ - {{ // Form parameters let param_name = Some("name_example".to_string()); let param_status = Some("status_example".to_string()); - Box::new( - api_impl.update_pet_with_form( + let result = api_impl.update_pet_with_form( param_pet_id, param_name, param_status, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -2027,11 +1903,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // UploadFile - POST /pet/{petId}/uploadImage @@ -2039,10 +1911,10 @@ where { let authorization = match (&context as &dyn Has>).get() { &Some(ref authorization) => authorization, - &None => return Box::new(future::ok(Response::builder() + &None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) .body(Body::from("Unauthenticated")) - .expect("Unable to create Authentication Forbidden response"))), + .expect("Unable to create Authentication Forbidden response")), }; // Authorization @@ -2054,24 +1926,24 @@ where if !required_scopes.is_subset(scopes) { let missing_scopes = required_scopes.difference(scopes); - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::FORBIDDEN) .body(Body::from(missing_scopes.fold( "Insufficient authorization, missing scopes".to_string(), |s, scope| format!("{} {}", s, scope)) )) .expect("Unable to create Authentication Insufficient response") - )); + ); } } } let boundary = match swagger::multipart::boundary(&headers) { Some(boundary) => boundary.to_string(), - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Couldn't find valid multipart body".to_string())) - .expect("Unable to create Bad Request response for incorrect boundary"))), + .expect("Unable to create Bad Request response for incorrect boundary")), }; // Path parameters @@ -2086,23 +1958,22 @@ where let param_pet_id = match percent_encoding::percent_decode(path_params["petId"].as_bytes()).decode_utf8() { Ok(param_pet_id) => match param_pet_id.parse::() { Ok(param_pet_id) => param_pet_id, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse path parameter petId: {}", e))) - .expect("Unable to create Bad Request response for invalid path parameter"))), + .expect("Unable to create Bad Request response for invalid path parameter")), }, - Err(_) => return Box::new(future::ok(Response::builder() + Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["petId"]))) - .expect("Unable to create Bad Request response for invalid percent decode"))) + .expect("Unable to create Bad Request response for invalid percent decode")) }; // Form Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw(); + match result.await { Ok(body) => { use std::io::Read; @@ -2112,10 +1983,10 @@ where entries }, _ => { - return Box::new(future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Unable to process all message parts"))) - .expect("Unable to create Bad Request response due to failure to process all message"))) + .expect("Unable to create Bad Request response due to failure to process all message")) }, }; let field_additional_metadata = entries.fields.remove("additional_metadata"); @@ -2128,11 +1999,11 @@ where let additional_metadata_model: String = match serde_json::from_str(&data) { Ok(model) => model, Err(e) => { - return Box::new(future::ok( + return Ok( Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("additional_metadata data does not match API definition : {}", e))) - .expect("Unable to create Bad Request due to missing required form parameter additional_metadata"))) + .expect("Unable to create Bad Request due to missing required form parameter additional_metadata")) } }; additional_metadata_model @@ -2152,11 +2023,11 @@ where let file_model: swagger::ByteArray = match serde_json::from_str(&data) { Ok(model) => model, Err(e) => { - return Box::new(future::ok( + return Ok( Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("file data does not match API definition : {}", e))) - .expect("Unable to create Bad Request due to missing required form parameter file"))) + .expect("Unable to create Bad Request due to missing required form parameter file")) } }; file_model @@ -2166,15 +2037,14 @@ where None } }; - Box::new( - api_impl.upload_file( + let result = api_impl.upload_file( param_pet_id, param_additional_metadata, param_file, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -2201,18 +2071,13 @@ where }, } - future::ok(response) - } - )) - as Self::Future + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read multipart body"))) - .expect("Unable to create Bad Request response due to unable read multipart body"))), + .expect("Unable to create Bad Request response due to unable read multipart body")), } - }) - ) }, // DeleteOrder - DELETE /store/order/{order_id} @@ -2229,26 +2094,23 @@ where let param_order_id = match percent_encoding::percent_decode(path_params["order_id"].as_bytes()).decode_utf8() { Ok(param_order_id) => match param_order_id.parse::() { Ok(param_order_id) => param_order_id, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse path parameter order_id: {}", e))) - .expect("Unable to create Bad Request response for invalid path parameter"))), + .expect("Unable to create Bad Request response for invalid path parameter")), }, - Err(_) => return Box::new(future::ok(Response::builder() + Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["order_id"]))) - .expect("Unable to create Bad Request response for invalid percent decode"))) + .expect("Unable to create Bad Request response for invalid percent decode")) }; - Box::new({ - {{ - Box::new( - api_impl.delete_order( + let result = api_impl.delete_order( param_order_id, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -2272,11 +2134,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // GetInventory - GET /store/inventory @@ -2284,21 +2142,18 @@ where { let authorization = match (&context as &dyn Has>).get() { &Some(ref authorization) => authorization, - &None => return Box::new(future::ok(Response::builder() + &None => return Ok(Response::builder() .status(StatusCode::FORBIDDEN) .body(Body::from("Unauthenticated")) - .expect("Unable to create Authentication Forbidden response"))), + .expect("Unable to create Authentication Forbidden response")), }; } - Box::new({ - {{ - Box::new( - api_impl.get_inventory( + let result = api_impl.get_inventory( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -2325,11 +2180,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // GetOrderById - GET /store/order/{order_id} @@ -2346,26 +2197,23 @@ where let param_order_id = match percent_encoding::percent_decode(path_params["order_id"].as_bytes()).decode_utf8() { Ok(param_order_id) => match param_order_id.parse::() { Ok(param_order_id) => param_order_id, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse path parameter order_id: {}", e))) - .expect("Unable to create Bad Request response for invalid path parameter"))), + .expect("Unable to create Bad Request response for invalid path parameter")), }, - Err(_) => return Box::new(future::ok(Response::builder() + Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["order_id"]))) - .expect("Unable to create Bad Request response for invalid percent decode"))) + .expect("Unable to create Bad Request response for invalid percent decode")) }; - Box::new({ - {{ - Box::new( - api_impl.get_order_by_id( + let result = api_impl.get_order_by_id( param_order_id, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -2400,11 +2248,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // PlaceOrder - POST /store/order @@ -2412,9 +2256,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_body: Option = if !body.is_empty() { @@ -2424,29 +2267,28 @@ where unused_elements.push(path.to_string()); }) { Ok(param_body) => param_body, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid body parameter body due to schema"))), + .expect("Unable to create Bad Request response for invalid body parameter body due to schema")), } } else { None }; let param_body = match param_body { Some(param_body) => param_body, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required body parameter body")) - .expect("Unable to create Bad Request response for missing body parameter body"))), + .expect("Unable to create Bad Request response for missing body parameter body")), }; - Box::new( - api_impl.place_order( + let result = api_impl.place_order( param_body, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -2484,17 +2326,13 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter body: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter body"))), + .expect("Unable to create Bad Request response due to unable to read body parameter body")), } - }) - ) as Self::Future }, // CreateUser - POST /user @@ -2502,9 +2340,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_body: Option = if !body.is_empty() { @@ -2514,29 +2351,28 @@ where unused_elements.push(path.to_string()); }) { Ok(param_body) => param_body, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid body parameter body due to schema"))), + .expect("Unable to create Bad Request response for invalid body parameter body due to schema")), } } else { None }; let param_body = match param_body { Some(param_body) => param_body, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required body parameter body")) - .expect("Unable to create Bad Request response for missing body parameter body"))), + .expect("Unable to create Bad Request response for missing body parameter body")), }; - Box::new( - api_impl.create_user( + let result = api_impl.create_user( param_body, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -2563,17 +2399,13 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter body: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter body"))), + .expect("Unable to create Bad Request response due to unable to read body parameter body")), } - }) - ) as Self::Future }, // CreateUsersWithArrayInput - POST /user/createWithArray @@ -2581,9 +2413,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_body: Option> = if !body.is_empty() { @@ -2593,29 +2424,28 @@ where unused_elements.push(path.to_string()); }) { Ok(param_body) => param_body, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid body parameter body due to schema"))), + .expect("Unable to create Bad Request response for invalid body parameter body due to schema")), } } else { None }; let param_body = match param_body { Some(param_body) => param_body, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required body parameter body")) - .expect("Unable to create Bad Request response for missing body parameter body"))), + .expect("Unable to create Bad Request response for missing body parameter body")), }; - Box::new( - api_impl.create_users_with_array_input( + let result = api_impl.create_users_with_array_input( param_body.as_ref(), &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -2642,17 +2472,13 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter body: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter body"))), + .expect("Unable to create Bad Request response due to unable to read body parameter body")), } - }) - ) as Self::Future }, // CreateUsersWithListInput - POST /user/createWithList @@ -2660,9 +2486,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_body: Option> = if !body.is_empty() { @@ -2672,29 +2497,28 @@ where unused_elements.push(path.to_string()); }) { Ok(param_body) => param_body, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid body parameter body due to schema"))), + .expect("Unable to create Bad Request response for invalid body parameter body due to schema")), } } else { None }; let param_body = match param_body { Some(param_body) => param_body, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required body parameter body")) - .expect("Unable to create Bad Request response for missing body parameter body"))), + .expect("Unable to create Bad Request response for missing body parameter body")), }; - Box::new( - api_impl.create_users_with_list_input( + let result = api_impl.create_users_with_list_input( param_body.as_ref(), &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -2721,17 +2545,13 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter body: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter body"))), + .expect("Unable to create Bad Request response due to unable to read body parameter body")), } - }) - ) as Self::Future }, // DeleteUser - DELETE /user/{username} @@ -2748,26 +2568,23 @@ where let param_username = match percent_encoding::percent_decode(path_params["username"].as_bytes()).decode_utf8() { Ok(param_username) => match param_username.parse::() { Ok(param_username) => param_username, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse path parameter username: {}", e))) - .expect("Unable to create Bad Request response for invalid path parameter"))), + .expect("Unable to create Bad Request response for invalid path parameter")), }, - Err(_) => return Box::new(future::ok(Response::builder() + Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["username"]))) - .expect("Unable to create Bad Request response for invalid percent decode"))) + .expect("Unable to create Bad Request response for invalid percent decode")) }; - Box::new({ - {{ - Box::new( - api_impl.delete_user( + let result = api_impl.delete_user( param_username, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -2791,11 +2608,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // GetUserByName - GET /user/{username} @@ -2812,26 +2625,23 @@ where let param_username = match percent_encoding::percent_decode(path_params["username"].as_bytes()).decode_utf8() { Ok(param_username) => match param_username.parse::() { Ok(param_username) => param_username, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse path parameter username: {}", e))) - .expect("Unable to create Bad Request response for invalid path parameter"))), + .expect("Unable to create Bad Request response for invalid path parameter")), }, - Err(_) => return Box::new(future::ok(Response::builder() + Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["username"]))) - .expect("Unable to create Bad Request response for invalid percent decode"))) + .expect("Unable to create Bad Request response for invalid percent decode")) }; - Box::new({ - {{ - Box::new( - api_impl.get_user_by_name( + let result = api_impl.get_user_by_name( param_username, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -2866,11 +2676,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // LoginUser - GET /user/login @@ -2882,42 +2688,39 @@ where let param_username = match param_username { Some(param_username) => match param_username.parse::() { Ok(param_username) => param_username, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse query parameter username - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid query parameter username"))), + .expect("Unable to create Bad Request response for invalid query parameter username")), }, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required query parameter username")) - .expect("Unable to create Bad Request response for missing qeury parameter username"))), + .expect("Unable to create Bad Request response for missing qeury parameter username")), }; let param_password = query_params.iter().filter(|e| e.0 == "password").map(|e| e.1.to_owned()) .nth(0); let param_password = match param_password { Some(param_password) => match param_password.parse::() { Ok(param_password) => param_password, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse query parameter password - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid query parameter password"))), + .expect("Unable to create Bad Request response for invalid query parameter password")), }, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required query parameter password")) - .expect("Unable to create Bad Request response for missing qeury parameter password"))), + .expect("Unable to create Bad Request response for missing qeury parameter password")), }; - Box::new({ - {{ - Box::new( - api_impl.login_user( + let result = api_impl.login_user( param_username, param_password, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -2934,7 +2737,7 @@ where let x_rate_limit = match header::IntoHeaderValue(x_rate_limit).try_into() { Ok(val) => val, Err(e) => { - return future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) .body(Body::from(format!("An internal server error occurred handling x_rate_limit header - {}", e))) .expect("Unable to create Internal Server Error for invalid response header")) @@ -2944,7 +2747,7 @@ where let x_expires_after = match header::IntoHeaderValue(x_expires_after).try_into() { Ok(val) => val, Err(e) => { - return future::ok(Response::builder() + return Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) .body(Body::from(format!("An internal server error occurred handling x_expires_after header - {}", e))) .expect("Unable to create Internal Server Error for invalid response header")) @@ -2980,23 +2783,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // LogoutUser - GET /user/logout &hyper::Method::GET if path.matched(paths::ID_USER_LOGOUT) => { - Box::new({ - {{ - Box::new( - api_impl.logout_user( + let result = api_impl.logout_user( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -3016,11 +2812,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // UpdateUser - PUT /user/{username} @@ -3037,23 +2829,22 @@ where let param_username = match percent_encoding::percent_decode(path_params["username"].as_bytes()).decode_utf8() { Ok(param_username) => match param_username.parse::() { Ok(param_username) => param_username, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse path parameter username: {}", e))) - .expect("Unable to create Bad Request response for invalid path parameter"))), + .expect("Unable to create Bad Request response for invalid path parameter")), }, - Err(_) => return Box::new(future::ok(Response::builder() + Err(_) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't percent-decode path parameter as UTF-8: {}", &path_params["username"]))) - .expect("Unable to create Bad Request response for invalid percent decode"))) + .expect("Unable to create Bad Request response for invalid percent decode")) }; // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_body: Option = if !body.is_empty() { @@ -3063,30 +2854,29 @@ where unused_elements.push(path.to_string()); }) { Ok(param_body) => param_body, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse body parameter body - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid body parameter body due to schema"))), + .expect("Unable to create Bad Request response for invalid body parameter body due to schema")), } } else { None }; let param_body = match param_body { Some(param_body) => param_body, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required body parameter body")) - .expect("Unable to create Bad Request response for missing body parameter body"))), + .expect("Unable to create Bad Request response for missing body parameter body")), }; - Box::new( - api_impl.update_user( + let result = api_impl.update_user( param_username, param_body, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -3117,17 +2907,13 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter body: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter body"))), + .expect("Unable to create Bad Request response due to unable to read body parameter body")), } - }) - ) as Self::Future }, _ if path.matched(paths::ID_ANOTHER_FAKE_DUMMY) => method_not_allowed(), @@ -3157,23 +2943,11 @@ where _ if path.matched(paths::ID_USER_LOGIN) => method_not_allowed(), _ if path.matched(paths::ID_USER_LOGOUT) => method_not_allowed(), _ if path.matched(paths::ID_USER_USERNAME) => method_not_allowed(), - _ => Box::new(future::ok( - Response::builder().status(StatusCode::NOT_FOUND) + _ => Ok(Response::builder().status(StatusCode::NOT_FOUND) .body(Body::empty()) - .expect("Unable to create Not Found response") - )) as Self::Future + .expect("Unable to create Not Found response")) } - } -} - -impl Clone for Service where T: Clone -{ - fn clone(&self) -> Self { - Service { - api_impl: self.api_impl.clone(), - marker: self.marker.clone(), - } - } + } Box::pin(run(self.api_impl.clone(), req)) } } /// Request parser for `Api`. diff --git a/samples/server/petstore/rust-server/output/rust-server-test/Cargo.toml b/samples/server/petstore/rust-server/output/rust-server-test/Cargo.toml index 8479e643bd6..adb71498607 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/Cargo.toml +++ b/samples/server/petstore/rust-server/output/rust-server-test/Cargo.toml @@ -9,7 +9,7 @@ edition = "2018" [features] default = ["client", "server"] client = [ - "hyper", "hyper-openssl", "native-tls", "openssl", "url" + "hyper", "hyper-openssl", "hyper-tls", "native-tls", "openssl", "url" ] server = [ "serde_ignored", "hyper", "regex", "percent-encoding", "url", "lazy_static" @@ -18,35 +18,37 @@ conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk- [target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] native-tls = { version = "0.2", optional = true } +hyper-tls = { version = "0.4", optional = true } [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dependencies] -hyper-openssl = { version = "0.7.1", optional = true } +hyper-openssl = { version = "0.8", optional = true } openssl = {version = "0.10", optional = true } [dependencies] # Common +async-trait = "0.1.24" chrono = { version = "0.4", features = ["serde"] } -futures = "0.1" -swagger = "4.0" +futures = "0.3" +swagger = "5.0.0-alpha-1" log = "0.4.0" mime = "0.3" -serde = { version = "1.0", features = ["derive"]} +serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" # Crates included if required by the API definition # Common between server and client features -hyper = {version = "0.12", optional = true} -serde_ignored = {version = "0.0.4", optional = true} -url = {version = "1.5", optional = true} +hyper = {version = "0.13", optional = true} +serde_ignored = {version = "0.1.1", optional = true} +url = {version = "2.1", optional = true} # Client-specific # Server, and client callback-specific lazy_static = { version = "1.4", optional = true } -percent-encoding = {version = "1.0.0", optional = true} -regex = {version = "0.2", optional = true} +percent-encoding = {version = "2.1.0", optional = true} +regex = {version = "1.3", optional = true} # Conversion frunk = { version = "0.3.0", optional = true } @@ -57,13 +59,13 @@ frunk-enum-core = { version = "0.2.0", optional = true } [dev-dependencies] clap = "2.25" -error-chain = "0.12" -env_logger = "0.6" -tokio = "0.1.17" -uuid = {version = "0.7", features = ["serde", "v4"]} +env_logger = "0.7" +tokio = { version = "0.2", features = ["rt-threaded", "macros", "stream"] } +native-tls = "0.2" +tokio-tls = "0.3" [target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dev-dependencies] -tokio-openssl = "0.3" +tokio-openssl = "0.4" openssl = "0.10" [[example]] diff --git a/samples/server/petstore/rust-server/output/rust-server-test/examples/client/main.rs b/samples/server/petstore/rust-server/output/rust-server-test/examples/client/main.rs index 1584d433fe7..e615b83c4f0 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/examples/client/main.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/examples/client/main.rs @@ -2,10 +2,9 @@ #[allow(unused_imports)] -use futures::{Future, future, Stream, stream}; +use futures::{future, Stream, stream}; #[allow(unused_imports)] use rust_server_test::{Api, ApiNoContext, Client, ContextWrapperExt, models, - ApiError, AllOfGetResponse, DummyGetResponse, DummyPutResponse, @@ -14,7 +13,7 @@ use rust_server_test::{Api, ApiNoContext, Client, ContextWrapperExt, models, HtmlPostResponse, PostYamlResponse, RawJsonGetResponse, - SoloObjectPostResponse + SoloObjectPostResponse, }; use clap::{App, Arg}; @@ -23,7 +22,9 @@ use log::info; // swagger::Has may be unused if there are no examples #[allow(unused_imports)] -use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData}; +use swagger::{AuthData, ContextBuilder, EmptyContext, Has, Push, XSpanIdString}; + +type ClientContext = swagger::make_context_ty!(ContextBuilder, EmptyContext, Option, XSpanIdString); // rt may be unused if there are no examples #[allow(unused_mut)] @@ -65,21 +66,21 @@ fn main() { matches.value_of("host").unwrap(), matches.value_of("port").unwrap()); - let client = if matches.is_present("https") { - // Using Simple HTTPS - Client::try_new_https(&base_url) - .expect("Failed to create HTTPS client") - } else { - // Using HTTP - Client::try_new_http( - &base_url) - .expect("Failed to create HTTP client") - }; - - let context: swagger::make_context_ty!(ContextBuilder, EmptyContext, Option, XSpanIdString) = + let context: ClientContext = swagger::make_context!(ContextBuilder, EmptyContext, None as Option, XSpanIdString::default()); - let client = client.with_context(context); + let mut client : Box> = if matches.is_present("https") { + // Using Simple HTTPS + let client = Box::new(Client::try_new_https(&base_url) + .expect("Failed to create HTTPS client")); + Box::new(client.with_context(context)) + } else { + // Using HTTP + let client = Box::new(Client::try_new_http( + &base_url) + .expect("Failed to create HTTP client")); + Box::new(client.with_context(context)) + }; let mut rt = tokio::runtime::Runtime::new().unwrap(); diff --git a/samples/server/petstore/rust-server/output/rust-server-test/examples/server/main.rs b/samples/server/petstore/rust-server/output/rust-server-test/examples/server/main.rs index cdf588968aa..1a3f8022c38 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/examples/server/main.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/examples/server/main.rs @@ -9,7 +9,8 @@ mod server; /// Create custom server, wire it to the autogenerated router, /// and pass it to the web server. -fn main() { +#[tokio::main] +async fn main() { env_logger::init(); let matches = App::new("server") @@ -20,5 +21,5 @@ fn main() { let addr = "127.0.0.1:8080"; - hyper::rt::run(server::create(addr, matches.is_present("https"))); + server::create(addr, matches.is_present("https")).await; } diff --git a/samples/server/petstore/rust-server/output/rust-server-test/examples/server/server.rs b/samples/server/petstore/rust-server/output/rust-server-test/examples/server/server.rs index 5fa44541184..6ab48764bdd 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/examples/server/server.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/examples/server/server.rs @@ -2,30 +2,22 @@ #![allow(unused_imports)] -mod errors { - error_chain::error_chain!{} -} - -pub use self::errors::*; - -use chrono; -use futures::{future, Future, Stream}; +use async_trait::async_trait; +use futures::{future, Stream, StreamExt, TryFutureExt, TryStreamExt}; use hyper::server::conn::Http; -use hyper::service::MakeService as _; +use hyper::service::Service; use log::info; use openssl::ssl::SslAcceptorBuilder; +use std::future::Future; use std::marker::PhantomData; use std::net::SocketAddr; use std::sync::{Arc, Mutex}; -use swagger; +use std::task::{Context, Poll}; use swagger::{Has, XSpanIdString}; use swagger::auth::MakeAllowAllAuthenticator; use swagger::EmptyContext; use tokio::net::TcpListener; - -#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] -use tokio_openssl::SslAcceptorExt; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; @@ -33,18 +25,18 @@ use rust_server_test::models; #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] /// Builds an SSL implementation for Simple HTTPS from some hard-coded file names -pub fn create(addr: &str, https: bool) -> Box + Send> { +pub async fn create(addr: &str, https: bool) { let addr = addr.parse().expect("Failed to parse bind address"); let server = Server::new(); - let service_fn = MakeService::new(server); + let service = MakeService::new(server); - let service_fn = MakeAllowAllAuthenticator::new(service_fn, "cosmo"); + let service = MakeAllowAllAuthenticator::new(service, "cosmo"); - let service_fn = + let mut service = rust_server_test::server::context::MakeAddContext::<_, EmptyContext>::new( - service_fn + service ); if https { @@ -62,32 +54,31 @@ pub fn create(addr: &str, https: bool) -> Box ssl.set_certificate_chain_file("examples/server-chain.pem").expect("Failed to set cerificate chain"); ssl.check_private_key().expect("Failed to check private key"); - let tls_acceptor = ssl.build(); - let service_fn = Arc::new(Mutex::new(service_fn)); - let tls_listener = TcpListener::bind(&addr).unwrap().incoming().for_each(move |tcp| { - let addr = tcp.peer_addr().expect("Unable to get remote address"); + let tls_acceptor = Arc::new(ssl.build()); + let mut tcp_listener = TcpListener::bind(&addr).await.unwrap(); + let mut incoming = tcp_listener.incoming(); - let service_fn = service_fn.clone(); + while let (Some(tcp), rest) = incoming.into_future().await { + if let Ok(tcp) = tcp { + let addr = tcp.peer_addr().expect("Unable to get remote address"); + let service = service.call(addr); + let tls_acceptor = Arc::clone(&tls_acceptor); - hyper::rt::spawn(tls_acceptor.accept_async(tcp).map_err(|_| ()).and_then(move |tls| { - let ms = { - let mut service_fn = service_fn.lock().unwrap(); - service_fn.make_service(&addr) - }; + tokio::spawn(async move { + let tls = tokio_openssl::accept(&*tls_acceptor, tcp).await.map_err(|_| ())?; - ms.and_then(move |service| { - Http::new().serve_connection(tls, service) - }).map_err(|_| ()) - })); + let service = service.await.map_err(|_| ())?; - Ok(()) - }).map_err(|_| ()); + Http::new().serve_connection(tls, service).await.map_err(|_| ()) + }); + } - Box::new(tls_listener) + incoming = rest; + } } } else { // Using HTTP - Box::new(hyper::server::Server::bind(&addr).serve(service_fn).map_err(|e| panic!("{:?}", e))) + hyper::server::Server::bind(&addr).serve(service).await.unwrap() } } @@ -105,7 +96,6 @@ impl Server { use rust_server_test::{ Api, - ApiError, AllOfGetResponse, DummyGetResponse, DummyPutResponse, @@ -117,96 +107,100 @@ use rust_server_test::{ SoloObjectPostResponse, }; use rust_server_test::server::MakeService; +use std::error::Error; +use swagger::ApiError; -impl Api for Server where C: Has{ - fn all_of_get( +#[async_trait] +impl Api for Server where C: Has + Send + Sync +{ + async fn all_of_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("all_of_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// A dummy endpoint to make the spec valid. - fn dummy_get( + async fn dummy_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("dummy_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn dummy_put( + async fn dummy_put( &self, nested_response: models::InlineObject, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("dummy_put({:?}) - X-Span-ID: {:?}", nested_response, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Get a file - fn file_response_get( + async fn file_response_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("file_response_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn get_structured_yaml( + async fn get_structured_yaml( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("get_structured_yaml() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Test HTML handling - fn html_post( + async fn html_post( &self, body: String, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("html_post(\"{}\") - X-Span-ID: {:?}", body, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } - fn post_yaml( + async fn post_yaml( &self, value: String, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("post_yaml(\"{}\") - X-Span-ID: {:?}", value, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Get an arbitrary JSON blob. - fn raw_json_get( + async fn raw_json_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("raw_json_get() - X-Span-ID: {:?}", context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } /// Send an arbitrary JSON blob - fn solo_object_post( + async fn solo_object_post( &self, value: serde_json::Value, - context: &C) -> Box + Send> + context: &C) -> Result { let context = context.clone(); info!("solo_object_post({:?}) - X-Span-ID: {:?}", value, context.get().0.clone()); - Box::new(future::err("Generic failure".into())) + Err("Generic failuare".into()) } } diff --git a/samples/server/petstore/rust-server/output/rust-server-test/src/client/mod.rs b/samples/server/petstore/rust-server/output/rust-server-test/src/client/mod.rs index 7ce4e8ad0ac..aaece7a9b13 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/src/client/mod.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/src/client/mod.rs @@ -1,37 +1,38 @@ -use futures; -use futures::{Future, Stream, future, stream}; -use hyper; -use hyper::client::HttpConnector; +use async_trait::async_trait; +use futures::{Stream, future, future::BoxFuture, stream, future::TryFutureExt, future::FutureExt, stream::StreamExt}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; -use hyper::{Body, Uri, Response}; -#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] -use hyper_openssl::HttpsConnector; -use serde_json; +use hyper::{Body, Request, Response, service::Service, Uri}; +use percent_encoding::{utf8_percent_encode, AsciiSet}; use std::borrow::Cow; use std::convert::TryInto; -use std::io::{Read, Error, ErrorKind}; -use std::error; +use std::io::{ErrorKind, Read}; +use std::error::Error; +use std::future::Future; use std::fmt; use std::path::Path; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use std::str; use std::str::FromStr; use std::string::ToString; -use swagger; -use swagger::{ApiError, Connector, client::Service, XSpanIdString, Has, AuthData}; +use std::task::{Context, Poll}; +use swagger::{ApiError, AuthData, BodyExt, Connector, Has, XSpanIdString}; use url::form_urlencoded; -use url::percent_encoding::{utf8_percent_encode, PATH_SEGMENT_ENCODE_SET, QUERY_ENCODE_SET}; + use crate::models; use crate::header; -url::define_encode_set! { - /// This encode set is used for object IDs - /// - /// Aside from the special characters defined in the `PATH_SEGMENT_ENCODE_SET`, - /// the vertical bar (|) is encoded. - pub ID_ENCODE_SET = [PATH_SEGMENT_ENCODE_SET] | {'|'} -} +/// https://url.spec.whatwg.org/#fragment-percent-encode-set +#[allow(dead_code)] +const FRAGMENT_ENCODE_SET: &AsciiSet = &percent_encoding::CONTROLS + .add(b' ').add(b'"').add(b'<').add(b'>').add(b'`'); + +/// This encode set is used for object IDs +/// +/// Aside from the special characters defined in the `PATH_SEGMENT_ENCODE_SET`, +/// the vertical bar (|) is encoded. +#[allow(dead_code)] +const ID_ENCODE_SET: &AsciiSet = &FRAGMENT_ENCODE_SET.add(b'|'); use crate::{Api, AllOfGetResponse, @@ -46,11 +47,11 @@ use crate::{Api, }; /// Convert input into a base path, e.g. "http://example:123". Also checks the scheme as it goes. -fn into_base_path(input: &str, correct_scheme: Option<&'static str>) -> Result { +fn into_base_path(input: impl TryInto, correct_scheme: Option<&'static str>) -> Result { // First convert to Uri, since a base path is a subset of Uri. - let uri = Uri::from_str(input)?; + let uri = input.try_into()?; - let scheme = uri.scheme_part().ok_or(ClientInitError::InvalidScheme)?; + let scheme = uri.scheme_str().ok_or(ClientInitError::InvalidScheme)?; // Check the scheme if necessary if let Some(correct_scheme) = correct_scheme { @@ -60,38 +61,54 @@ fn into_base_path(input: &str, correct_scheme: Option<&'static str>) -> Result +pub struct Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { /// Inner service - client_service: Arc + Send + Sync>>, + client_service: S, /// Base path of the API base_path: String, } -impl fmt::Debug for Client +impl fmt::Debug for Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Client {{ base_path: {} }}", self.base_path) } } -impl Clone for Client +impl Clone for Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { fn clone(&self) -> Self { - Client { + Self { client_service: self.client_service.clone(), base_path: self.base_path.clone(), } } } -impl Client +impl Client> where + C: hyper::client::connect::Connect + Clone + Send + Sync + 'static { /// Create a client with a custom implementation of hyper::client::Connect. /// @@ -104,30 +121,93 @@ impl Client /// /// # Arguments /// - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "http://www.my-api-implementation.com" /// * `protocol` - Which protocol to use when constructing the request url, e.g. `Some("http")` /// * `connector` - Implementation of `hyper::client::Connect` to use for the client - pub fn try_new_with_connector( + pub fn try_new_with_connector( base_path: &str, protocol: Option<&'static str>, connector: C, - ) -> Result where - C: hyper::client::connect::Connect + 'static, - C::Transport: 'static, - C::Future: 'static, + ) -> Result { - let client_service = Box::new(hyper::client::Client::builder().build(connector)); + let client_service = hyper::client::Client::builder().build(connector); - Ok(Client { - client_service: Arc::new(client_service), + Ok(Self { + client_service, base_path: into_base_path(base_path, protocol)?, }) } +} +#[derive(Debug, Clone)] +pub enum HyperClient { + Http(hyper::client::Client), + Https(hyper::client::Client), +} + +impl Service> for HyperClient { + type Response = Response; + type Error = hyper::Error; + type Future = hyper::client::ResponseFuture; + + fn poll_ready(&mut self, cx: &mut Context) -> Poll> { + match self { + HyperClient::Http(client) => client.poll_ready(cx), + HyperClient::Https(client) => client.poll_ready(cx), + } + } + + fn call(&mut self, req: Request) -> Self::Future { + match self { + HyperClient::Http(client) => client.call(req), + HyperClient::Https(client) => client.call(req) + } + } +} + +impl Client { /// Create an HTTP client. /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "http://www.my-api-implementation.com" + pub fn try_new( + base_path: &str, + ) -> Result { + let uri = Uri::from_str(base_path)?; + + let scheme = uri.scheme_str().ok_or(ClientInitError::InvalidScheme)?; + let scheme = scheme.to_ascii_lowercase(); + + let connector = Connector::builder(); + + let client_service = match scheme.as_str() { + "http" => { + HyperClient::Http(hyper::client::Client::builder().build(connector.build())) + }, + "https" => { + let connector = connector.https() + .build() + .map_err(|e| ClientInitError::SslError(e))?; + HyperClient::Https(hyper::client::Client::builder().build(connector)) + }, + _ => { + return Err(ClientInitError::InvalidScheme); + } + }; + + Ok(Self { + client_service, + base_path: into_base_path(base_path, None)?, + }) + } +} + +impl Client> +{ + /// Create an HTTP client. + /// + /// # Arguments + /// * `base_path` - base path of the client API, i.e. "http://www.my-api-implementation.com" pub fn try_new_http( base_path: &str, ) -> Result { @@ -135,11 +215,20 @@ impl Client Self::try_new_with_connector(base_path, Some("http"), http_connector) } +} +#[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] +type HttpsConnector = hyper_tls::HttpsConnector; + +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +type HttpsConnector = hyper_openssl::HttpsConnector; + +impl Client> +{ /// Create a client with a TLS connection to the server /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "https://www.my-api-implementation.com" pub fn try_new_https(base_path: &str) -> Result { let https_connector = Connector::builder() @@ -152,7 +241,7 @@ impl Client /// Create a client with a TLS connection to the server using a pinned certificate /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "https://www.my-api-implementation.com" /// * `ca_certificate` - Path to CA certificate used to authenticate the server #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] pub fn try_new_https_pinned( @@ -173,7 +262,7 @@ impl Client /// Create a client with a mutually authenticated TLS connection to the server. /// /// # Arguments - /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + /// * `base_path` - base path of the client API, i.e. "https://www.my-api-implementation.com" /// * `ca_certificate` - Path to CA certificate used to authenticate the server /// * `client_key` - Path to the client private key /// * `client_certificate` - Path to the client's public certificate associated with the private key @@ -199,17 +288,24 @@ impl Client } } -impl Client +impl Client where + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { - /// Constructor for creating a `Client` by passing in a pre-made `swagger::Service` + /// Constructor for creating a `Client` by passing in a pre-made `hyper::service::Service` / + /// `tower::Service` /// /// This allows adding custom wrappers around the underlying transport, for example for logging. pub fn try_new_with_client_service( - client_service: Arc + Send + Sync>>, + client_service: S, base_path: &str, - ) -> Result { - Ok(Client { - client_service: client_service, + ) -> Result + { + Ok(Self { + client_service, base_path: into_base_path(base_path, None)?, }) } @@ -249,199 +345,205 @@ impl fmt::Display for ClientInitError { } } -impl error::Error for ClientInitError { +impl Error for ClientInitError { fn description(&self) -> &str { "Failed to produce a hyper client." } } -impl Api for Client where - C: Has , - F: Future, Error=hyper::Error> + Send + 'static +#[async_trait] +impl Api for Client where + C: Has + Clone + Send + Sync + 'static, + S: Service< + Request, + Response=Response> + Clone + Sync + Send + 'static, + S::Future: Send + 'static, + S::Error: Into + fmt::Display, { - fn all_of_get( + fn poll_ready(&self, cx: &mut Context) -> Poll> { + match self.client_service.clone().poll_ready(cx) { + Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())), + Poll::Ready(Ok(o)) => Poll::Ready(Ok(o)), + Poll::Pending => Poll::Pending, + } + } + + async fn all_of_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/allOf", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - serde_json::from_str::(body) - .map_err(|e| e.into()) - ) - ) - .map(move |body| { - AllOfGetResponse::OK - (body) - }) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(body)?; + Ok(AllOfGetResponse::OK + (body) + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn dummy_get( + async fn dummy_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/dummy", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - DummyGetResponse::Success - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + DummyGetResponse::Success + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn dummy_put( + async fn dummy_put( &self, param_nested_response: models::InlineObject, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/dummy", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("PUT") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let body = serde_json::to_string(¶m_nested_response).expect("impossible to fail to serialize"); @@ -450,243 +552,226 @@ impl Api for Client where let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - future::ok( - DummyPutResponse::Success - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + Ok( + DummyPutResponse::Success + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn file_response_get( + async fn file_response_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/file_response", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - serde_json::from_str::(body) - .map_err(|e| e.into()) - ) - ) - .map(move |body| { - FileResponseGetResponse::Success - (body) - }) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(body)?; + Ok(FileResponseGetResponse::Success + (body) + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn get_structured_yaml( + async fn get_structured_yaml( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/get-structured-yaml", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - Ok(body.to_string()) - ) - ) - .map(move |body| { - GetStructuredYamlResponse::OK - (body) - }) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = body.to_string(); + Ok(GetStructuredYamlResponse::OK + (body) + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn html_post( + async fn html_post( &self, param_body: String, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/html", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let body = param_body; @@ -695,89 +780,82 @@ impl Api for Client where let header = "text/html"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - Ok(body.to_string()) - ) - ) - .map(move |body| { - HtmlPostResponse::Success - (body) - }) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = body.to_string(); + Ok(HtmlPostResponse::Success + (body) + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn post_yaml( + async fn post_yaml( &self, param_value: String, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/post-yaml", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let body = param_value; @@ -786,161 +864,151 @@ impl Api for Client where let header = "application/yaml"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 204 => { - let body = response.into_body(); - Box::new( - future::ok( - PostYamlResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 204 => { + let body = response.into_body(); + Ok( + PostYamlResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn raw_json_get( + async fn raw_json_get( &self, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/raw_json", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("GET") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 200 => { - let body = response.into_body(); - Box::new( - body - .concat2() - .map_err(|e| ApiError(format!("Failed to read response: {}", e))) - .and_then(|body| - str::from_utf8(&body) - .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e))) - .and_then(|body| - serde_json::from_str::(body) - .map_err(|e| e.into()) - ) - ) - .map(move |body| { - RawJsonGetResponse::Success - (body) - }) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 200 => { + let body = response.into_body(); + let body = body + .to_raw() + .map_err(|e| ApiError(format!("Failed to read response: {}", e))).await?; + let body = str::from_utf8(&body) + .map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(body)?; + Ok(RawJsonGetResponse::Success + (body) + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } - fn solo_object_post( + async fn solo_object_post( &self, param_value: serde_json::Value, - context: &C) -> Box + Send> + context: &C) -> Result { + let mut client_service = self.client_service.clone(); let mut uri = format!( "{}/solo-object", self.base_path ); // Query parameters - let mut query_string = url::form_urlencoded::Serializer::new("".to_owned()); - let query_string_str = query_string.finish(); - if !query_string_str.is_empty() { + let query_string = { + let mut query_string = form_urlencoded::Serializer::new("".to_owned()); + query_string.finish() + }; + if !query_string.is_empty() { uri += "?"; - uri += &query_string_str; + uri += &query_string; } let uri = match Uri::from_str(&uri) { Ok(uri) => uri, - Err(err) => return Box::new(future::err(ApiError(format!("Unable to build URI: {}", err)))), + Err(err) => return Err(ApiError(format!("Unable to build URI: {}", err))), }; - let mut request = match hyper::Request::builder() + let mut request = match Request::builder() .method("POST") .uri(uri) .body(Body::empty()) { Ok(req) => req, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create request: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create request: {}", e))) }; let body = serde_json::to_string(¶m_value).expect("impossible to fail to serialize"); @@ -950,48 +1018,43 @@ impl Api for Client where let header = "application/json"; request.headers_mut().insert(CONTENT_TYPE, match HeaderValue::from_str(header) { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create header: {} - {}", header, e)))) + Err(e) => return Err(ApiError(format!("Unable to create header: {} - {}", header, e))) }); - let header = HeaderValue::from_str((context as &dyn Has).get().0.clone().to_string().as_str()); + let header = HeaderValue::from_str(Has::::get(context).0.clone().to_string().as_str()); request.headers_mut().insert(HeaderName::from_static("x-span-id"), match header { Ok(h) => h, - Err(e) => return Box::new(future::err(ApiError(format!("Unable to create X-Span ID header value: {}", e)))) + Err(e) => return Err(ApiError(format!("Unable to create X-Span ID header value: {}", e))) }); - Box::new(self.client_service.request(request) - .map_err(|e| ApiError(format!("No response received: {}", e))) - .and_then(|mut response| { - match response.status().as_u16() { - 204 => { - let body = response.into_body(); - Box::new( - future::ok( - SoloObjectPostResponse::OK - ) - ) as Box + Send> - }, - code => { - let headers = response.headers().clone(); - Box::new(response.into_body() - .take(100) - .concat2() - .then(move |body| - future::err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", - code, - headers, - match body { - Ok(ref body) => match str::from_utf8(body) { - Ok(body) => Cow::from(body), - Err(e) => Cow::from(format!("", e)), - }, - Err(e) => Cow::from(format!("", e)), - }))) - ) - ) as Box + Send> - } + let mut response = client_service.call(request) + .map_err(|e| ApiError(format!("No response received: {}", e))).await?; + + match response.status().as_u16() { + 204 => { + let body = response.into_body(); + Ok( + SoloObjectPostResponse::OK + ) } - })) + code => { + let headers = response.headers().clone(); + let body = response.into_body() + .take(100) + .to_raw().await; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + headers, + match body { + Ok(body) => match String::from_utf8(body) { + Ok(body) => body, + Err(e) => format!("", e), + }, + Err(e) => format!("", e), + } + ))) + } + } } } diff --git a/samples/server/petstore/rust-server/output/rust-server-test/src/context.rs b/samples/server/petstore/rust-server/output/rust-server-test/src/context.rs index d14e73f822d..fadd880b965 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/src/context.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/src/context.rs @@ -1,13 +1,12 @@ -use futures::Future; -use hyper; +use futures::future::BoxFuture; use hyper::header::HeaderName; -use hyper::{Error, Request, Response, StatusCode, service::Service, body::Payload}; +use hyper::{Error, Request, Response, StatusCode, service::Service}; use url::form_urlencoded; use std::default::Default; use std::io; use std::marker::PhantomData; +use std::task::{Poll, Context}; use swagger::auth::{AuthData, Authorization, Bearer, Scopes}; -use swagger::context::ContextualPayload; use swagger::{EmptyContext, Has, Pop, Push, XSpanIdString}; use crate::Api; @@ -31,58 +30,52 @@ where } // Make a service that adds context. -impl<'a, T, SC, A, B, C, D, E, ME, S, OB, F> hyper::service::MakeService<&'a SC> for +impl Service for MakeAddContext where - A: Default + Push, + Target: Send, + A: Default + Push + Send, B: Push, Result = C>, C: Push, Result = D>, D: Send + 'static, - T: hyper::service::MakeService< - &'a SC, - Error = E, - MakeError = ME, - Service = S, - ReqBody = ContextualPayload, - ResBody = OB, - Future = F - >, - S: Service< - Error = E, - ReqBody = ContextualPayload, - ResBody = OB> + 'static, - ME: swagger::ErrorBound, - E: swagger::ErrorBound, - F: Future + Send + 'static, - S::Future: Send, - OB: Payload, + T: Service + Send, + T::Future: Send + 'static { - type ReqBody = hyper::Body; - type ResBody = OB; - type Error = E; - type MakeError = ME; - type Service = AddContext; - type Future = Box + Send + 'static>; + type Error = T::Error; + type Response = AddContext; + type Future = BoxFuture<'static, Result>; - fn make_service(&mut self, ctx: &'a SC) -> Self::Future { - Box::new(self.inner.make_service(ctx).map(|s| AddContext::new(s))) + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + self.inner.poll_ready(cx) + } + + fn call(&mut self, target: Target) -> Self::Future { + let service = self.inner.call(target); + + Box::pin(async move { + Ok(AddContext::new(service.await?)) + }) } } -/// Middleware to extract authentication data from request -pub struct AddContext { +/// Middleware to add context data from the request +pub struct AddContext +where + A: Default + Push, + B: Push, Result = C>, + C: Push, Result = D> +{ inner: T, marker: PhantomData, } -impl AddContext +impl AddContext where A: Default + Push, B: Push, Result = C>, C: Push, Result = D>, - T: Service, { - pub fn new(inner: T) -> AddContext { + pub fn new(inner: T) -> Self { AddContext { inner, marker: PhantomData, @@ -90,33 +83,31 @@ where } } -impl Service for AddContext +impl Service> for AddContext where A: Default + Push, B: Push, Result=C>, C: Push, Result=D>, D: Send + 'static, - T: Service>, - T::Future: Future, Error=T::Error> + Send + 'static + T: Service<(Request, D)> { - type ReqBody = hyper::Body; - type ResBody = T::ResBody; type Error = T::Error; - type Future = Box, Error=T::Error> + Send + 'static>; + type Future = T::Future; + type Response = T::Response; - fn call(&mut self, req: Request) -> Self::Future { - let context = A::default().push(XSpanIdString::get_or_generate(&req)); - let (head, body) = req.into_parts(); - let headers = head.headers.clone(); + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + self.inner.poll_ready(cx) + } + + + fn call(&mut self, request: Request) -> Self::Future { + let context = A::default().push(XSpanIdString::get_or_generate(&request)); + let headers = request.headers(); let context = context.push(None::); let context = context.push(None::); - let body = ContextualPayload { - inner: body, - context: context, - }; - Box::new(self.inner.call(hyper::Request::from_parts(head, body))) + self.inner.call((request, context)) } } diff --git a/samples/server/petstore/rust-server/output/rust-server-test/src/lib.rs b/samples/server/petstore/rust-server/output/rust-server-test/src/lib.rs index b8553112ae5..d7928600363 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/src/lib.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/src/lib.rs @@ -1,12 +1,12 @@ #![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)] +use async_trait::async_trait; use futures::Stream; -use std::io::Error; +use std::error::Error; +use std::task::{Poll, Context}; +use swagger::{ApiError, ContextWrapper}; -#[deprecated(note = "Import swagger-rs directly")] -pub use swagger::{ApiError, ContextWrapper}; -#[deprecated(note = "Import futures directly")] -pub use futures::Future; +type ServiceError = Box; pub const BASE_PATH: &'static str = ""; pub const API_VERSION: &'static str = "2.3.4"; @@ -71,190 +71,221 @@ pub enum SoloObjectPostResponse { } /// API -pub trait Api { - fn all_of_get( +#[async_trait] +pub trait Api { + fn poll_ready(&self, _cx: &mut Context) -> Poll>> { + Poll::Ready(Ok(())) + } + + async fn all_of_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; /// A dummy endpoint to make the spec valid. - fn dummy_get( + async fn dummy_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn dummy_put( + async fn dummy_put( &self, nested_response: models::InlineObject, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Get a file - fn file_response_get( + async fn file_response_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn get_structured_yaml( + async fn get_structured_yaml( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Test HTML handling - fn html_post( + async fn html_post( &self, body: String, - context: &C) -> Box + Send>; + context: &C) -> Result; - fn post_yaml( + async fn post_yaml( &self, value: String, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Get an arbitrary JSON blob. - fn raw_json_get( + async fn raw_json_get( &self, - context: &C) -> Box + Send>; + context: &C) -> Result; /// Send an arbitrary JSON blob - fn solo_object_post( + async fn solo_object_post( &self, value: serde_json::Value, - context: &C) -> Box + Send>; + context: &C) -> Result; } -/// API without a `Context` -pub trait ApiNoContext { - fn all_of_get( +/// API where `Context` isn't passed on every API call +#[async_trait] +pub trait ApiNoContext { + + fn poll_ready(&self, _cx: &mut Context) -> Poll>>; + + fn context(&self) -> &C; + + async fn all_of_get( &self, - ) -> Box + Send>; + ) -> Result; /// A dummy endpoint to make the spec valid. - fn dummy_get( + async fn dummy_get( &self, - ) -> Box + Send>; + ) -> Result; - fn dummy_put( + async fn dummy_put( &self, nested_response: models::InlineObject, - ) -> Box + Send>; + ) -> Result; /// Get a file - fn file_response_get( + async fn file_response_get( &self, - ) -> Box + Send>; + ) -> Result; - fn get_structured_yaml( + async fn get_structured_yaml( &self, - ) -> Box + Send>; + ) -> Result; /// Test HTML handling - fn html_post( + async fn html_post( &self, body: String, - ) -> Box + Send>; + ) -> Result; - fn post_yaml( + async fn post_yaml( &self, value: String, - ) -> Box + Send>; + ) -> Result; /// Get an arbitrary JSON blob. - fn raw_json_get( + async fn raw_json_get( &self, - ) -> Box + Send>; + ) -> Result; /// Send an arbitrary JSON blob - fn solo_object_post( + async fn solo_object_post( &self, value: serde_json::Value, - ) -> Box + Send>; + ) -> Result; } /// Trait to extend an API to make it easy to bind it to a context. -pub trait ContextWrapperExt<'a, C> where Self: Sized { +pub trait ContextWrapperExt where Self: Sized +{ /// Binds this API to a context. - fn with_context(self: &'a Self, context: C) -> ContextWrapper<'a, Self, C>; + fn with_context(self: Self, context: C) -> ContextWrapper; } -impl<'a, T: Api + Sized, C> ContextWrapperExt<'a, C> for T { - fn with_context(self: &'a T, context: C) -> ContextWrapper<'a, T, C> { +impl + Send + Sync, C: Clone + Send + Sync> ContextWrapperExt for T { + fn with_context(self: T, context: C) -> ContextWrapper { ContextWrapper::::new(self, context) } } -impl<'a, T: Api, C> ApiNoContext for ContextWrapper<'a, T, C> { - fn all_of_get( +#[async_trait] +impl + Send + Sync, C: Clone + Send + Sync> ApiNoContext for ContextWrapper { + fn poll_ready(&self, cx: &mut Context) -> Poll> { + self.api().poll_ready(cx) + } + + fn context(&self) -> &C { + ContextWrapper::context(self) + } + + async fn all_of_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().all_of_get(&self.context()) + let context = self.context().clone(); + self.api().all_of_get(&context).await } /// A dummy endpoint to make the spec valid. - fn dummy_get( + async fn dummy_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().dummy_get(&self.context()) + let context = self.context().clone(); + self.api().dummy_get(&context).await } - fn dummy_put( + async fn dummy_put( &self, nested_response: models::InlineObject, - ) -> Box + Send> + ) -> Result { - self.api().dummy_put(nested_response, &self.context()) + let context = self.context().clone(); + self.api().dummy_put(nested_response, &context).await } /// Get a file - fn file_response_get( + async fn file_response_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().file_response_get(&self.context()) + let context = self.context().clone(); + self.api().file_response_get(&context).await } - fn get_structured_yaml( + async fn get_structured_yaml( &self, - ) -> Box + Send> + ) -> Result { - self.api().get_structured_yaml(&self.context()) + let context = self.context().clone(); + self.api().get_structured_yaml(&context).await } /// Test HTML handling - fn html_post( + async fn html_post( &self, body: String, - ) -> Box + Send> + ) -> Result { - self.api().html_post(body, &self.context()) + let context = self.context().clone(); + self.api().html_post(body, &context).await } - fn post_yaml( + async fn post_yaml( &self, value: String, - ) -> Box + Send> + ) -> Result { - self.api().post_yaml(value, &self.context()) + let context = self.context().clone(); + self.api().post_yaml(value, &context).await } /// Get an arbitrary JSON blob. - fn raw_json_get( + async fn raw_json_get( &self, - ) -> Box + Send> + ) -> Result { - self.api().raw_json_get(&self.context()) + let context = self.context().clone(); + self.api().raw_json_get(&context).await } /// Send an arbitrary JSON blob - fn solo_object_post( + async fn solo_object_post( &self, value: serde_json::Value, - ) -> Box + Send> + ) -> Result { - self.api().solo_object_post(value, &self.context()) + let context = self.context().clone(); + self.api().solo_object_post(value, &context).await } } + #[cfg(feature = "client")] pub mod client; diff --git a/samples/server/petstore/rust-server/output/rust-server-test/src/server/mod.rs b/samples/server/petstore/rust-server/output/rust-server-test/src/server/mod.rs index 69fd7709b91..7f9e845c9a3 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/src/server/mod.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/src/server/mod.rs @@ -1,20 +1,17 @@ -use std::marker::PhantomData; -use futures::{Future, future, Stream, stream}; -use hyper; -use hyper::{Request, Response, Error, StatusCode, Body, HeaderMap}; +use futures::{future, future::BoxFuture, Stream, stream, future::FutureExt, stream::TryStreamExt}; +use hyper::{Request, Response, StatusCode, Body, HeaderMap}; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; use log::warn; -use serde_json; #[allow(unused_imports)] use std::convert::{TryFrom, TryInto}; -use std::io; -use url::form_urlencoded; -#[allow(unused_imports)] -use swagger; -use swagger::{ApiError, XSpanIdString, Has, RequestParser}; +use std::error::Error; +use std::future::Future; +use std::marker::PhantomData; +use std::task::{Context, Poll}; +use swagger::{ApiError, BodyExt, Has, RequestParser, XSpanIdString}; pub use swagger::auth::Authorization; use swagger::auth::Scopes; -use swagger::context::ContextualPayload; +use url::form_urlencoded; #[allow(unused_imports)] use crate::models; @@ -22,6 +19,8 @@ use crate::header; pub use crate::context; +type ServiceFuture = BoxFuture<'static, Result, crate::ServiceError>>; + use crate::{Api, AllOfGetResponse, DummyGetResponse, @@ -60,15 +59,17 @@ mod paths { pub(crate) static ID_SOLO_OBJECT: usize = 7; } -pub struct MakeService { +pub struct MakeService where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static +{ api_impl: T, - marker: PhantomData, + marker: PhantomData, } -impl MakeService -where - T: Api + Clone + Send + 'static, - RC: Has + 'static +impl MakeService where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static { pub fn new(api_impl: T) -> Self { MakeService { @@ -78,44 +79,45 @@ where } } -impl<'a, T, SC, RC> hyper::service::MakeService<&'a SC> for MakeService -where - T: Api + Clone + Send + 'static, - RC: Has + 'static + Send +impl hyper::service::Service for MakeService where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static { - type ReqBody = ContextualPayload; - type ResBody = Body; - type Error = Error; - type Service = Service; - type Future = future::FutureResult; - type MakeError = Error; + type Response = Service; + type Error = crate::ServiceError; + type Future = future::Ready>; - fn make_service(&mut self, _ctx: &'a SC) -> Self::Future { - future::FutureResult::from(Ok(Service::new( + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn call(&mut self, target: Target) -> Self::Future { + futures::future::ok(Service::new( self.api_impl.clone(), - ))) + )) } } -type ServiceFuture = Box, Error = Error> + Send>; - -fn method_not_allowed() -> ServiceFuture { - Box::new(future::ok( +fn method_not_allowed() -> Result, crate::ServiceError> { + Ok( Response::builder().status(StatusCode::METHOD_NOT_ALLOWED) .body(Body::empty()) .expect("Unable to create Method Not Allowed response") - )) + ) } -pub struct Service { +pub struct Service where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static +{ api_impl: T, - marker: PhantomData, + marker: PhantomData, } -impl Service -where - T: Api + Clone + Send + 'static, - RC: Has + 'static { +impl Service where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static +{ pub fn new(api_impl: T) -> Self { Service { api_impl: api_impl, @@ -124,36 +126,48 @@ where } } -impl hyper::service::Service for Service -where +impl Clone for Service where T: Api + Clone + Send + 'static, - C: Has + 'static + Send + C: Has + Send + Sync + 'static { - type ReqBody = ContextualPayload; - type ResBody = Body; - type Error = Error; + fn clone(&self) -> Self { + Service { + api_impl: self.api_impl.clone(), + marker: self.marker.clone(), + } + } +} + +impl hyper::service::Service<(Request, C)> for Service where + T: Api + Clone + Send + Sync + 'static, + C: Has + Send + Sync + 'static +{ + type Response = Response; + type Error = crate::ServiceError; type Future = ServiceFuture; - fn call(&mut self, req: Request) -> Self::Future { - let api_impl = self.api_impl.clone(); - let (parts, body) = req.into_parts(); + fn poll_ready(&mut self, cx: &mut Context) -> Poll> { + self.api_impl.poll_ready(cx) + } + + fn call(&mut self, req: (Request, C)) -> Self::Future { async fn run(mut api_impl: T, req: (Request, C)) -> Result, crate::ServiceError> where + T: Api + Clone + Send + 'static, + C: Has + Send + Sync + 'static + { + let (request, context) = req; + let (parts, body) = request.into_parts(); let (method, uri, headers) = (parts.method, parts.uri, parts.headers); let path = paths::GLOBAL_REGEX_SET.matches(uri.path()); - let mut context = body.context; - let body = body.inner; match &method { // AllOfGet - GET /allOf &hyper::Method::GET if path.matched(paths::ID_ALLOF) => { - Box::new({ - {{ - Box::new( - api_impl.all_of_get( + let result = api_impl.all_of_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -180,23 +194,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // DummyGet - GET /dummy &hyper::Method::GET if path.matched(paths::ID_DUMMY) => { - Box::new({ - {{ - Box::new( - api_impl.dummy_get( + let result = api_impl.dummy_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -216,11 +223,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // DummyPut - PUT /dummy @@ -228,9 +231,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_nested_response: Option = if !body.is_empty() { @@ -240,29 +242,28 @@ where unused_elements.push(path.to_string()); }) { Ok(param_nested_response) => param_nested_response, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse body parameter nested_response - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid body parameter nested_response due to schema"))), + .expect("Unable to create Bad Request response for invalid body parameter nested_response due to schema")), } } else { None }; let param_nested_response = match param_nested_response { Some(param_nested_response) => param_nested_response, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required body parameter nested_response")) - .expect("Unable to create Bad Request response for missing body parameter nested_response"))), + .expect("Unable to create Bad Request response for missing body parameter nested_response")), }; - Box::new( - api_impl.dummy_put( + let result = api_impl.dummy_put( param_nested_response, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -289,29 +290,22 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter nested_response: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter nested_response"))), + .expect("Unable to create Bad Request response due to unable to read body parameter nested_response")), } - }) - ) as Self::Future }, // FileResponseGet - GET /file_response &hyper::Method::GET if path.matched(paths::ID_FILE_RESPONSE) => { - Box::new({ - {{ - Box::new( - api_impl.file_response_get( + let result = api_impl.file_response_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -338,23 +332,16 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // GetStructuredYaml - GET /get-structured-yaml &hyper::Method::GET if path.matched(paths::ID_GET_STRUCTURED_YAML) => { - Box::new({ - {{ - Box::new( - api_impl.get_structured_yaml( + let result = api_impl.get_structured_yaml( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -381,11 +368,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // HtmlPost - POST /html @@ -393,36 +376,34 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let param_body: Option = if !body.is_empty() { match String::from_utf8(body.to_vec()) { Ok(param_body) => Some(param_body), - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse body parameter body - not valid UTF-8: {}", e))) - .expect("Unable to create Bad Request response for invalid body parameter body due to UTF-8"))), + .expect("Unable to create Bad Request response for invalid body parameter body due to UTF-8")), } } else { None }; let param_body = match param_body { Some(param_body) => param_body, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required body parameter body")) - .expect("Unable to create Bad Request response for missing body parameter body"))), + .expect("Unable to create Bad Request response for missing body parameter body")), }; - Box::new( - api_impl.html_post( + let result = api_impl.html_post( param_body, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -449,17 +430,13 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter body: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter body"))), + .expect("Unable to create Bad Request response due to unable to read body parameter body")), } - }) - ) as Self::Future }, // PostYaml - POST /post-yaml @@ -467,36 +444,34 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let param_value: Option = if !body.is_empty() { match String::from_utf8(body.to_vec()) { Ok(param_value) => Some(param_value), - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse body parameter value - not valid UTF-8: {}", e))) - .expect("Unable to create Bad Request response for invalid body parameter value due to UTF-8"))), + .expect("Unable to create Bad Request response for invalid body parameter value due to UTF-8")), } } else { None }; let param_value = match param_value { Some(param_value) => param_value, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required body parameter value")) - .expect("Unable to create Bad Request response for missing body parameter value"))), + .expect("Unable to create Bad Request response for missing body parameter value")), }; - Box::new( - api_impl.post_yaml( + let result = api_impl.post_yaml( param_value, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -516,29 +491,22 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter value: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter value"))), + .expect("Unable to create Bad Request response due to unable to read body parameter value")), } - }) - ) as Self::Future }, // RawJsonGet - GET /raw_json &hyper::Method::GET if path.matched(paths::ID_RAW_JSON) => { - Box::new({ - {{ - Box::new( - api_impl.raw_json_get( + let result = api_impl.raw_json_get( &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -565,11 +533,7 @@ where }, } - future::ok(response) - } - )) - }} - }) as Self::Future + Ok(response) }, // SoloObjectPost - POST /solo-object @@ -577,9 +541,8 @@ where // Body parameters (note that non-required body parameters will ignore garbage // values, rather than causing a 400 response). Produce warning header and logs for // any unused fields. - Box::new(body.concat2() - .then(move |result| -> Self::Future { - match result { + let result = body.to_raw().await; + match result { Ok(body) => { let mut unused_elements = Vec::new(); let param_value: Option = if !body.is_empty() { @@ -589,29 +552,28 @@ where unused_elements.push(path.to_string()); }) { Ok(param_value) => param_value, - Err(e) => return Box::new(future::ok(Response::builder() + Err(e) => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't parse body parameter value - doesn't match schema: {}", e))) - .expect("Unable to create Bad Request response for invalid body parameter value due to schema"))), + .expect("Unable to create Bad Request response for invalid body parameter value due to schema")), } } else { None }; let param_value = match param_value { Some(param_value) => param_value, - None => return Box::new(future::ok(Response::builder() + None => return Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from("Missing required body parameter value")) - .expect("Unable to create Bad Request response for missing body parameter value"))), + .expect("Unable to create Bad Request response for missing body parameter value")), }; - Box::new( - api_impl.solo_object_post( + let result = api_impl.solo_object_post( param_value, &context - ).then(move |result| { - let mut response = Response::new(Body::empty()); - response.headers_mut().insert( + ).await; + let mut response = Response::new(Body::empty()); + response.headers_mut().insert( HeaderName::from_static("x-span-id"), HeaderValue::from_str((&context as &dyn Has).get().0.clone().to_string().as_str()) .expect("Unable to create X-Span-ID header value")); @@ -638,17 +600,13 @@ where }, } - future::ok(response) - } - )) + Ok(response) }, - Err(e) => Box::new(future::ok(Response::builder() + Err(e) => Ok(Response::builder() .status(StatusCode::BAD_REQUEST) .body(Body::from(format!("Couldn't read body parameter value: {}", e))) - .expect("Unable to create Bad Request response due to unable to read body parameter value"))), + .expect("Unable to create Bad Request response due to unable to read body parameter value")), } - }) - ) as Self::Future }, _ if path.matched(paths::ID_ALLOF) => method_not_allowed(), @@ -659,23 +617,11 @@ where _ if path.matched(paths::ID_POST_YAML) => method_not_allowed(), _ if path.matched(paths::ID_RAW_JSON) => method_not_allowed(), _ if path.matched(paths::ID_SOLO_OBJECT) => method_not_allowed(), - _ => Box::new(future::ok( - Response::builder().status(StatusCode::NOT_FOUND) + _ => Ok(Response::builder().status(StatusCode::NOT_FOUND) .body(Body::empty()) - .expect("Unable to create Not Found response") - )) as Self::Future + .expect("Unable to create Not Found response")) } - } -} - -impl Clone for Service where T: Clone -{ - fn clone(&self) -> Self { - Service { - api_impl: self.api_impl.clone(), - marker: self.marker.clone(), - } - } + } Box::pin(run(self.api_impl.clone(), req)) } } /// Request parser for `Api`. From 8480706da1eb92d95b3eff0e57f02a40d21a1bd6 Mon Sep 17 00:00:00 2001 From: Ghufz <18732053+Ghufz@users.noreply.github.com> Date: Fri, 29 May 2020 21:45:38 +0530 Subject: [PATCH 06/62] [PS] Refactor the http signing auth with ecdsa support (#6397) * ValidatePattern having double quote(") throws exception on running Build.ps1 * fix tab with space * [powershell-experimental] : http signature auth * fix the tab issue * merge cnflict fix for powershell experimental * Htpp signing : added support for ecdsa * Update modules/openapi-generator/src/main/resources/powershell/configuration.mustache Co-authored-by: Sebastien Rosset * Update modules/openapi-generator/src/main/resources/powershell/configuration.mustache Co-authored-by: Sebastien Rosset * Update modules/openapi-generator/src/main/resources/powershell/configuration.mustache Co-authored-by: Sebastien Rosset * Update modules/openapi-generator/src/main/resources/powershell/configuration.mustache Co-authored-by: Sebastien Rosset * Update modules/openapi-generator/src/main/resources/powershell/configuration.mustache Co-authored-by: Sebastien Rosset * HttpSigningHeader accepts any header available in request to calculate the signature. * Update modules/openapi-generator/src/main/resources/powershell/http_signature_auth.mustache Co-authored-by: Sebastien Rosset * Incorporated the review comments * addressed the merge conflict Co-authored-by: Ghufran Zahidi Co-authored-by: Sebastien Rosset --- .../resources/powershell/api_client.mustache | 4 +- .../powershell/configuration.mustache | 137 ++++++ .../powershell/http_signature_auth.mustache | 453 ++++++++++++++---- .../powershell/rsa_provider.mustache | 286 ++++------- 4 files changed, 584 insertions(+), 296 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/powershell/api_client.mustache b/modules/openapi-generator/src/main/resources/powershell/api_client.mustache index f98ae6695e6..95b23b26d5f 100644 --- a/modules/openapi-generator/src/main/resources/powershell/api_client.mustache +++ b/modules/openapi-generator/src/main/resources/powershell/api_client.mustache @@ -91,11 +91,13 @@ function Invoke-{{{apiNamePrefix}}}ApiClient { {{#hasHttpSignatureMethods}} # http signature authentication - if ($null -ne $Configuration['ApiKey'] -and $Configuration['ApiKey'].Count -gt 0) { + $httpSigningConfig = Get-{{{apiNamePrefix}}}ConfigurationHttpSigning + if ($null -ne $httpSigningConfig) { $httpSignHeaderArgument = @{ Method = $Method UriBuilder = $UriBuilder Body = $Body + RequestHeader = $HeaderParameters } $signedHeader = Get-{{{apiNamePrefix}}}HttpSignedHeader @httpSignHeaderArgument if($null -ne $signedHeader -and $signedHeader.Count -gt 0){ diff --git a/modules/openapi-generator/src/main/resources/powershell/configuration.mustache b/modules/openapi-generator/src/main/resources/powershell/configuration.mustache index 4d17452be17..622bce2b65a 100644 --- a/modules/openapi-generator/src/main/resources/powershell/configuration.mustache +++ b/modules/openapi-generator/src/main/resources/powershell/configuration.mustache @@ -372,3 +372,140 @@ function Get-{{apiNamePrefix}}UrlFromHostSetting { } } + +<# +.SYNOPSIS +Sets the configuration for http signing. +.DESCRIPTION + +Sets the configuration for the HTTP signature security scheme. +The HTTP signature security scheme is used to sign HTTP requests with a key +which is in possession of the API client. +An 'Authorization' header is calculated by creating a hash of select headers, +and optionally the body of the HTTP request, then signing the hash value using +a key. The 'Authorization' header is added to outbound HTTP requests. + +Ref: https://openapi-generator.tech + +.PARAMETER KeyId +KeyId for HTTP signing + +.PARAMETER KeyFilePath +KeyFilePath for HTTP signing + +.PARAMETER KeyPassPhrase +KeyPassPhrase, if the HTTP signing key is protected + +.PARAMETER HttpSigningHeader +HttpSigningHeader list of HTTP headers used to calculate the signature. The two special signature headers '(request-target)' and '(created)' +SHOULD be included. + The '(created)' header expresses when the signature was created. + The '(request-target)' header is a concatenation of the lowercased :method, an + ASCII space, and the :path pseudo-headers. +If no headers are specified then '(created)' sets as default. + +.PARAMETER HashAlgorithm +HashAlgrithm to calculate the hash, Supported values are "sha256" and "sha512" + +.PARAMETER SigningAlgorithm +SigningAlgorithm specifies the signature algorithm, supported values are "RSASSA-PKCS1-v1_5" and "RSASSA-PSS" +RSA key : Supported values "RSASSA-PKCS1-v1_5" and "RSASSA-PSS", for ECDSA key this parameter is not applicable + +.PARAMETER SignatureValidityPeriod +SignatureValidityPeriod specifies the signature maximum validity time in seconds. It accepts integer value + +.OUTPUTS + +System.Collections.Hashtable +#> +function Set-{{{apiNamePrefix}}}ConfigurationHttpSigning { + [CmdletBinding()] + param( + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [string]$KeyId, + [Parameter(Mandatory = $true)] + [string]$KeyFilePath, + [Parameter(Mandatory = $false)] + [securestring]$KeyPassPhrase, + [Parameter(Mandatory = $false)] + [ValidateNotNullOrEmpty()] + [string[]] $HttpSigningHeader = @("(created)"), + [Parameter(Mandatory = $false)] + [ValidateSet("sha256", "sha512")] + [string] $HashAlgorithm = "sha256", + [Parameter(Mandatory = $false)] + [ValidateSet("RSASSA-PKCS1-v1_5", "RSASSA-PSS")] + [string]$SigningAlgorithm , + [Parameter(Mandatory = $false)] + [int]$SignatureValidityPeriod + ) + + Process { + $httpSignatureConfiguration = @{ } + + if (Test-Path -Path $KeyFilePath) { + $httpSignatureConfiguration["KeyId"] = $KeyId + $httpSignatureConfiguration["KeyFilePath"] = $KeyFilePath + } + else { + throw "Private key file path does not exist" + } + + $keyType = Get-{{{apiNamePrefix}}}KeyTypeFromFile -KeyFilePath $KeyFilePath + if ([String]::IsNullOrEmpty($SigningAlgorithm)) { + if ($keyType -eq "RSA") { + $SigningAlgorithm = "RSASSA-PKCS1-v1_5" + } + } + + if ($keyType -eq "RSA" -and + ($SigningAlgorithm -ne "RSASSA-PKCS1-v1_5" -and $SigningAlgorithm -ne "RSASSA-PSS" )) { + throw "Provided Key and SigningAlgorithm : $SigningAlgorithm is not compatible." + } + + if ($HttpSigningHeader -contains "(expires)" -and $SignatureValidityPeriod -le 0) { + throw "SignatureValidityPeriod must be greater than 0 seconds." + } + + if ($HttpSigningHeader -contains "(expires)") { + $httpSignatureConfiguration["SignatureValidityPeriod"] = $SignatureValidityPeriod + } + if ($null -ne $HttpSigningHeader -and $HttpSigningHeader.Length -gt 0) { + $httpSignatureConfiguration["HttpSigningHeader"] = $HttpSigningHeader + } + + if ($null -ne $HashAlgorithm ) { + $httpSignatureConfiguration["HashAlgorithm"] = $HashAlgorithm + } + + if ($null -ne $SigningAlgorithm) { + $httpSignatureConfiguration["SigningAlgorithm"] = $SigningAlgorithm + } + + if ($null -ne $KeyPassPhrase) { + $httpSignatureConfiguration["KeyPassPhrase"] = $KeyPassPhrase + } + + $Script:Configuration["HttpSigning"] = New-Object -TypeName PSCustomObject -Property $httpSignatureConfiguration + } +} + +<# +.SYNOPSIS + +Get the configuration object '{{{apiNamePrefix}}}ConfigurationHttpSigning'. + +.DESCRIPTION + +Get the configuration object '{{{apiNamePrefix}}}ConfigurationHttpSigning'. + +.OUTPUTS + +[PSCustomObject] +#> +function Get-{{{apiNamePrefix}}}ConfigurationHttpSigning{ + + $httpSignatureConfiguration = $Script:Configuration["HttpSigning"] + return $httpSignatureConfiguration +} diff --git a/modules/openapi-generator/src/main/resources/powershell/http_signature_auth.mustache b/modules/openapi-generator/src/main/resources/powershell/http_signature_auth.mustache index aeb74be678d..69ab0b43bb1 100644 --- a/modules/openapi-generator/src/main/resources/powershell/http_signature_auth.mustache +++ b/modules/openapi-generator/src/main/resources/powershell/http_signature_auth.mustache @@ -1,64 +1,11 @@ {{>partial_header}} <# .SYNOPSIS -Get the API key Id and API key file path. - + Gets the headers for HTTP signature. .DESCRIPTION -Get the API key Id and API key file path. If no api prefix is provided then it use default api key prefix 'Signature' -.OUTPUTS -PSCustomObject : This contains APIKeyId, APIKeyFilePath, APIKeyPrefix -#> -function Get-{{{apiNamePrefix}}}APIKeyInfo { - $ApiKeysList = $Script:Configuration['ApiKey'] - $ApiKeyPrefixList = $Script:Configuration['ApiKeyPrefix'] - $apiPrefix = "Signature" - - if ($null -eq $ApiKeysList -or $ApiKeysList.Count -eq 0) { - throw "Unable to reterieve the api key details" - } - - if ($null -eq $ApiKeyPrefixList -or $ApiKeyPrefixList.Count -eq 0) { - Write-Verbose "Unable to reterieve the api key prefix details,setting it to default ""Signature""" - } - - foreach ($item in $ApiKeysList.GetEnumerator()) { - if (![string]::IsNullOrEmpty($item.Name)) { - if (Test-Path -Path $item.Value) { - $apiKey = $item.Value - $apikeyId = $item.Name - break; - } - else { - throw "API key file path does not exist." - } - } - } - - if ($ApiKeyPrefixList.ContainsKey($apikeyId)) { - $apiPrefix = ApiKeyPrefixList[$apikeyId] - } - - if ($apikeyId -and $apiKey -and $apiPrefix) { - $result = New-Object -Type PSCustomObject -Property @{ - ApiKeyId = $apikeyId; - ApiKeyFilePath = $apiKey - ApiKeyPrefix = $apiPrefix - } - } - else { - return $null - } - return $result -} - -<# -.SYNOPSIS - Gets the headers for http signed auth. - -.DESCRIPTION - Gets the headers for the http signed auth. It use (targetpath), date, host and body digest to create authorization header. + Gets the headers for the http sigature. .PARAMETER Method - Http method + HTTP method .PARAMETER UriBuilder UriBuilder for url and query parameter .PARAMETER Body @@ -70,93 +17,393 @@ function Get-{{{apiNamePrefix}}}HttpSignedHeader { param( [string]$Method, [System.UriBuilder]$UriBuilder, - [string]$Body + [string]$Body, + [hashtable]$RequestHeader ) + $HEADER_REQUEST_TARGET = '(request-target)' + # The time when the HTTP signature was generated. + $HEADER_CREATED = '(created)' + # The time when the HTTP signature expires. The API server should reject HTTP requests + # that have expired. + $HEADER_EXPIRES = '(expires)' + # The 'Host' header. + $HEADER_HOST = 'Host' + # The 'Date' header. + $HEADER_DATE = 'Date' + # When the 'Digest' header is included in the HTTP signature, the client automatically + # computes the digest of the HTTP request body, per RFC 3230. + $HEADER_DIGEST = 'Digest' + # The 'Authorization' header is automatically generated by the client. It includes + # the list of signed headers and a base64-encoded signature. + $HEADER_AUTHORIZATION = 'Authorization' + #Hash table to store singed headers - $HttpSignedHeader = @{} + $HttpSignedRequestHeader = @{ } + $HttpSignatureHeader = @{ } $TargetHost = $UriBuilder.Host - - #Check for Authentication type - $apiKeyInfo = Get-{{{apiNamePrefix}}}APIKeyInfo - if ($null -eq $apiKeyInfo) { - throw "Unable to reterieve the api key info " - } - + $httpSigningConfiguration = Get-{{{apiNamePrefix}}}ConfigurationHttpSigning + $Digest = $null + #get the body digest - $bodyHash = Get-{{{apiNamePrefix}}}StringHash -String $Body - $Digest = [String]::Format("SHA-256={0}", [Convert]::ToBase64String($bodyHash)) - - #get the date in UTC + $bodyHash = Get-{{{apiNamePrefix}}}StringHash -String $Body -HashName $httpSigningConfiguration.HashAlgorithm + if ($httpSigningConfiguration.HashAlgorithm -eq "SHA256") { + $Digest = [String]::Format("SHA-256={0}", [Convert]::ToBase64String($bodyHash)) + } + elseif ($httpSigningConfiguration.HashAlgorithm -eq "SHA512") { + $Digest = [String]::Format("SHA-512={0}", [Convert]::ToBase64String($bodyHash)) + } + $dateTime = Get-Date + #get the date in UTC $currentDate = $dateTime.ToUniversalTime().ToString("r") - $requestTargetPath = [string]::Format("{0} {1}{2}",$Method.ToLower(),$UriBuilder.Path.ToLower(),$UriBuilder.Query) - $h_requestTarget = [string]::Format("(request-target): {0}",$requestTargetPath) - $h_cdate = [string]::Format("date: {0}",$currentDate) - $h_digest = [string]::Format("digest: {0}",$Digest) - $h_targetHost = [string]::Format("host: {0}",$TargetHost) + foreach ($headerItem in $httpSigningConfiguration.HttpSigningHeader) { + + if ($headerItem -eq $HEADER_REQUEST_TARGET) { + $requestTargetPath = [string]::Format("{0} {1}{2}", $Method.ToLower(), $UriBuilder.Path, $UriBuilder.Query) + $HttpSignatureHeader.Add($HEADER_REQUEST_TARGET, $requestTargetPath) + } + elseif ($headerItem -eq $HEADER_CREATED) { + $created = Get-{{{apiNamePrefix}}}UnixTime -Date $dateTime -TotalTime TotalSeconds + $HttpSignatureHeader.Add($HEADER_CREATED, $created) + } + elseif ($headerItem -eq $HEADER_EXPIRES) { + $expire = $dateTime.AddSeconds($httpSigningConfiguration.SignatureValidityPeriod) + $expireEpocTime = Get-{{{apiNamePrefix}}}UnixTime -Date $expire -TotalTime TotalSeconds + $HttpSignatureHeader.Add($HEADER_EXPIRES, $expireEpocTime) + } + elseif ($headerItem -eq $HEADER_HOST) { + $HttpSignedRequestHeader[$HEADER_HOST] = $TargetHost + $HttpSignatureHeader.Add($HEADER_HOST.ToLower(), $TargetHost) + } + elseif ($headerItem -eq $HEADER_DATE) { + $HttpSignedRequestHeader[$HEADER_DATE] = $currentDate + $HttpSignatureHeader.Add($HEADER_DATE.ToLower(), $currentDate) + } + elseif ($headerItem -eq $HEADER_DIGEST) { + $HttpSignedRequestHeader[$HEADER_DIGEST] = $Digest + $HttpSignatureHeader.Add($HEADER_DIGEST.ToLower(), $Digest) + }elseif($RequestHeader.ContainsKey($headerItem)){ + $HttpSignatureHeader.Add($headerItem.ToLower(), $RequestHeader[$headerItem]) + }else{ + throw "Cannot sign HTTP request. Request does not contain the $headerItem header." + } + } - $stringToSign = [String]::Format("{0}`n{1}`n{2}`n{3}", - $h_requestTarget,$h_cdate, - $h_targetHost,$h_digest) + # header's name separated by space + $headersKeysString = $HttpSignatureHeader.Keys -join " " + $headerValuesList = @() + foreach ($item in $HttpSignatureHeader.GetEnumerator()) { + $headerValuesList += [string]::Format("{0}: {1}", $item.Name, $item.Value) + } + #Concatinate headers value separated by new line + $headerValuesString = $headerValuesList -join "`n" - $hashedString = Get-{{{apiNamePrefix}}}StringHash -String $stringToSign - $signedHeader = Get-{{{apiNamePrefix}}}RSASHA256SignedString -APIKeyFilePath $apiKeyInfo.ApiKeyFilePath -DataToSign $hashedString - $authorizationHeader = [string]::Format("{0} keyId=""{1}"",algorithm=""rsa-sha256"",headers=""(request-target) date host digest"",signature=""{2}""", - $apiKeyInfo.ApiKeyPrefix, $apiKeyInfo.ApiKeyId, $signedHeader) + #Gets the hash of the headers value + $signatureHashString = Get-{{{apiNamePrefix}}}StringHash -String $headerValuesString -HashName $httpSigningConfiguration.HashAlgorithm + + #Gets the Key type to select the correct signing alogorithm + $KeyType = Get-{{{apiNamePrefix}}}KeyTypeFromFile -KeyFilePath $httpSigningConfiguration.KeyFilePath + + if ($keyType -eq "RSA") { + $headerSignatureStr = Get-{{{apiNamePrefix}}}RSASignature -PrivateKeyFilePath $httpSigningConfiguration.KeyFilePath ` + -DataToSign $signatureHashString ` + -HashAlgorithmName $httpSigningConfiguration.HashAlgorithm ` + -KeyPassPhrase $httpSigningConfiguration.KeyPassPhrase ` + -SigningAlgorithm $httpSigningConfiguration.SigningAlgorithm + } + elseif ($KeyType -eq "EC") { + $headerSignatureStr = Get-{{{apiNamePrefix}}}ECDSASignature -ECKeyFilePath $httpSigningConfiguration.KeyFilePath ` + -DataToSign $signatureHashString ` + -HashAlgorithmName $httpSigningConfiguration.HashAlgorithm ` + -KeyPassPhrase $httpSigningConfiguration.KeyPassPhrase + } + #Depricated + <#$cryptographicScheme = Get-{{{apiNamePrefix}}}CryptographicScheme -SigningAlgorithm $httpSigningConfiguration.SigningAlgorithm ` + -HashAlgorithm $httpSigningConfiguration.HashAlgorithm + #> + $cryptographicScheme = "hs2019" + $authorizationHeaderValue = [string]::Format("Signature keyId=""{0}"",algorithm=""{1}""", + $httpSigningConfiguration.KeyId, $cryptographicScheme) + + if ($HttpSignatureHeader.ContainsKey($HEADER_CREATED)) { + $authorizationHeaderValue += [string]::Format(",created={0}", $HttpSignatureHeader[$HEADER_CREATED]) + } + + if ($HttpSignatureHeader.ContainsKey($HEADER_EXPIRES)) { + $authorizationHeaderValue += [string]::Format(",expires={0}", $HttpSignatureHeader[$HEADER_EXPIRES]) + } - $HttpSignedHeader["Date"] = $currentDate - $HttpSignedHeader["Host"] = $TargetHost - $HttpSignedHeader["Content-Type"] = "application/json" - $HttpSignedHeader["Digest"] = $Digest - $HttpSignedHeader["Authorization"] = $authorizationHeader - return $HttpSignedHeader + $authorizationHeaderValue += [string]::Format(",headers=""{0}"",signature=""{1}""", + $headersKeysString , $headerSignatureStr) + + $HttpSignedRequestHeader[$HEADER_AUTHORIZATION] = $authorizationHeaderValue + return $HttpSignedRequestHeader } <# .SYNOPSIS - Gets the headers for http signed auth. + Gets the RSA signature .DESCRIPTION - Gets the headers for the http signed auth. It use (targetpath), date, host and body digest to create authorization header. -.PARAMETER APIKeyFilePath + Gets the RSA signature for the http signing +.PARAMETER PrivateKeyFilePath Specify the API key file path .PARAMETER DataToSign Specify the data to sign +.PARAMETER HashAlgorithmName + HashAlgorithm to calculate the hash +.PARAMETER KeyPassPhrase + KeyPassPhrase for the encrypted key .OUTPUTS - String + Base64String #> -function Get-{{{apiNamePrefix}}}RSASHA256SignedString { +function Get-{{{apiNamePrefix}}}RSASignature { Param( - [string]$APIKeyFilePath, - [byte[]]$DataToSign + [string]$PrivateKeyFilePath, + [byte[]]$DataToSign, + [string]$HashAlgorithmName, + [string]$SigningAlgorithm, + [securestring]$KeyPassPhrase ) try { - $rsa_provider_path = Join-Path -Path $PSScriptRoot -ChildPath "{{{apiNamePrefix}}}RSAEncryptionProvider.cs" - $rsa_provider_sourceCode = Get-Content -Path $rsa_provider_path -Raw - Add-Type -TypeDefinition $rsa_provider_sourceCode - $signed_string = [RSAEncryption.RSAEncryptionProvider]::GetRSASignb64encode($APIKeyFilePath, $DataToSign) - if ($null -eq $signed_string) { - throw "Unable to sign the header using the API key" + if ($hashAlgorithmName -eq "sha256") { + $hashAlgo = [System.Security.Cryptography.HashAlgorithmName]::SHA256 } - return $signed_string + elseif ($hashAlgorithmName -eq "sha512") { + $hashAlgo = [System.Security.Cryptography.HashAlgorithmName]::SHA512 + } + + if ($PSVersionTable.PSVersion.Major -ge 7) { + $ecKeyHeader = "-----BEGIN RSA PRIVATE KEY-----" + $ecKeyFooter = "-----END RSA PRIVATE KEY-----" + $keyStr = Get-Content -Path $PrivateKeyFilePath -Raw + $ecKeyBase64String = $keyStr.Replace($ecKeyHeader, "").Replace($ecKeyFooter, "").Trim() + $keyBytes = [System.Convert]::FromBase64String($ecKeyBase64String) + $rsa = [System.Security.Cryptography.RSACng]::new() + [int]$bytCount = 0 + $rsa.ImportRSAPrivateKey($keyBytes, [ref] $bytCount) + + if ($SigningAlgorithm -eq "RSASSA-PSS") { + $signedBytes = $rsa.SignHash($DataToSign, $hashAlgo, [System.Security.Cryptography.RSASignaturePadding]::Pss) + } + else { + $signedBytes = $rsa.SignHash($DataToSign, $hashAlgo, [System.Security.Cryptography.RSASignaturePadding]::Pkcs1) + } + } + else { + $rsa_provider_path = Join-Path -Path $PSScriptRoot -ChildPath "{{{apiNamePrefix}}}RSAEncryptionProvider.cs" + $rsa_provider_sourceCode = Get-Content -Path $rsa_provider_path -Raw + Add-Type -TypeDefinition $rsa_provider_sourceCode + + [System.Security.Cryptography.RSA]$rsa = [RSAEncryption.RSAEncryptionProvider]::GetRSAProviderFromPemFile($PrivateKeyFilePath, $KeyPassPhrase) + + if ($SigningAlgorithm -eq "RSASSA-PSS") { + throw "$SigningAlgorithm is not supported on $($PSVersionTable.PSVersion)" + } + else { + $signedBytes = $rsa.SignHash($DataToSign, $hashAlgo, [System.Security.Cryptography.RSASignaturePadding]::Pkcs1) + } + + } + + $signedString = [Convert]::ToBase64String($signedBytes) + return $signedString } catch { throw $_ } } + +<# +.SYNOPSIS + Gets the ECDSA signature + +.DESCRIPTION + Gets the ECDSA signature for the http signing +.PARAMETER PrivateKeyFilePath + Specify the API key file path +.PARAMETER DataToSign + Specify the data to sign +.PARAMETER HashAlgorithmName + HashAlgorithm to calculate the hash +.PARAMETER KeyPassPhrase + KeyPassPhrase for the encrypted key +.OUTPUTS + Base64String +#> +function Get-{{{apiNamePrefix}}}ECDSASignature { + param( + [Parameter(Mandatory = $true)] + [string]$ECKeyFilePath, + [Parameter(Mandatory = $true)] + [byte[]]$DataToSign, + [Parameter(Mandatory = $false)] + [String]$HashAlgorithmName, + [Parameter(Mandatory = $false)] + [securestring]$KeyPassPhrase + ) + if (!(Test-Path -Path $ECKeyFilePath)) { + throw "key file path does not exist." + } + + if($PSVersionTable.PSVersion.Major -lt 7){ + throw "ECDSA key is not supported on $($PSVersionTable.PSVersion), Use PSVersion 7.0 and above" + } + + $ecKeyHeader = "-----BEGIN EC PRIVATE KEY-----" + $ecKeyFooter = "-----END EC PRIVATE KEY-----" + $keyStr = Get-Content -Path $ECKeyFilePath -Raw + $ecKeyBase64String = $keyStr.Replace($ecKeyHeader, "").Replace($ecKeyFooter, "").Trim() + $keyBytes = [System.Convert]::FromBase64String($ecKeyBase64String) + + #$cngKey = [System.Security.Cryptography.CngKey]::Import($keyBytes,[System.Security.Cryptography.CngKeyBlobFormat]::Pkcs8PrivateBlob) + #$ecdsa = [System.Security.Cryptography.ECDsaCng]::New($cngKey) + $ecdsa = [System.Security.Cryptography.ECDsaCng]::New() + [int]$bytCount =0 + if(![string]::IsNullOrEmpty($KeyPassPhrase)){ + $ecdsa.ImportEncryptedPkcs8PrivateKey($KeyPassPhrase,$keyBytes,[ref]$bytCount) + } + else{ + $ecdsa.ImportPkcs8PrivateKey($keyBytes,[ref]$bytCount) + } + + if ($HashAlgorithmName -eq "sha512") { + $ecdsa.HashAlgorithm = [System.Security.Cryptography.CngAlgorithm]::Sha512 + } + else { + $ecdsa.HashAlgorithm = [System.Security.Cryptography.CngAlgorithm]::Sha256 + } + + $signedBytes = $ecdsa.SignHash($DataToSign) + $signedString = [System.Convert]::ToBase64String($signedBytes) + return $signedString + +} + + <# .Synopsis Gets the hash of string. .Description Gets the hash of string +.Parameter String + Specifies the string to calculate the hash +.Parameter HashName + Specifies the hash name to calculate the hash, Accepted values are "SHA1", "SHA256" and "SHA512" + It is recommneded not to use "SHA1" to calculate the Hash .Outputs String #> -Function Get-{{{apiNamePrefix}}}StringHash([String] $String, $HashName = "SHA256") { - +Function Get-{{{apiNamePrefix}}}StringHash { + param( + [Parameter(Mandatory = $true)] + [AllowEmptyString()] + [string]$String, + [Parameter(Mandatory = $true)] + [ValidateSet("SHA1", "SHA256", "SHA512")] + $HashName + ) $hashAlogrithm = [System.Security.Cryptography.HashAlgorithm]::Create($HashName) $hashAlogrithm.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($String)) +} + +<# +.Synopsis + Gets the Unix time. +.Description + Gets the Unix time +.Parameter Date + Specifies the date to calculate the unix time +.Parameter ToTalTime + Specifies the total time , Accepted values are "TotalDays", "TotalHours", "TotalMinutes", "TotalSeconds" and "TotalMilliseconds" +.Outputs +Integer +#> +function Get-{{{apiNamePrefix}}}UnixTime { + param( + [Parameter(Mandatory = $true)] + [DateTime]$Date, + [Parameter(Mandatory = $false)] + [ValidateSet("TotalDays", "TotalHours", "TotalMinutes", "TotalSeconds", "TotalMilliseconds")] + [string]$TotalTime = "TotalSeconds" + ) + $date1 = Get-Date -Date "01/01/1970" + $timespan = New-TimeSpan -Start $date1 -End $Date + switch ($TotalTime) { + "TotalDays" { [int]$timespan.TotalDays } + "TotalHours" { [int]$timespan.TotalHours } + "TotalMinutes" { [int]$timespan.TotalMinutes } + "TotalSeconds" { [int]$timespan.TotalSeconds } + "TotalMilliseconds" { [int]$timespan.TotalMilliseconds } + } +} + +function Get-{{{apiNamePrefix}}}CryptographicScheme { + param( + [Parameter(Mandatory = $true)] + [string]$SigningAlgorithm, + [Parameter(Mandatory = $true)] + [string]$HashAlgorithm + ) + $rsaSigntureType = @("RSASSA-PKCS1-v1_5", "RSASSA-PSS") + $SigningAlgorithm = $null + if ($rsaSigntureType -contains $SigningAlgorithm) { + switch ($HashAlgorithm) { + "sha256" { $SigningAlgorithm = "rsa-sha256" } + "sha512" { $SigningAlgorithm = "rsa-sha512" } + } + } + return $SigningAlgorithm +} + + +<# +.Synopsis + Gets the key type from the pem file. +.Description + Gets the key type from the pem file. +.Parameter KeyFilePath + Specifies the key file path (pem file) +.Outputs +String +#> +function Get-{{{apiNamePrefix}}}KeyTypeFromFile { + param( + [Parameter(Mandatory = $true)] + [string]$KeyFilePath + ) + + if (-not(Test-Path -Path $KeyFilePath)) { + throw "Key file path does not exist." + } + $ecPrivateKeyHeader = "BEGIN EC PRIVATE KEY" + $ecPrivateKeyFooter = "END EC PRIVATE KEY" + $rsaPrivateKeyHeader = "BEGIN RSA PRIVATE KEY" + $rsaPrivateFooter = "END RSA PRIVATE KEY" + $pkcs8Header = "BEGIN PRIVATE KEY" + $pkcs8Footer = "END PRIVATE KEY" + $keyType = $null + $key = Get-Content -Path $KeyFilePath + + if ($key[0] -match $rsaPrivateKeyHeader -and $key[$key.Length - 1] -match $rsaPrivateFooter) { + $KeyType = "RSA" + + } + elseif ($key[0] -match $ecPrivateKeyHeader -and $key[$key.Length - 1] -match $ecPrivateKeyFooter) { + $keyType = "EC" + } + elseif ($key[0] -match $ecPrivateKeyHeader -and $key[$key.Length - 1] -match $ecPrivateKeyFooter) { + <#this type of key can hold many type different types of private key, but here due lack of pem header + Considering this as EC key + #> + #TODO :- update the key based on oid + $keyType = "EC" + } + else { + throw "Either the key is invalid or key is not supported" + } + return $keyType } \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/powershell/rsa_provider.mustache b/modules/openapi-generator/src/main/resources/powershell/rsa_provider.mustache index a23490b366e..7a671929fb2 100644 --- a/modules/openapi-generator/src/main/resources/powershell/rsa_provider.mustache +++ b/modules/openapi-generator/src/main/resources/powershell/rsa_provider.mustache @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Net; using System.Runtime.InteropServices; using System.Security; using System.Security.Cryptography; @@ -10,15 +11,97 @@ namespace RSAEncryption { public class RSAEncryptionProvider { + public static RSACryptoServiceProvider GetRSAProviderFromPemFile(String pemfile,SecureString keyPassPharse = null) + { + const String pempubheader = "-----BEGIN PUBLIC KEY-----"; + const String pempubfooter = "-----END PUBLIC KEY-----"; + bool isPrivateKeyFile = true; + byte[] pemkey = null; + + if (!File.Exists(pemfile)) + { + throw new Exception("private key file does not exist."); + } + string pemstr = File.ReadAllText(pemfile).Trim(); + + if (pemstr.StartsWith(pempubheader) && pemstr.EndsWith(pempubfooter)) + { + isPrivateKeyFile = false; + } + + if (isPrivateKeyFile) + { + pemkey = ConvertPrivateKeyToBytes(pemstr,keyPassPharse); + if (pemkey == null) + { + return null; + } + return DecodeRSAPrivateKey(pemkey); + } + return null ; + } + + static byte[] ConvertPrivateKeyToBytes(String instr, SecureString keyPassPharse = null) + { + const String pemprivheader = "-----BEGIN RSA PRIVATE KEY-----"; + const String pemprivfooter = "-----END RSA PRIVATE KEY-----"; + String pemstr = instr.Trim(); + byte[] binkey; + + if (!pemstr.StartsWith(pemprivheader) || !pemstr.EndsWith(pemprivfooter)) + { + return null; + } + + StringBuilder sb = new StringBuilder(pemstr); + sb.Replace(pemprivheader, ""); + sb.Replace(pemprivfooter, ""); + String pvkstr = sb.ToString().Trim(); + + try + { // if there are no PEM encryption info lines, this is an UNencrypted PEM private key + binkey = Convert.FromBase64String(pvkstr); + return binkey; + } + catch (System.FormatException) + { + StringReader str = new StringReader(pvkstr); + + //-------- read PEM encryption info. lines and extract salt ----- + if (!str.ReadLine().StartsWith("Proc-Type: 4,ENCRYPTED")) + return null; + String saltline = str.ReadLine(); + if (!saltline.StartsWith("DEK-Info: DES-EDE3-CBC,")) + return null; + String saltstr = saltline.Substring(saltline.IndexOf(",") + 1).Trim(); + byte[] salt = new byte[saltstr.Length / 2]; + for (int i = 0; i < salt.Length; i++) + salt[i] = Convert.ToByte(saltstr.Substring(i * 2, 2), 16); + if (!(str.ReadLine() == "")) + return null; + + //------ remaining b64 data is encrypted RSA key ---- + String encryptedstr = str.ReadToEnd(); + + try + { //should have b64 encrypted RSA key now + binkey = Convert.FromBase64String(encryptedstr); + } + catch (System.FormatException) + { //data is not in base64 fromat + return null; + } + + byte[] deskey = GetEncryptedKey(salt, keyPassPharse, 1, 2); // count=1 (for OpenSSL implementation); 2 iterations to get at least 24 bytes + if (deskey == null) + return null; + + //------ Decrypt the encrypted 3des-encrypted RSA private key ------ + byte[] rsakey = DecryptKey(binkey, deskey, salt); //OpenSSL uses salt value in PEM header also as 3DES IV + return rsakey; + } + } - const String pemprivheader = "-----BEGIN RSA PRIVATE KEY-----"; - const String pemprivfooter = "-----END RSA PRIVATE KEY-----"; - const String pempubheader = "-----BEGIN PUBLIC KEY-----"; - const String pempubfooter = "-----END PUBLIC KEY-----"; - const String pemp8header = "-----BEGIN PRIVATE KEY-----"; - const String pemp8footer = "-----END PRIVATE KEY-----"; - const String pemp8encheader = "-----BEGIN ENCRYPTED PRIVATE KEY-----"; - const String pemp8encfooter = "-----END ENCRYPTED PRIVATE KEY-----"; public static RSACryptoServiceProvider DecodeRSAPrivateKey(byte[] privkey) { byte[] MODULUS, E, D, P, Q, DP, DQ, IQ; @@ -46,7 +129,6 @@ namespace RSAEncryption if (bt != 0x00) return null; - //------ all private key components are Integer sequences ---- elems = GetIntegerSize(binr); MODULUS = binr.ReadBytes(elems); @@ -72,19 +154,6 @@ namespace RSAEncryption elems = GetIntegerSize(binr); IQ = binr.ReadBytes(elems); - /*Console.WriteLine("showing components .."); - if (true) - { - showBytes("\nModulus", MODULUS); - showBytes("\nExponent", E); - showBytes("\nD", D); - showBytes("\nP", P); - showBytes("\nQ", Q); - showBytes("\nDP", DP); - showBytes("\nDQ", DQ); - showBytes("\nIQ", IQ); - }*/ - // ------- create RSACryptoServiceProvider instance and initialize with public key ----- RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(); RSAParameters RSAparams = new RSAParameters(); @@ -140,94 +209,17 @@ namespace RSAEncryption return count; } - static byte[] DecodeOpenSSLPrivateKey(String instr) - { - const String pemprivheader = "-----BEGIN RSA PRIVATE KEY-----"; - const String pemprivfooter = "-----END RSA PRIVATE KEY-----"; - String pemstr = instr.Trim(); - byte[] binkey; - if (!pemstr.StartsWith(pemprivheader) || !pemstr.EndsWith(pemprivfooter)) - return null; - - StringBuilder sb = new StringBuilder(pemstr); - sb.Replace(pemprivheader, ""); //remove headers/footers, if present - sb.Replace(pemprivfooter, ""); - - String pvkstr = sb.ToString().Trim(); //get string after removing leading/trailing whitespace - - try - { // if there are no PEM encryption info lines, this is an UNencrypted PEM private key - binkey = Convert.FromBase64String(pvkstr); - return binkey; - } - catch (System.FormatException) - { //if can't b64 decode, it must be an encrypted private key - //Console.WriteLine("Not an unencrypted OpenSSL PEM private key"); - } - - StringReader str = new StringReader(pvkstr); - - //-------- read PEM encryption info. lines and extract salt ----- - if (!str.ReadLine().StartsWith("Proc-Type: 4,ENCRYPTED")) - return null; - String saltline = str.ReadLine(); - if (!saltline.StartsWith("DEK-Info: DES-EDE3-CBC,")) - return null; - String saltstr = saltline.Substring(saltline.IndexOf(",") + 1).Trim(); - byte[] salt = new byte[saltstr.Length / 2]; - for (int i = 0; i < salt.Length; i++) - salt[i] = Convert.ToByte(saltstr.Substring(i * 2, 2), 16); - if (!(str.ReadLine() == "")) - return null; - - //------ remaining b64 data is encrypted RSA key ---- - String encryptedstr = str.ReadToEnd(); - - try - { //should have b64 encrypted RSA key now - binkey = Convert.FromBase64String(encryptedstr); - } - catch (System.FormatException) - { // bad b64 data. - return null; - } - - //------ Get the 3DES 24 byte key using PDK used by OpenSSL ---- - - SecureString despswd = GetSecPswd("Enter password to derive 3DES key==>"); - //Console.Write("\nEnter password to derive 3DES key: "); - //String pswd = Console.ReadLine(); - byte[] deskey = GetOpenSSL3deskey(salt, despswd, 1, 2); // count=1 (for OpenSSL implementation); 2 iterations to get at least 24 bytes - if (deskey == null) - return null; - //showBytes("3DES key", deskey) ; - - //------ Decrypt the encrypted 3des-encrypted RSA private key ------ - byte[] rsakey = DecryptKey(binkey, deskey, salt); //OpenSSL uses salt value in PEM header also as 3DES IV - if (rsakey != null) - return rsakey; //we have a decrypted RSA private key - else - { - Console.WriteLine("Failed to decrypt RSA private key; probably wrong password."); - return null; - } - } - - static byte[] GetOpenSSL3deskey(byte[] salt, SecureString secpswd, int count, int miter) + static byte[] GetEncryptedKey(byte[] salt, SecureString secpswd, int count, int miter) { IntPtr unmanagedPswd = IntPtr.Zero; int HASHLENGTH = 16; //MD5 bytes byte[] keymaterial = new byte[HASHLENGTH * miter]; //to store contatenated Mi hashed results - byte[] psbytes = new byte[secpswd.Length]; unmanagedPswd = Marshal.SecureStringToGlobalAllocAnsi(secpswd); Marshal.Copy(unmanagedPswd, psbytes, 0, psbytes.Length); Marshal.ZeroFreeGlobalAllocAnsi(unmanagedPswd); - //UTF8Encoding utf8 = new UTF8Encoding(); - //byte[] psbytes = utf8.GetBytes(pswd); - // --- contatenate salt and pswd bytes into fixed data array --- byte[] data00 = new byte[psbytes.Length + salt.Length]; Array.Copy(psbytes, data00, psbytes.Length); //copy the pswd bytes @@ -248,15 +240,12 @@ namespace RSAEncryption Array.Copy(result, hashtarget, result.Length); Array.Copy(data00, 0, hashtarget, result.Length, data00.Length); result = hashtarget; - //Console.WriteLine("Updated new initial hash target:") ; - //showBytes(result) ; } for (int i = 0; i < count; i++) result = md5.ComputeHash(result); Array.Copy(result, 0, keymaterial, j * HASHLENGTH, result.Length); //contatenate to keymaterial } - //showBytes("Final key material", keymaterial); byte[] deskey = new byte[24]; Array.Copy(keymaterial, deskey, deskey.Length); @@ -265,46 +254,9 @@ namespace RSAEncryption Array.Clear(result, 0, result.Length); Array.Clear(hashtarget, 0, hashtarget.Length); Array.Clear(keymaterial, 0, keymaterial.Length); - return deskey; } - public static string GetRSASignb64encode(string private_key_path, byte[] digest) - { - RSACryptoServiceProvider cipher = new RSACryptoServiceProvider(); - cipher = GetRSAProviderFromPemFile(private_key_path); - RSAPKCS1SignatureFormatter RSAFormatter = new RSAPKCS1SignatureFormatter(cipher); - RSAFormatter.SetHashAlgorithm("SHA256"); - byte[] signedHash = RSAFormatter.CreateSignature(digest); - return Convert.ToBase64String(signedHash); - } - - public static RSACryptoServiceProvider GetRSAProviderFromPemFile(String pemfile) - { - bool isPrivateKeyFile = true; - if (!File.Exists(pemfile)) - { - throw new Exception("pemfile does not exist."); - } - string pemstr = File.ReadAllText(pemfile).Trim(); - if (pemstr.StartsWith(pempubheader) && pemstr.EndsWith(pempubfooter)) - isPrivateKeyFile = false; - - byte[] pemkey = null; - if (isPrivateKeyFile) - pemkey = DecodeOpenSSLPrivateKey(pemstr); - - - if (pemkey == null) - return null; - - if (isPrivateKeyFile) - { - return DecodeRSAPrivateKey(pemkey); - } - return null; - } - static byte[] DecryptKey(byte[] cipherData, byte[] desKey, byte[] IV) { MemoryStream memst = new MemoryStream(); @@ -317,61 +269,11 @@ namespace RSAEncryption cs.Write(cipherData, 0, cipherData.Length); cs.Close(); } - catch (Exception exc) - { - Console.WriteLine(exc.Message); + catch (Exception){ return null; } byte[] decryptedData = memst.ToArray(); return decryptedData; } - - static SecureString GetSecPswd(String prompt) - { - SecureString password = new SecureString(); - - Console.ForegroundColor = ConsoleColor.Gray; - Console.ForegroundColor = ConsoleColor.Magenta; - - while (true) - { - ConsoleKeyInfo cki = Console.ReadKey(true); - if (cki.Key == ConsoleKey.Enter) - { - Console.ForegroundColor = ConsoleColor.Gray; - return password; - } - else if (cki.Key == ConsoleKey.Backspace) - { - // remove the last asterisk from the screen... - if (password.Length > 0) - { - Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop); - Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop); - password.RemoveAt(password.Length - 1); - } - } - else if (cki.Key == ConsoleKey.Escape) - { - Console.ForegroundColor = ConsoleColor.Gray; - return password; - } - else if (Char.IsLetterOrDigit(cki.KeyChar) || Char.IsSymbol(cki.KeyChar)) - { - if (password.Length < 20) - { - password.AppendChar(cki.KeyChar); - } - else - { - Console.Beep(); - } - } - else - { - Console.Beep(); - } - } - } } -} +} \ No newline at end of file From 5ef626be53b67b78980f415a2db224ab10985b37 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Sat, 30 May 2020 10:24:40 +0800 Subject: [PATCH 07/62] add new file in php-symfony sample --- .../php-symfony/SymfonyBundle-php/.openapi-generator/FILES | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/samples/server/petstore/php-symfony/SymfonyBundle-php/.openapi-generator/FILES b/samples/server/petstore/php-symfony/SymfonyBundle-php/.openapi-generator/FILES index 448f2a8d2aa..c99e0a880af 100644 --- a/samples/server/petstore/php-symfony/SymfonyBundle-php/.openapi-generator/FILES +++ b/samples/server/petstore/php-symfony/SymfonyBundle-php/.openapi-generator/FILES @@ -30,9 +30,10 @@ ./Tests/Model/TagTest.php ./Tests/Model/UserTest.php ./Tests/test_config.yml +.coveralls.yml .gitignore .openapi-generator-ignore -.php_cs +.php_cs.dist .travis.yml DependencyInjection/Compiler/OpenAPIServerApiPass.php DependencyInjection/OpenAPIServerExtension.php From 74584eb734f54ec0e7028aa643e68d1adeb3f014 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Sat, 30 May 2020 11:17:19 +0800 Subject: [PATCH 08/62] migrate apex samples to use oas3 spec (#6488) --- bin/apex-petstore.sh | 2 +- samples/client/petstore/apex/README.md | 5 ++- .../main/default/classes/OASPetApi.cls | 30 +++++++------ .../main/default/classes/OASStoreApi.cls | 8 ++-- .../main/default/classes/OASUserApi.cls | 44 +++++++++---------- 5 files changed, 46 insertions(+), 43 deletions(-) diff --git a/bin/apex-petstore.sh b/bin/apex-petstore.sh index c4a2e6e0daa..28863b97d24 100755 --- a/bin/apex-petstore.sh +++ b/bin/apex-petstore.sh @@ -27,6 +27,6 @@ fi # if you've executed sbt assembly previously it will use that instead. export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties" -ags="generate -t modules/openapi-generator/src/main/resources/apex -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g apex -o samples/client/petstore/apex $@" +ags="generate -t modules/openapi-generator/src/main/resources/apex -i modules/openapi-generator/src/test/resources/3_0/petstore.yaml -g apex -o samples/client/petstore/apex -DskipFormModel=true $@" java $JAVA_OPTS -jar $executable $ags diff --git a/samples/client/petstore/apex/README.md b/samples/client/petstore/apex/README.md index 45720bb0ab3..60da087e3fb 100644 --- a/samples/client/petstore/apex/README.md +++ b/samples/client/petstore/apex/README.md @@ -47,12 +47,13 @@ OASClient client = api.getClient(); Map params = new Map{ - 'body' => '' + 'oaSPet' => '' }; try { // cross your fingers - api.addPet(params); + OASPet result = api.addPet(params); + System.debug(result); } catch (OAS.ApiException e) { // ...handle your exceptions } diff --git a/samples/client/petstore/apex/force-app/main/default/classes/OASPetApi.cls b/samples/client/petstore/apex/force-app/main/default/classes/OASPetApi.cls index 1ad41d52ab5..75d79a76882 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/OASPetApi.cls +++ b/samples/client/petstore/apex/force-app/main/default/classes/OASPetApi.cls @@ -28,24 +28,25 @@ public class OASPetApi { /** * Add a new pet to the store * - * @param body Pet object that needs to be added to the store (required) + * @param oaSPet Pet object that needs to be added to the store (required) + * @return OASPet * @throws OAS.ApiException if fails to make API call */ - public void addPet(Map params) { - client.assertNotNull(params.get('body'), 'body'); + public OASPet addPet(Map params) { + client.assertNotNull(params.get('oaSPet'), 'oaSPet'); List query = new List(); List form = new List(); - client.invoke( + return (OASPet) client.invoke( 'POST', '/pet', - (OASPet) params.get('body'), + (OASPet) params.get('oaSPet'), query, form, new Map(), new Map(), - new List(), + new List{ 'application/xml', 'application/json' }, new List{ 'application/json', 'application/xml' }, new List { 'petstore_auth' }, - null + OASPet.class ); } /** @@ -157,24 +158,25 @@ public class OASPetApi { /** * Update an existing pet * - * @param body Pet object that needs to be added to the store (required) + * @param oaSPet Pet object that needs to be added to the store (required) + * @return OASPet * @throws OAS.ApiException if fails to make API call */ - public void updatePet(Map params) { - client.assertNotNull(params.get('body'), 'body'); + public OASPet updatePet(Map params) { + client.assertNotNull(params.get('oaSPet'), 'oaSPet'); List query = new List(); List form = new List(); - client.invoke( + return (OASPet) client.invoke( 'PUT', '/pet', - (OASPet) params.get('body'), + (OASPet) params.get('oaSPet'), query, form, new Map(), new Map(), - new List(), + new List{ 'application/xml', 'application/json' }, new List{ 'application/json', 'application/xml' }, new List { 'petstore_auth' }, - null + OASPet.class ); } /** diff --git a/samples/client/petstore/apex/force-app/main/default/classes/OASStoreApi.cls b/samples/client/petstore/apex/force-app/main/default/classes/OASStoreApi.cls index c5307e79fea..8ad6201cd16 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/OASStoreApi.cls +++ b/samples/client/petstore/apex/force-app/main/default/classes/OASStoreApi.cls @@ -98,23 +98,23 @@ public class OASStoreApi { /** * Place an order for a pet * - * @param body order placed for purchasing the pet (required) + * @param oaSOrder order placed for purchasing the pet (required) * @return OASOrder * @throws OAS.ApiException if fails to make API call */ public OASOrder placeOrder(Map params) { - client.assertNotNull(params.get('body'), 'body'); + client.assertNotNull(params.get('oaSOrder'), 'oaSOrder'); List query = new List(); List form = new List(); return (OASOrder) client.invoke( 'POST', '/store/order', - (OASOrder) params.get('body'), + (OASOrder) params.get('oaSOrder'), query, form, new Map(), new Map(), new List{ 'application/xml', 'application/json' }, - new List(), + new List{ 'application/json' }, new List(), OASOrder.class ); diff --git a/samples/client/petstore/apex/force-app/main/default/classes/OASUserApi.cls b/samples/client/petstore/apex/force-app/main/default/classes/OASUserApi.cls index 79adfc28ddd..021d6377d9d 100644 --- a/samples/client/petstore/apex/force-app/main/default/classes/OASUserApi.cls +++ b/samples/client/petstore/apex/force-app/main/default/classes/OASUserApi.cls @@ -28,69 +28,69 @@ public class OASUserApi { /** * Create user * This can only be done by the logged in user. - * @param body Created user object (required) + * @param oaSUser Created user object (required) * @throws OAS.ApiException if fails to make API call */ public void createUser(Map params) { - client.assertNotNull(params.get('body'), 'body'); + client.assertNotNull(params.get('oaSUser'), 'oaSUser'); List query = new List(); List form = new List(); client.invoke( 'POST', '/user', - (OASUser) params.get('body'), + (OASUser) params.get('oaSUser'), query, form, new Map(), new Map(), new List(), - new List(), - new List(), + new List{ 'application/json' }, + new List { 'api_key' }, null ); } /** * Creates list of users with given input array * - * @param body List of user object (required) + * @param oaSUser List of user object (required) * @throws OAS.ApiException if fails to make API call */ public void createUsersWithArrayInput(Map params) { - client.assertNotNull(params.get('body'), 'body'); + client.assertNotNull(params.get('oaSUser'), 'oaSUser'); List query = new List(); List form = new List(); client.invoke( 'POST', '/user/createWithArray', - (List) params.get('body'), + (List) params.get('oaSUser'), query, form, new Map(), new Map(), new List(), - new List(), - new List(), + new List{ 'application/json' }, + new List { 'api_key' }, null ); } /** * Creates list of users with given input array * - * @param body List of user object (required) + * @param oaSUser List of user object (required) * @throws OAS.ApiException if fails to make API call */ public void createUsersWithListInput(Map params) { - client.assertNotNull(params.get('body'), 'body'); + client.assertNotNull(params.get('oaSUser'), 'oaSUser'); List query = new List(); List form = new List(); client.invoke( 'POST', '/user/createWithList', - (List) params.get('body'), + (List) params.get('oaSUser'), query, form, new Map(), new Map(), new List(), - new List(), - new List(), + new List{ 'application/json' }, + new List { 'api_key' }, null ); } @@ -114,7 +114,7 @@ public class OASUserApi { new Map(), new List(), new List(), - new List(), + new List { 'api_key' }, null ); } @@ -189,7 +189,7 @@ public class OASUserApi { new Map(), new List(), new List(), - new List(), + new List { 'api_key' }, null ); } @@ -197,26 +197,26 @@ public class OASUserApi { * Updated user * This can only be done by the logged in user. * @param username name that need to be deleted (required) - * @param body Updated user object (required) + * @param oaSUser Updated user object (required) * @throws OAS.ApiException if fails to make API call */ public void updateUser(Map params) { client.assertNotNull(params.get('username'), 'username'); - client.assertNotNull(params.get('body'), 'body'); + client.assertNotNull(params.get('oaSUser'), 'oaSUser'); List query = new List(); List form = new List(); client.invoke( 'PUT', '/user/{username}', - (OASUser) params.get('body'), + (OASUser) params.get('oaSUser'), query, form, new Map{ 'username' => (String) params.get('username') }, new Map(), new List(), - new List(), - new List(), + new List{ 'application/json' }, + new List { 'api_key' }, null ); } From a47e522fae1a70d927d0701cb3915c08897b6c58 Mon Sep 17 00:00:00 2001 From: Jim Schubert Date: Sat, 30 May 2020 00:19:03 -0400 Subject: [PATCH 09/62] [core] Refactor templating management (#6357) * [core] Refactor templating management This refactors template management to get logic out of DefaultGenerator and to provide a cleaner API to template search and read/compile. Deprecates MockDefaultGenerator, which is not a mock and causes in-memory retention of file contents. Maintainers should prefer executing a "dryRun" with new DefaultGenerator(true) or do true mock/spies if evaluating template intermediaries is truly necessary. Tests may read written files with lower overhead than the in-process retention of those bytes. This attempts to maintain some compatibility with existing templating adapter interfaces. Any breaking change here would be unintentional but minimal effort to retarget the new interface. * Tests for dry run file outputs * Update API usage in Meta, test TemplateManager * Wait on lastModified, lookup by filename in SpringCodegenTest * Test DefaultGenerator + ignore file * Move config.processOpenAPI in DefaultGenerator * Fix wrong use of libraries templateDirector (java) The samples scripts for Java incorrectly referenced the libraries directories directly rather than the upper-level Java directory. This was incorrect usage of template directories, because the generator expects to be given the "language" directory and perform a lookup for missing templates in the order: * user defined libraries directory * user defined language root * embedded libraries directory * embedded language root * _common directory This is incorrect in our samples scripts because a user or maintainer has the expectation that any template change to files at the Java/ root should also be honored on generation if the script specifies a custom template directory. * Fix handlebars extension usage, clean up Meta tasks HandlebarseEngineAdapter previously didn't handle files without extensions in the same was as the MustacheEngineAdapter. This now allows for files without extension (or dotfiles) to lookup in the same location. Meta tasks are cleaned up to use template manager only, rather than attempting to create an "empty" generator to use the previous templating specific methods. * Update kotlin-multiplatform gradle wrapper * Rename GraphQL .gitignore template The .gitignore file is unable to load via classpath resource from the graphql node server resource directory (for unknown reasons). Before this change, the missing template would fail silently. A .gitignore file may exist in other directories and load as expected. Added a default .gitignore to _common as a fallback so as not to break any custom generators which may also be failing silently. * Log entire stacktrace in go sdk built by gradle in AppVeyor * Rename PHP .gitignore to gitignore Java resources may not load .gitignore, this follows suit with other generators and uses "gitignore" (some use "gitignore.mustache"). * [php] Rename .gitignore templates to gitignore * Use same classpath lookup in common locator * [rust] Properly escape empty triple-braces * [samples] Regenerate --- appveyor.yml | 2 +- bin/ci/java-feign.json | 2 +- bin/ci/java-feign10x.json | 2 +- bin/ci/java-google-api-client.json | 2 +- bin/ci/java-native.json | 2 +- bin/ci/java-okhttp-gson-parcelableModel.json | 2 +- bin/ci/java-okhttp-gson.json | 2 +- bin/ci/java-petstore-feign-10x.json | 2 +- bin/ci/java-rest-assured-jackson.json | 2 +- bin/ci/java-rest-assured.json | 2 +- bin/ci/java-retrofit2.json | 2 +- bin/ci/java-retrofit2rx.json | 2 +- bin/ci/java-retrofit2rx2.json | 2 +- bin/ci/java-vertx.json | 2 +- bin/java-petstore-feign-10x.sh | 2 +- bin/java-petstore-google-api-client.sh | 2 +- bin/java-petstore-native-async.sh | 2 +- bin/java-petstore-native.sh | 2 +- bin/java-petstore-okhttp-gson-parcelable.sh | 2 +- bin/java-petstore-okhttp-gson.sh | 2 +- bin/java-petstore-rest-assured-jackson.sh | 2 +- bin/java-petstore-rest-assured.sh | 2 +- bin/java-petstore-retrofit2.sh | 2 +- bin/java-petstore-retrofit2rx.sh | 2 +- bin/java-petstore-retrofit2rx2.sh | 2 +- bin/java-petstore-vertx.sh | 2 +- bin/windows/java-petstore-feign-10x.bat | 2 +- .../java-petstore-google-api-client.bat | 2 +- bin/windows/java-petstore-native.bat | 2 +- .../java-petstore-okhttp-gson-parcelable.bat | 2 +- bin/windows/java-petstore-okhttp-gson.bat | 2 +- .../java-petstore-rest-assured-jackson.bat | 2 +- bin/windows/java-petstore-rest-assured.bat | 2 +- bin/windows/java-petstore-retrofit2.bat | 2 +- bin/windows/java-petstore-retrofit2rx.bat | 2 +- bin/windows/java-petstore-retrofit2rx2.bat | 2 +- bin/windows/java-petstore-vertx.bat | 2 +- .../org/openapitools/codegen/cmd/Meta.java | 69 +- .../codegen/api/TemplatePathLocator.java | 14 + .../codegen/api/TemplateProcessor.java | 57 ++ .../codegen/api/TemplatingEngineAdapter.java | 26 +- .../codegen/api/TemplatingExecutor.java | 26 + .../codegen/api/TemplatingGenerator.java | 23 +- .../generator/gradle/plugin/tasks/MetaTask.kt | 31 +- .../src/test/kotlin/GenerateTaskDslTest.kt | 5 +- .../src/test/kotlin/MetaTaskDslTest.kt | 2 +- .../codegen/AbstractGenerator.java | 213 ----- .../openapitools/codegen/CodegenConfig.java | 2 - .../openapitools/codegen/DefaultCodegen.java | 15 - .../codegen/DefaultGenerator.java | 516 ++++------ .../codegen/DryRunTemplateManager.java | 107 +++ .../codegen/GlobalSupportingFile.java | 29 - .../openapitools/codegen/TemplateManager.java | 235 +++++ .../codegen/languages/AbstractPhpCodegen.java | 2 +- .../GraphQLNodeJSExpressServerCodegen.java | 2 +- .../languages/PhpLaravelServerCodegen.java | 20 +- .../languages/PhpSilexServerCodegen.java | 2 +- .../CommonTemplateContentLocator.java | 50 + .../GeneratorTemplateContentLocator.java | 91 ++ .../templating/HandlebarsEngineAdapter.java | 21 +- .../templating/MustacheEngineAdapter.java | 27 +- .../templating/TemplateManagerOptions.java | 45 + .../src/main/resources/_common/.gitignore | 74 ++ .../src/main/resources/_common/LICENSE | 201 ---- .../{.gitignore => gitignore} | 0 .../bootstrap/cache/{.gitignore => gitignore} | 0 .../database/{.gitignore => gitignore} | 0 .../php-laravel/{.gitignore => gitignore} | 0 .../storage/app/{.gitignore => gitignore} | 0 .../app/public/{.gitignore => gitignore} | 0 .../framework/cache/{.gitignore => gitignore} | 0 .../framework/{.gitignore => gitignore} | 0 .../sessions/{.gitignore => gitignore} | 0 .../testing/{.gitignore => gitignore} | 0 .../framework/views/{.gitignore => gitignore} | 0 .../storage/logs/{.gitignore => gitignore} | 0 .../php-lumen/{.gitignore => gitignore} | 0 .../php-silex/{.gitignore => gitignore} | 0 .../php-slim-server/{.gitignore => gitignore} | 0 .../{.gitignore => gitignore} | 0 .../php-symfony/{.gitignore => gitignore} | 0 .../php-ze-ph/{.gitignore => gitignore} | 0 .../resources/php/{.gitignore => gitignore} | 0 .../src/main/resources/rust/request.rs | 2 +- .../codegen/DefaultGeneratorTest.java | 404 ++++++-- .../codegen/MockDefaultGenerator.java | 87 +- .../codegen/TemplateManagerTest.java | 189 ++++ .../org/openapitools/codegen/TestUtils.java | 82 +- .../asciidoc/AsciidocGeneratorTest.java | 7 +- .../HaskellServantCodegenTest.java | 16 +- .../codegen/java/JavaClientCodegenTest.java | 274 +++--- .../JavaJAXRSCXFExtServerCodegenTest.java | 47 +- .../jaxrs/JavaJAXRSSpecServerCodegenTest.java | 70 +- .../codegen/java/jaxrs/JavaJaxrsBaseTest.java | 19 +- .../java/spring/SpringCodegenTest.java | 880 +++++++++--------- .../kotlin/KotlinModelCodegenTest.java | 14 +- .../scalaakka/ScalaAkkaClientCodegenTest.java | 97 +- .../codegen/yaml/YamlGeneratorTest.java | 36 +- .../templating/templates/jmeter/api.hbs | 183 ++++ .../templates/jmeter/testdata-localhost.hbs | 2 + .../templating/templates/numbers.handlebars | 1 + .../templating/templates/simple.mustache | 1 + .../gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 99814 bytes .../gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 99814 bytes .../jersey1/gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 99814 bytes .../gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 99814 bytes .../native/gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 99814 bytes .../gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 99814 bytes .../gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 99814 bytes .../gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 99814 bytes .../gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 99814 bytes .../gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 99814 bytes .../gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 99814 bytes .../gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 99814 bytes .../gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 99814 bytes .../gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 99814 bytes .../gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 99814 bytes .../gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 99814 bytes .../gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 99814 bytes .../gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 99814 bytes .../vertx/gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 99814 bytes .../gradle/wrapper/gradle-wrapper.jar | Bin 58702 -> 99814 bytes .../.openapi-generator-ignore | 26 +- .../.openapi-generator/FILES | 4 - .../gradle/wrapper/gradle-wrapper.jar | Bin 53639 -> 58702 bytes .../gradle/wrapper/gradle-wrapper.properties | 3 +- .../petstore/kotlin-multiplatform/gradlew | 137 +-- .../petstore/kotlin-multiplatform/gradlew.bat | 190 ++-- .../php-laravel/.openapi-generator/FILES | 129 +++ .../php-laravel/.openapi-generator/VERSION | 2 +- .../app/Http/Controllers/FakeController.php | 46 +- .../php-laravel/lib/app/Models/BigCat.php | 24 + .../lib/app/Models/BigCatAllOf.php | 15 + .../php-laravel/lib/app/Models/FormatTest.php | 3 + .../lib/app/Models/TypeHolderExample.php | 3 + .../lib/resources/views/welcome.blade.php | 8 +- .../petstore/php-laravel/lib/routes/api.php | 11 +- .../petstore/php-slim4/lib/Model/Pet.php | 1 + .../petstore/php-slim4/lib/SlimRouter.php | 2 + 139 files changed, 3053 insertions(+), 1941 deletions(-) create mode 100644 modules/openapi-generator-core/src/main/java/org/openapitools/codegen/api/TemplatePathLocator.java create mode 100644 modules/openapi-generator-core/src/main/java/org/openapitools/codegen/api/TemplateProcessor.java create mode 100644 modules/openapi-generator-core/src/main/java/org/openapitools/codegen/api/TemplatingExecutor.java delete mode 100644 modules/openapi-generator/src/main/java/org/openapitools/codegen/AbstractGenerator.java create mode 100644 modules/openapi-generator/src/main/java/org/openapitools/codegen/DryRunTemplateManager.java delete mode 100644 modules/openapi-generator/src/main/java/org/openapitools/codegen/GlobalSupportingFile.java create mode 100644 modules/openapi-generator/src/main/java/org/openapitools/codegen/TemplateManager.java create mode 100644 modules/openapi-generator/src/main/java/org/openapitools/codegen/templating/CommonTemplateContentLocator.java create mode 100644 modules/openapi-generator/src/main/java/org/openapitools/codegen/templating/GeneratorTemplateContentLocator.java create mode 100644 modules/openapi-generator/src/main/java/org/openapitools/codegen/templating/TemplateManagerOptions.java create mode 100644 modules/openapi-generator/src/main/resources/_common/.gitignore delete mode 100644 modules/openapi-generator/src/main/resources/_common/LICENSE rename modules/openapi-generator/src/main/resources/graphql-nodejs-express-server/{.gitignore => gitignore} (100%) rename modules/openapi-generator/src/main/resources/php-laravel/bootstrap/cache/{.gitignore => gitignore} (100%) rename modules/openapi-generator/src/main/resources/php-laravel/database/{.gitignore => gitignore} (100%) rename modules/openapi-generator/src/main/resources/php-laravel/{.gitignore => gitignore} (100%) rename modules/openapi-generator/src/main/resources/php-laravel/storage/app/{.gitignore => gitignore} (100%) rename modules/openapi-generator/src/main/resources/php-laravel/storage/app/public/{.gitignore => gitignore} (100%) rename modules/openapi-generator/src/main/resources/php-laravel/storage/framework/cache/{.gitignore => gitignore} (100%) rename modules/openapi-generator/src/main/resources/php-laravel/storage/framework/{.gitignore => gitignore} (100%) rename modules/openapi-generator/src/main/resources/php-laravel/storage/framework/sessions/{.gitignore => gitignore} (100%) rename modules/openapi-generator/src/main/resources/php-laravel/storage/framework/testing/{.gitignore => gitignore} (100%) rename modules/openapi-generator/src/main/resources/php-laravel/storage/framework/views/{.gitignore => gitignore} (100%) rename modules/openapi-generator/src/main/resources/php-laravel/storage/logs/{.gitignore => gitignore} (100%) rename modules/openapi-generator/src/main/resources/php-lumen/{.gitignore => gitignore} (100%) rename modules/openapi-generator/src/main/resources/php-silex/{.gitignore => gitignore} (100%) rename modules/openapi-generator/src/main/resources/php-slim-server/{.gitignore => gitignore} (100%) rename modules/openapi-generator/src/main/resources/php-slim4-server/{.gitignore => gitignore} (100%) rename modules/openapi-generator/src/main/resources/php-symfony/{.gitignore => gitignore} (100%) rename modules/openapi-generator/src/main/resources/php-ze-ph/{.gitignore => gitignore} (100%) rename modules/openapi-generator/src/main/resources/php/{.gitignore => gitignore} (100%) create mode 100644 modules/openapi-generator/src/test/java/org/openapitools/codegen/TemplateManagerTest.java create mode 100644 modules/openapi-generator/src/test/resources/templating/templates/jmeter/api.hbs create mode 100644 modules/openapi-generator/src/test/resources/templating/templates/jmeter/testdata-localhost.hbs create mode 100644 modules/openapi-generator/src/test/resources/templating/templates/numbers.handlebars create mode 100644 modules/openapi-generator/src/test/resources/templating/templates/simple.mustache mode change 100644 => 100755 samples/client/petstore/kotlin-multiplatform/gradlew create mode 100644 samples/server/petstore/php-laravel/.openapi-generator/FILES create mode 100644 samples/server/petstore/php-laravel/lib/app/Models/BigCat.php create mode 100644 samples/server/petstore/php-laravel/lib/app/Models/BigCatAllOf.php diff --git a/appveyor.yml b/appveyor.yml index c0feaeaa505..d3c02aa19f1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -50,7 +50,7 @@ build_script: # install openapi-generator locally - mvn --no-snapshot-updates --quiet clean install -Dorg.slf4j.simpleLogger.defaultLogLevel=error # run the locally installed openapi-generator-gradle-plugin - - gradle -b modules\openapi-generator-gradle-plugin\samples\local-spec\build.gradle buildGoSdk --info + - gradle -b modules\openapi-generator-gradle-plugin\samples\local-spec\build.gradle buildGoSdk --stacktrace test_script: # restore test-related files - copy /b/v/y CI\samples.ci\client\petstore\csharp\OpenAPIClient\src\Org.OpenAPITools.Test\Org.OpenAPITools.Test.csproj samples\client\petstore\csharp\OpenAPIClient\src\Org.OpenAPITools.Test\Org.OpenAPITools.Test.csproj diff --git a/bin/ci/java-feign.json b/bin/ci/java-feign.json index 3e2d314e4d5..8d2c23fa7ea 100644 --- a/bin/ci/java-feign.json +++ b/bin/ci/java-feign.json @@ -3,7 +3,7 @@ "generatorName": "java", "inputSpec": "modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml", "outputDir": "samples/client/petstore/java/feign", - "templateDir": "modules/openapi-generator/src/main/resources/Java/libraries/feign", + "templateDir": "modules/openapi-generator/src/main/resources/Java", "additionalProperties": { "hideGenerationTimestamp": true, "booleanGetterPrefix": "is", diff --git a/bin/ci/java-feign10x.json b/bin/ci/java-feign10x.json index 77262b06219..50574a95423 100644 --- a/bin/ci/java-feign10x.json +++ b/bin/ci/java-feign10x.json @@ -3,7 +3,7 @@ "generatorName": "java", "inputSpec": "modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml", "outputDir": "samples/client/petstore/java/feign10x", - "templateDir": "modules/openapi-generator/src/main/resources/Java/libraries/feign", + "templateDir": "modules/openapi-generator/src/main/resources/Java", "additionalProperties": { "hideGenerationTimestamp": true, "booleanGetterPrefix": "is" diff --git a/bin/ci/java-google-api-client.json b/bin/ci/java-google-api-client.json index 1a447f387fe..e30057f3c91 100644 --- a/bin/ci/java-google-api-client.json +++ b/bin/ci/java-google-api-client.json @@ -3,7 +3,7 @@ "generatorName": "java", "inputSpec": "modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml", "outputDir": "samples/client/petstore/java/google-api-client", - "templateDir": "modules/openapi-generator/src/main/resources/Java/libraries/google-api-client", + "templateDir": "modules/openapi-generator/src/main/resources/Java", "additionalProperties": { "hideGenerationTimestamp": true } diff --git a/bin/ci/java-native.json b/bin/ci/java-native.json index 99506422cfa..7d8c792e5bc 100644 --- a/bin/ci/java-native.json +++ b/bin/ci/java-native.json @@ -3,7 +3,7 @@ "generatorName": "java", "inputSpec": "modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml", "outputDir": "samples/client/petstore/java/native", - "templateDir": "modules/openapi-generator/src/main/resources/Java/libraries/native", + "templateDir": "modules/openapi-generator/src/main/resources/Java", "additionalProperties": { "hideGenerationTimestamp": true } diff --git a/bin/ci/java-okhttp-gson-parcelableModel.json b/bin/ci/java-okhttp-gson-parcelableModel.json index 31b5cd136e9..332fa46a24f 100644 --- a/bin/ci/java-okhttp-gson-parcelableModel.json +++ b/bin/ci/java-okhttp-gson-parcelableModel.json @@ -4,7 +4,7 @@ "generatorName": "java", "inputSpec": "modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml", "outputDir": "samples/client/petstore/java/okhttp-gson-parcelableModel", - "templateDir": "modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson", + "templateDir": "modules/openapi-generator/src/main/resources/Java", "additionalProperties": { "hideGenerationTimestamp": true, "parcelableModel": true diff --git a/bin/ci/java-okhttp-gson.json b/bin/ci/java-okhttp-gson.json index 78ca97e598d..cdba0e71287 100644 --- a/bin/ci/java-okhttp-gson.json +++ b/bin/ci/java-okhttp-gson.json @@ -3,7 +3,7 @@ "generatorName": "java", "inputSpec": "modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml", "outputDir": "samples/client/petstore/java/okhttp-gson", - "templateDir": "modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson", + "templateDir": "modules/openapi-generator/src/main/resources/Java", "additionalProperties": { "hideGenerationTimestamp": true } diff --git a/bin/ci/java-petstore-feign-10x.json b/bin/ci/java-petstore-feign-10x.json index 186e64fc9e3..50994004159 100644 --- a/bin/ci/java-petstore-feign-10x.json +++ b/bin/ci/java-petstore-feign-10x.json @@ -1,7 +1,7 @@ { "generatorName": "java", "inputSpec": "modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml", - "templateDir": "modules/openapi-generator/src/main/resources/Java/libraries/feign", + "templateDir": "modules/openapi-generator/src/main/resources/Java", "outputDir": "samples/client/petstore/java/feign10x", "additionalProperties": { "hideGenerationTimestamp": true, diff --git a/bin/ci/java-rest-assured-jackson.json b/bin/ci/java-rest-assured-jackson.json index 1ff56d80ea8..c652a9bf7a2 100644 --- a/bin/ci/java-rest-assured-jackson.json +++ b/bin/ci/java-rest-assured-jackson.json @@ -3,7 +3,7 @@ "generatorName": "java", "inputSpec": "modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml", "outputDir": "samples/client/petstore/java/rest-assured-jackson", - "templateDir": "modules/openapi-generator/src/main/resources/Java/libraries/rest-assured", + "templateDir": "modules/openapi-generator/src/main/resources/Java", "additionalProperties": { "hideGenerationTimestamp": true, "booleanGetterPrefix": "is", diff --git a/bin/ci/java-rest-assured.json b/bin/ci/java-rest-assured.json index 19119b115c7..c1328500ad3 100644 --- a/bin/ci/java-rest-assured.json +++ b/bin/ci/java-rest-assured.json @@ -3,7 +3,7 @@ "generatorName": "java", "inputSpec": "modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml", "outputDir": "samples/client/petstore/java/rest-assured", - "templateDir": "modules/openapi-generator/src/main/resources/Java/libraries/rest-assured", + "templateDir": "modules/openapi-generator/src/main/resources/Java", "additionalProperties": { "hideGenerationTimestamp": true, "booleanGetterPrefix": "is" diff --git a/bin/ci/java-retrofit2.json b/bin/ci/java-retrofit2.json index 2b3d251241a..8f2c2a8fba1 100644 --- a/bin/ci/java-retrofit2.json +++ b/bin/ci/java-retrofit2.json @@ -3,7 +3,7 @@ "generatorName": "java", "inputSpec": "modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml", "outputDir": "samples/client/petstore/java/retrofit2", - "templateDir": "modules/openapi-generator/src/main/resources/Java/libraries/retrofit2", + "templateDir": "modules/openapi-generator/src/main/resources/Java", "additionalProperties": { "hideGenerationTimestamp": true } diff --git a/bin/ci/java-retrofit2rx.json b/bin/ci/java-retrofit2rx.json index 3479b1d08b0..35ca3ab5831 100644 --- a/bin/ci/java-retrofit2rx.json +++ b/bin/ci/java-retrofit2rx.json @@ -3,7 +3,7 @@ "generatorName": "java", "inputSpec": "modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml", "outputDir": "samples/client/petstore/java/retrofit2rx", - "templateDir": "modules/openapi-generator/src/main/resources/Java/libraries/retrofit2", + "templateDir": "modules/openapi-generator/src/main/resources/Java", "additionalProperties": { "useRxJava": true, "hideGenerationTimestamp": true diff --git a/bin/ci/java-retrofit2rx2.json b/bin/ci/java-retrofit2rx2.json index c3a6d841683..ce0d7d89d4c 100644 --- a/bin/ci/java-retrofit2rx2.json +++ b/bin/ci/java-retrofit2rx2.json @@ -3,7 +3,7 @@ "generatorName": "java", "inputSpec": "modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml", "outputDir": "samples/client/petstore/java/retrofit2rx2", - "templateDir": "modules/openapi-generator/src/main/resources/Java/libraries/retrofit2", + "templateDir": "modules/openapi-generator/src/main/resources/Java", "additionalProperties": { "useRxJava2": true, "hideGenerationTimestamp": true diff --git a/bin/ci/java-vertx.json b/bin/ci/java-vertx.json index 0e6bf3edd75..2eb162e1c37 100644 --- a/bin/ci/java-vertx.json +++ b/bin/ci/java-vertx.json @@ -3,7 +3,7 @@ "generatorName": "java", "inputSpec": "modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml", "outputDir": "samples/client/petstore/java/vertx", - "templateDir": "modules/openapi-generator/src/main/resources/Java/libraries/vertx", + "templateDir": "modules/openapi-generator/src/main/resources/Java", "additionalProperties": { "hideGenerationTimestamp": true } diff --git a/bin/java-petstore-feign-10x.sh b/bin/java-petstore-feign-10x.sh index 15b1b40e214..3a98ad061bb 100755 --- a/bin/java-petstore-feign-10x.sh +++ b/bin/java-petstore-feign-10x.sh @@ -27,7 +27,7 @@ fi # if you've executed sbt assembly previously it will use that instead. export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties" -ags="generate -t modules/openapi-generator/src/main/resources/Java/libraries/feign -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-feign-10x.json -o samples/client/petstore/java/feign10x --additional-properties hideGenerationTimestamp=true,booleanGetterPrefix=is $@" +ags="generate -t modules/openapi-generator/src/main/resources/Java -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-feign-10x.json -o samples/client/petstore/java/feign10x --additional-properties hideGenerationTimestamp=true,booleanGetterPrefix=is $@" echo "Removing files and folders under samples/client/petstore/java/feign10x/src/main" rm -rf samples/client/petstore/java/feign10x/src/main diff --git a/bin/java-petstore-google-api-client.sh b/bin/java-petstore-google-api-client.sh index 20e3577f197..866e8d40106 100755 --- a/bin/java-petstore-google-api-client.sh +++ b/bin/java-petstore-google-api-client.sh @@ -27,7 +27,7 @@ fi # if you've executed sbt assembly previously it will use that instead. export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties" -ags="generate -t modules/openapi-generator/src/main/resources/Java/libraries/google-api-client -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-google-api-client.json -o samples/client/petstore/java/google-api-client --additional-properties hideGenerationTimestamp=true $@" +ags="generate -t modules/openapi-generator/src/main/resources/Java -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-google-api-client.json -o samples/client/petstore/java/google-api-client --additional-properties hideGenerationTimestamp=true $@" echo "Removing files and folders under samples/client/petstore/java/google-api-client/src/main" rm -rf samples/client/petstore/java/google-api-client/src/main diff --git a/bin/java-petstore-native-async.sh b/bin/java-petstore-native-async.sh index d163250beb6..1782614d9ee 100755 --- a/bin/java-petstore-native-async.sh +++ b/bin/java-petstore-native-async.sh @@ -27,7 +27,7 @@ fi # if you've executed sbt assembly previously it will use that instead. export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties" -ags="generate -t modules/openapi-generator/src/main/resources/Java/libraries/native -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-native.json -o samples/client/petstore/java/native-async --additional-properties hideGenerationTimestamp=true,asyncNative=true $@" +ags="generate -t modules/openapi-generator/src/main/resources/Java -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-native.json -o samples/client/petstore/java/native-async --additional-properties hideGenerationTimestamp=true,asyncNative=true $@" echo "Removing files and folders under samples/client/petstore/java/httpclient/src/main" rm -rf samples/client/petstore/java/native-async/src/main diff --git a/bin/java-petstore-native.sh b/bin/java-petstore-native.sh index d155429a3a6..063275017e9 100755 --- a/bin/java-petstore-native.sh +++ b/bin/java-petstore-native.sh @@ -27,7 +27,7 @@ fi # if you've executed sbt assembly previously it will use that instead. export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties" -ags="generate -t modules/openapi-generator/src/main/resources/Java/libraries/native -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-native.json -o samples/client/petstore/java/native --additional-properties hideGenerationTimestamp=true $@" +ags="generate -t modules/openapi-generator/src/main/resources/Java -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-native.json -o samples/client/petstore/java/native --additional-properties hideGenerationTimestamp=true $@" echo "Removing files and folders under samples/client/petstore/java/httpclient/src/main" rm -rf samples/client/petstore/java/native/src/main diff --git a/bin/java-petstore-okhttp-gson-parcelable.sh b/bin/java-petstore-okhttp-gson-parcelable.sh index ae4fbfd8d2b..92087756ddb 100755 --- a/bin/java-petstore-okhttp-gson-parcelable.sh +++ b/bin/java-petstore-okhttp-gson-parcelable.sh @@ -27,7 +27,7 @@ fi # if you've executed sbt assembly previously it will use that instead. export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties" -ags="generate --artifact-id petstore-okhttp-gson-parcelableModel -t modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-okhttp-gson.json -o samples/client/petstore/java/okhttp-gson-parcelableModel --additional-properties hideGenerationTimestamp=true,parcelableModel=true $@" +ags="generate --artifact-id petstore-okhttp-gson-parcelableModel -t modules/openapi-generator/src/main/resources/Java -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-okhttp-gson.json -o samples/client/petstore/java/okhttp-gson-parcelableModel --additional-properties hideGenerationTimestamp=true,parcelableModel=true $@" rm -rf samples/client/petstore/java/okhttp-gson-parcelableModel/src/main find samples/client/petstore/java/okhttp-gson-parcelableModel -maxdepth 1 -type f ! -name "README.md" -exec rm {} + diff --git a/bin/java-petstore-okhttp-gson.sh b/bin/java-petstore-okhttp-gson.sh index 8e7e7ac84e4..8e2e527d2a3 100755 --- a/bin/java-petstore-okhttp-gson.sh +++ b/bin/java-petstore-okhttp-gson.sh @@ -27,7 +27,7 @@ fi # if you've executed sbt assembly previously it will use that instead. export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties" -ags="generate -t modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-okhttp-gson.json -o samples/client/petstore/java/okhttp-gson --additional-properties hideGenerationTimestamp=true $@" +ags="generate -t modules/openapi-generator/src/main/resources/Java -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-okhttp-gson.json -o samples/client/petstore/java/okhttp-gson --additional-properties hideGenerationTimestamp=true $@" rm -rf samples/client/petstore/java/okhttp-gson/src/main find samples/client/petstore/java/okhttp-gson -maxdepth 1 -type f ! -name "README.md" -exec rm {} + diff --git a/bin/java-petstore-rest-assured-jackson.sh b/bin/java-petstore-rest-assured-jackson.sh index eeffe6aacee..b5d1888032b 100755 --- a/bin/java-petstore-rest-assured-jackson.sh +++ b/bin/java-petstore-rest-assured-jackson.sh @@ -28,7 +28,7 @@ fi # if you've executed sbt assembly previously it will use that instead. export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties" -args="generate -t modules/openapi-generator/src/main/resources/Java/libraries/rest-assured -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-rest-assured-jackson.json -o ${target_dir} --additional-properties hideGenerationTimestamp=true --additional-properties useBeanValidation=true --additional-properties performBeanValidation=true --additional-properties booleanGetterPrefix=is --additional-properties java8=true --additional-properties dateLibrary=java8 --additional-properties serializationLibrary=jackson $@" +args="generate -t modules/openapi-generator/src/main/resources/Java -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-rest-assured-jackson.json -o ${target_dir} --additional-properties hideGenerationTimestamp=true --additional-properties useBeanValidation=true --additional-properties performBeanValidation=true --additional-properties booleanGetterPrefix=is --additional-properties java8=true --additional-properties dateLibrary=java8 --additional-properties serializationLibrary=jackson $@" echo "Removing ${target_dir}" rm -rf "${target_dir}" diff --git a/bin/java-petstore-rest-assured.sh b/bin/java-petstore-rest-assured.sh index 93de0703ed7..81f1893ed89 100755 --- a/bin/java-petstore-rest-assured.sh +++ b/bin/java-petstore-rest-assured.sh @@ -27,7 +27,7 @@ fi # if you've executed sbt assembly previously it will use that instead. export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties" -ags="generate -t modules/openapi-generator/src/main/resources/Java/libraries/rest-assured -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-rest-assured.json -o samples/client/petstore/java/rest-assured --additional-properties hideGenerationTimestamp=true --additional-properties useBeanValidation=true --additional-properties performBeanValidation=true --additional-properties booleanGetterPrefix=is $@" +ags="generate -t modules/openapi-generator/src/main/resources/Java -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-rest-assured.json -o samples/client/petstore/java/rest-assured --additional-properties hideGenerationTimestamp=true --additional-properties useBeanValidation=true --additional-properties performBeanValidation=true --additional-properties booleanGetterPrefix=is $@" echo "Removing files and folders under samples/client/petstore/java/rest-assured/src/main" rm -rf samples/client/petstore/java/rest-assured/src/main diff --git a/bin/java-petstore-retrofit2.sh b/bin/java-petstore-retrofit2.sh index 2dce65f2724..09bd66f4540 100755 --- a/bin/java-petstore-retrofit2.sh +++ b/bin/java-petstore-retrofit2.sh @@ -27,7 +27,7 @@ fi # if you've executed sbt assembly previously it will use that instead. export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties" -ags="generate -t modules/openapi-generator/src/main/resources/Java/libraries/retrofit2 -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-retrofit2.json -o samples/client/petstore/java/retrofit2 --additional-properties hideGenerationTimestamp=true $@" +ags="generate -t modules/openapi-generator/src/main/resources/Java -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-retrofit2.json -o samples/client/petstore/java/retrofit2 --additional-properties hideGenerationTimestamp=true $@" echo "Removing files and folders under samples/client/petstore/java/retrofit2/src/main" rm -rf samples/client/petstore/java/retrofit2/src/main diff --git a/bin/java-petstore-retrofit2rx.sh b/bin/java-petstore-retrofit2rx.sh index 74729919db1..c1ddc268e5a 100755 --- a/bin/java-petstore-retrofit2rx.sh +++ b/bin/java-petstore-retrofit2rx.sh @@ -27,7 +27,7 @@ fi # if you've executed sbt assembly previously it will use that instead. export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties" -ags="generate -t modules/openapi-generator/src/main/resources/Java/libraries/retrofit2 -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-retrofit2rx.json -o samples/client/petstore/java/retrofit2rx --additional-properties useRxJava=true,hideGenerationTimestamp=true $@" +ags="generate -t modules/openapi-generator/src/main/resources/Java -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-retrofit2rx.json -o samples/client/petstore/java/retrofit2rx --additional-properties useRxJava=true,hideGenerationTimestamp=true $@" echo "Removing files and folders under samples/client/petstore/java/retrofit2rx/src/main" rm -rf samples/client/petstore/java/retrofit2rx/src/main diff --git a/bin/java-petstore-retrofit2rx2.sh b/bin/java-petstore-retrofit2rx2.sh index 05d6acb7bd0..9e7d0fe4046 100755 --- a/bin/java-petstore-retrofit2rx2.sh +++ b/bin/java-petstore-retrofit2rx2.sh @@ -27,7 +27,7 @@ fi # if you've executed sbt assembly previously it will use that instead. export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties" -ags="generate -t modules/openapi-generator/src/main/resources/Java/libraries/retrofit2 -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-retrofit2rx2.json -o samples/client/petstore/java/retrofit2rx2 --additional-properties useRxJava2=true,hideGenerationTimestamp=true $@" +ags="generate -t modules/openapi-generator/src/main/resources/Java -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-retrofit2rx2.json -o samples/client/petstore/java/retrofit2rx2 --additional-properties useRxJava2=true,hideGenerationTimestamp=true $@" echo "Removing files and folders under samples/client/petstore/java/retrofit2rx2/src/main" rm -rf samples/client/petstore/java/retrofit2rx2/src/main diff --git a/bin/java-petstore-vertx.sh b/bin/java-petstore-vertx.sh index 8eeb623b278..a2536a3dbf2 100755 --- a/bin/java-petstore-vertx.sh +++ b/bin/java-petstore-vertx.sh @@ -27,7 +27,7 @@ fi # if you've executed sbt assembly previously it will use that instead. export JAVA_OPTS="${JAVA_OPTS} -Xmx1024M -DloggerPath=conf/log4j.properties" -ags="generate -t modules/openapi-generator/src/main/resources/Java/libraries/vertx -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-vertx.json -o samples/client/petstore/java/vertx --additional-properties hideGenerationTimestamp=true $@" +ags="generate -t modules/openapi-generator/src/main/resources/Java -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin/java-petstore-vertx.json -o samples/client/petstore/java/vertx --additional-properties hideGenerationTimestamp=true $@" echo "Removing files and folders under samples/client/petstore/java/vertx/src/main" rm -rf samples/client/petstore/java/vertx/src/main diff --git a/bin/windows/java-petstore-feign-10x.bat b/bin/windows/java-petstore-feign-10x.bat index d9163fdac99..68fda6d0236 100644 --- a/bin/windows/java-petstore-feign-10x.bat +++ b/bin/windows/java-petstore-feign-10x.bat @@ -5,6 +5,6 @@ If Not Exist %executable% ( ) REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -set ags=generate -t modules\openapi-generator\src\main\resources\Java\libraries\feign -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-feign-10x.json -o samples\client\petstore\java\feign10x --additional-properties hideGenerationTimestamp=true,booleanGetterPrefix=is +set ags=generate -t modules\openapi-generator\src\main\resources\Java -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-feign-10x.json -o samples\client\petstore\java\feign10x --additional-properties hideGenerationTimestamp=true,booleanGetterPrefix=is java %JAVA_OPTS% -jar %executable% %ags% diff --git a/bin/windows/java-petstore-google-api-client.bat b/bin/windows/java-petstore-google-api-client.bat index c9d2d761b66..ae005af5c94 100644 --- a/bin/windows/java-petstore-google-api-client.bat +++ b/bin/windows/java-petstore-google-api-client.bat @@ -5,6 +5,6 @@ If Not Exist %executable% ( ) REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -set ags=generate -t modules\openapi-generator\src\main\resources\Java\libraries\google-api-client -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-google-api-client.json -o samples\client\petstore\java\google-api-client --additional-properties hideGenerationTimestamp=true +set ags=generate -t modules\openapi-generator\src\main\resources\Java -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-google-api-client.json -o samples\client\petstore\java\google-api-client --additional-properties hideGenerationTimestamp=true java %JAVA_OPTS% -jar %executable% %ags% diff --git a/bin/windows/java-petstore-native.bat b/bin/windows/java-petstore-native.bat index e7301e90679..8980399c815 100644 --- a/bin/windows/java-petstore-native.bat +++ b/bin/windows/java-petstore-native.bat @@ -5,6 +5,6 @@ If Not Exist %executable% ( ) REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -set ags=generate -t modules\openapi-generator\src\main\resources\Java\libraries\native -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-native.json -o samples\client\petstore\java\native --additional-properties hideGenerationTimestamp=true +set ags=generate -t modules\openapi-generator\src\main\resources\Java -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-native.json -o samples\client\petstore\java\native --additional-properties hideGenerationTimestamp=true java %JAVA_OPTS% -jar %executable% %ags% diff --git a/bin/windows/java-petstore-okhttp-gson-parcelable.bat b/bin/windows/java-petstore-okhttp-gson-parcelable.bat index 402a3cda7f9..fb88907214e 100644 --- a/bin/windows/java-petstore-okhttp-gson-parcelable.bat +++ b/bin/windows/java-petstore-okhttp-gson-parcelable.bat @@ -5,6 +5,6 @@ If Not Exist %executable% ( ) REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -set ags=generate --artifact-id petstore-okhttp-gson-parcelableModel -t modules\openapi-generator\src\main\resources\Java\libraries\okhttp-gson -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-okhttp-gson.json -o samples\client\petstore\java\okhttp-gson-parcelableModel --additional-properties hideGenerationTimestamp=true,parcelableModel=true +set ags=generate --artifact-id petstore-okhttp-gson-parcelableModel -t modules\openapi-generator\src\main\resources\Java -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-okhttp-gson.json -o samples\client\petstore\java\okhttp-gson-parcelableModel --additional-properties hideGenerationTimestamp=true,parcelableModel=true java %JAVA_OPTS% -jar %executable% %ags% diff --git a/bin/windows/java-petstore-okhttp-gson.bat b/bin/windows/java-petstore-okhttp-gson.bat index 80581ca14d4..0965f6a6ae5 100755 --- a/bin/windows/java-petstore-okhttp-gson.bat +++ b/bin/windows/java-petstore-okhttp-gson.bat @@ -5,6 +5,6 @@ If Not Exist %executable% ( ) REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -set ags=generate -t modules\openapi-generator\src\main\resources\Java\libraries\okhttp-gson -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-okhttp-gson.json -o samples\client\petstore\java\okhttp-gson --additional-properties hideGenerationTimestamp=true +set ags=generate -t modules\openapi-generator\src\main\resources\Java -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-okhttp-gson.json -o samples\client\petstore\java\okhttp-gson --additional-properties hideGenerationTimestamp=true java %JAVA_OPTS% -jar %executable% %ags% diff --git a/bin/windows/java-petstore-rest-assured-jackson.bat b/bin/windows/java-petstore-rest-assured-jackson.bat index 8104df8b771..070156e2f4e 100644 --- a/bin/windows/java-petstore-rest-assured-jackson.bat +++ b/bin/windows/java-petstore-rest-assured-jackson.bat @@ -5,6 +5,6 @@ If Not Exist %executable% ( ) REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -set ags=generate -t modules\openapi-generator\src\main\resources\Java\libraries\rest-assured -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-rest-assured-jackson.json -o samples\client\petstore\java\rest-assured-jackson --additional-properties hideGenerationTimestamp=true,booleanGetterPrefix=is,java8=true,dateLibrary=java8,serializationLibrary=jackson,useBeanValidation=true,performBeanValidation=true, +set ags=generate -t modules\openapi-generator\src\main\resources\Java -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-rest-assured-jackson.json -o samples\client\petstore\java\rest-assured-jackson --additional-properties hideGenerationTimestamp=true,booleanGetterPrefix=is,java8=true,dateLibrary=java8,serializationLibrary=jackson,useBeanValidation=true,performBeanValidation=true, java %JAVA_OPTS% -jar %executable% %ags% diff --git a/bin/windows/java-petstore-rest-assured.bat b/bin/windows/java-petstore-rest-assured.bat index 758af247586..d83f8c42898 100644 --- a/bin/windows/java-petstore-rest-assured.bat +++ b/bin/windows/java-petstore-rest-assured.bat @@ -5,6 +5,6 @@ If Not Exist %executable% ( ) REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -set ags=generate -t modules\openapi-generator\src\main\resources\Java\libraries\rest-assured -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-rest-assured.json -o samples\client\petstore\java\rest-assured --additional-properties hideGenerationTimestamp=true --additional-properties useBeanValidation=true --additional-properties performBeanValidation=true --additional-properties booleanGetterPrefix=is +set ags=generate -t modules\openapi-generator\src\main\resources\Java -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-rest-assured.json -o samples\client\petstore\java\rest-assured --additional-properties hideGenerationTimestamp=true --additional-properties useBeanValidation=true --additional-properties performBeanValidation=true --additional-properties booleanGetterPrefix=is java %JAVA_OPTS% -jar %executable% %ags% diff --git a/bin/windows/java-petstore-retrofit2.bat b/bin/windows/java-petstore-retrofit2.bat index e0d57dfdaa2..c21b2941a5f 100644 --- a/bin/windows/java-petstore-retrofit2.bat +++ b/bin/windows/java-petstore-retrofit2.bat @@ -5,6 +5,6 @@ If Not Exist %executable% ( ) REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -set ags=generate -t modules\openapi-generator\src\main\resources\Java\libraries\retrofit2 -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-retrofit2.json -o samples\client\petstore\java\retrofit2 --additional-properties hideGenerationTimestamp=true +set ags=generate -t modules\openapi-generator\src\main\resources\Java -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-retrofit2.json -o samples\client\petstore\java\retrofit2 --additional-properties hideGenerationTimestamp=true java %JAVA_OPTS% -jar %executable% %ags% diff --git a/bin/windows/java-petstore-retrofit2rx.bat b/bin/windows/java-petstore-retrofit2rx.bat index e3801c9b7cd..c62e07cf07f 100644 --- a/bin/windows/java-petstore-retrofit2rx.bat +++ b/bin/windows/java-petstore-retrofit2rx.bat @@ -5,6 +5,6 @@ If Not Exist %executable% ( ) REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -set ags=generate -t modules\openapi-generator\src\main\resources\Java\libraries\retrofit2 -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-retrofit2rx.json -o samples\client\petstore\java\retrofit2rx --additional-properties useRxJava=true,hideGenerationTimestamp=true +set ags=generate -t modules\openapi-generator\src\main\resources\Java -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-retrofit2rx.json -o samples\client\petstore\java\retrofit2rx --additional-properties useRxJava=true,hideGenerationTimestamp=true java %JAVA_OPTS% -jar %executable% %ags% diff --git a/bin/windows/java-petstore-retrofit2rx2.bat b/bin/windows/java-petstore-retrofit2rx2.bat index 29899b36960..a9521ef27c3 100644 --- a/bin/windows/java-petstore-retrofit2rx2.bat +++ b/bin/windows/java-petstore-retrofit2rx2.bat @@ -5,6 +5,6 @@ If Not Exist %executable% ( ) REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -set ags=generate -t modules\openapi-generator\src\main\resources\Java\libraries\retrofit2 -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-retrofit2rx2.json -o samples\client\petstore\java\retrofit2rx2 --additional-properties useRxJava2=true,hideGenerationTimestamp=true +set ags=generate -t modules\openapi-generator\src\main\resources\Java -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-retrofit2rx2.json -o samples\client\petstore\java\retrofit2rx2 --additional-properties useRxJava2=true,hideGenerationTimestamp=true java %JAVA_OPTS% -jar %executable% %ags% diff --git a/bin/windows/java-petstore-vertx.bat b/bin/windows/java-petstore-vertx.bat index 151d1ac1fb3..133b8eb7173 100644 --- a/bin/windows/java-petstore-vertx.bat +++ b/bin/windows/java-petstore-vertx.bat @@ -5,6 +5,6 @@ If Not Exist %executable% ( ) REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M -set ags=generate -t modules\openapi-generator\src\main\resources\Java\libraries\vertx -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-vertx.json -o samples\client\petstore\java\vertx --additional-properties hideGenerationTimestamp=true +set ags=generate -t modules\openapi-generator\src\main\resources\Java -i modules\openapi-generator\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -g java -c bin\java-petstore-vertx.json -o samples\client\petstore\java\vertx --additional-properties hideGenerationTimestamp=true java %JAVA_OPTS% -jar %executable% %ags% diff --git a/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Meta.java b/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Meta.java index 9fa400098fb..0c4a8f7cf18 100644 --- a/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Meta.java +++ b/modules/openapi-generator-cli/src/main/java/org/openapitools/codegen/cmd/Meta.java @@ -30,6 +30,11 @@ import org.apache.commons.io.FileUtils; import org.openapitools.codegen.CodegenConfig; import org.openapitools.codegen.DefaultGenerator; import org.openapitools.codegen.SupportingFile; +import org.openapitools.codegen.TemplateManager; +import org.openapitools.codegen.api.TemplatePathLocator; +import org.openapitools.codegen.templating.MustacheEngineAdapter; +import org.openapitools.codegen.templating.TemplateManagerOptions; +import org.openapitools.codegen.templating.CommonTemplateContentLocator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -136,52 +141,38 @@ public class Meta extends OpenApiGeneratorCommand { */ private static Converter processFiles(final File targetDir, final Map data) { - return new Converter() { - private DefaultGenerator generator = new DefaultGenerator(); + return support -> { + try { + File destinationFolder = + new File(new File(targetDir.getAbsolutePath()), support.folder); + File outputFile = new File(destinationFolder, support.destinationFilename); - @Override - public File convert(SupportingFile support) { - try { - File destinationFolder = - new File(new File(targetDir.getAbsolutePath()), support.folder); - File outputFile = new File(destinationFolder, support.destinationFilename); + TemplateManager templateProcessor = new TemplateManager( + new TemplateManagerOptions(false, false), + new MustacheEngineAdapter(), + new TemplatePathLocator[]{ new CommonTemplateContentLocator("codegen") } + ); - String template = - generator.readTemplate(new File(TEMPLATE_DIR_CLASSPATH, - support.templateFile).getPath()); - String formatted = template; + String template = templateProcessor.readTemplate(new File(TEMPLATE_DIR_CLASSPATH, support.templateFile).getPath()); - if (support.templateFile.endsWith(MUSTACHE_EXTENSION)) { - LOGGER.info("writing file to {}", outputFile.getAbsolutePath()); - formatted = - Mustache.compiler().withLoader(loader(generator)).defaultValue("") - .compile(template).execute(data); - } else { - LOGGER.info("copying file to {}", outputFile.getAbsolutePath()); - } + String formatted = template; - FileUtils.writeStringToFile(outputFile, formatted, StandardCharsets.UTF_8); - return outputFile; + Mustache.TemplateLoader loader = name -> templateProcessor.getTemplateReader(name.concat(MUSTACHE_EXTENSION)); - } catch (IOException e) { - throw new RuntimeException("Can't generate project", e); + if (support.templateFile.endsWith(MUSTACHE_EXTENSION)) { + LOGGER.info("writing file to {}", outputFile.getAbsolutePath()); + formatted = + Mustache.compiler().withLoader(loader).defaultValue("") + .compile(template).execute(data); + } else { + LOGGER.info("copying file to {}", outputFile.getAbsolutePath()); } - } - }; - } - /** - * Creates mustache loader for template using classpath loader - * - * @param generator - class with reader getter - * @return loader for template - */ - private static Mustache.TemplateLoader loader(final DefaultGenerator generator) { - return new Mustache.TemplateLoader() { - @Override - public Reader getTemplate(String name) { - return generator.getTemplateReader(TEMPLATE_DIR_CLASSPATH + File.separator - + name.concat(MUSTACHE_EXTENSION)); + FileUtils.writeStringToFile(outputFile, formatted, StandardCharsets.UTF_8); + return outputFile; + + } catch (IOException e) { + throw new RuntimeException("Can't generate project", e); } }; } diff --git a/modules/openapi-generator-core/src/main/java/org/openapitools/codegen/api/TemplatePathLocator.java b/modules/openapi-generator-core/src/main/java/org/openapitools/codegen/api/TemplatePathLocator.java new file mode 100644 index 00000000000..9bcd4e2cc8b --- /dev/null +++ b/modules/openapi-generator-core/src/main/java/org/openapitools/codegen/api/TemplatePathLocator.java @@ -0,0 +1,14 @@ +package org.openapitools.codegen.api; + +/** + * Provides means for searching for "actual" template location based on relative template file. + */ +public interface TemplatePathLocator { + /** + * Get the full path to a relative template file. + * + * @param relativeTemplateFile Template file + * @return String Full template file path + */ + String getFullTemplatePath(String relativeTemplateFile); +} diff --git a/modules/openapi-generator-core/src/main/java/org/openapitools/codegen/api/TemplateProcessor.java b/modules/openapi-generator-core/src/main/java/org/openapitools/codegen/api/TemplateProcessor.java new file mode 100644 index 00000000000..6f105167605 --- /dev/null +++ b/modules/openapi-generator-core/src/main/java/org/openapitools/codegen/api/TemplateProcessor.java @@ -0,0 +1,57 @@ +package org.openapitools.codegen.api; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.Map; + +/** + * Interface for abstractions around writing templated data to a file. + */ +public interface TemplateProcessor { + /** + * Writes data to a compiled template + * + * @param data Input data + * @param template Input template location + * @param target The targeted file output location + * + * @return The actual file + * @throws IOException If file cannot be written. + */ + File write(Map data, String template, File target) throws IOException; + + /** + * Write bytes to a file + * + * @param filename The name of file to write + * @param contents The contents bytes. Typically this is a UTF-8 formatted string. + * @return File representing the written file. + * @throws IOException If file cannot be written. + */ + File writeToFile(String filename, byte[] contents) throws IOException; + + /** + * Allow a caller to mark a path as ignored with accompanying reason + * + * @param path The ignored path + * @param context The reason for ignoring this path + */ + void ignore(Path path, String context); + + /** + * Allow a caller to mark a path as skipped with accompanying reason + * + * @param path The skipped path + * @param context The reason for skipping this path + */ + void skip(Path path, String context); + + /** + * Allow a caller to mark a path having errored during processing with accompanying reason + * + * @param path The path which has caused an error + * @param context The reason for the error + */ + default void error(Path path, String context) { }; +} diff --git a/modules/openapi-generator-core/src/main/java/org/openapitools/codegen/api/TemplatingEngineAdapter.java b/modules/openapi-generator-core/src/main/java/org/openapitools/codegen/api/TemplatingEngineAdapter.java index 7fceac5246a..c7240cfe6c2 100644 --- a/modules/openapi-generator-core/src/main/java/org/openapitools/codegen/api/TemplatingEngineAdapter.java +++ b/modules/openapi-generator-core/src/main/java/org/openapitools/codegen/api/TemplatingEngineAdapter.java @@ -36,18 +36,6 @@ public interface TemplatingEngineAdapter { */ String getIdentifier(); - /** - * Compiles a template into a string - * - * @param generator From where we can fetch the templates content (e.g. an instance of DefaultGenerator) - * @param bundle The map of values to pass to the template - * @param templateFile The name of the template (e.g. model.mustache ) - * @return the processed template result - * @throws IOException an error ocurred in the template processing - */ - String compileTemplate(TemplatingGenerator generator, Map bundle, - String templateFile) throws IOException; - /** * During generation, if a supporting file has a file extension that is * inside that array, then it is considered a templated supporting file @@ -57,6 +45,18 @@ public interface TemplatingEngineAdapter { */ String[] getFileExtensions(); + /** + * Compiles a template into a string + * + * @param executor From where we can fetch the templates content (e.g. an instance of DefaultGenerator) + * @param bundle The map of values to pass to the template + * @param templateFile The name of the template (e.g. model.mustache ) + * @return the processed template result + * @throws IOException an error ocurred in the template processing + */ + String compileTemplate(TemplatingExecutor executor, Map bundle, + String templateFile) throws IOException; + /** * Determines whether the template file with supported extensions exists. This may be on the filesystem, * external filesystem, or classpath (implementation is up to TemplatingGenerator). @@ -65,7 +65,7 @@ public interface TemplatingEngineAdapter { * @param templateFile The original target filename * @return True if the template is available in the template search path, false if it can not be found */ - default boolean templateExists(TemplatingGenerator generator, String templateFile) { + default boolean templateExists(TemplatingExecutor generator, String templateFile) { return Arrays.stream(getFileExtensions()).anyMatch(ext -> { int idx = templateFile.lastIndexOf("."); String baseName; diff --git a/modules/openapi-generator-core/src/main/java/org/openapitools/codegen/api/TemplatingExecutor.java b/modules/openapi-generator-core/src/main/java/org/openapitools/codegen/api/TemplatingExecutor.java new file mode 100644 index 00000000000..d0fbb86b5db --- /dev/null +++ b/modules/openapi-generator-core/src/main/java/org/openapitools/codegen/api/TemplatingExecutor.java @@ -0,0 +1,26 @@ +package org.openapitools.codegen.api; + +import java.nio.file.Path; + +/** + * interface to the full template content + * implementers might take into account the -t cli option, + * look in the resources for a generator specific template, etc + */ +public interface TemplatingExecutor { + /** + * returns the template content by name + * + * @param name the template name (e.g. model.mustache) + * @return the contents of that template + */ + String getFullTemplateContents(String name); + + /** + * Returns the path of a template, allowing access to the template where consuming literal contents aren't desirable or possible. + * + * @param name the template name (e.g. model.mustache) + * @return The {@link Path} to the template + */ + Path getFullTemplatePath(String name); +} \ No newline at end of file diff --git a/modules/openapi-generator-core/src/main/java/org/openapitools/codegen/api/TemplatingGenerator.java b/modules/openapi-generator-core/src/main/java/org/openapitools/codegen/api/TemplatingGenerator.java index 268cda6cdfb..30927307e96 100644 --- a/modules/openapi-generator-core/src/main/java/org/openapitools/codegen/api/TemplatingGenerator.java +++ b/modules/openapi-generator-core/src/main/java/org/openapitools/codegen/api/TemplatingGenerator.java @@ -16,28 +16,15 @@ package org.openapitools.codegen.api; -import java.nio.file.Path; - +// TODO: 6.0 Remove /** * interface to the full template content * implementers might take into account the -t cli option, * look in the resources for a language specific template, etc + * + * @deprecated as of 5.0, replaced by {@link TemplatingExecutor}. */ -public interface TemplatingGenerator { +@Deprecated() +public interface TemplatingGenerator extends TemplatingExecutor { - /** - * returns the template content by name - * - * @param name the template name (e.g. model.mustache) - * @return the contents of that template - */ - String getFullTemplateContents(String name); - - /** - * Returns the path of a template, allowing access to the template where consuming literal contents aren't desirable or possible. - * - * @param name the template name (e.g. model.mustache) - * @return The {@link Path} to the template - */ - Path getFullTemplatePath(String name); } diff --git a/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/tasks/MetaTask.kt b/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/tasks/MetaTask.kt index 6a4a180665a..9bebdd4f457 100644 --- a/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/tasks/MetaTask.kt +++ b/modules/openapi-generator-gradle-plugin/src/main/kotlin/org/openapitools/generator/gradle/plugin/tasks/MetaTask.kt @@ -24,10 +24,12 @@ import org.gradle.api.tasks.TaskAction import org.gradle.internal.logging.text.StyledTextOutput import org.gradle.internal.logging.text.StyledTextOutputFactory import org.gradle.kotlin.dsl.property -import org.openapitools.codegen.CodegenConfig -import org.openapitools.codegen.CodegenConstants -import org.openapitools.codegen.DefaultGenerator -import org.openapitools.codegen.SupportingFile +import org.openapitools.codegen.* +import org.openapitools.codegen.api.TemplatePathLocator +import org.openapitools.codegen.templating.CommonTemplateContentLocator +import org.openapitools.codegen.templating.GeneratorTemplateContentLocator +import org.openapitools.codegen.templating.MustacheEngineAdapter +import org.openapitools.codegen.templating.TemplateManagerOptions import java.io.File import java.io.IOException import java.nio.charset.Charset @@ -83,19 +85,28 @@ open class MetaTask : DefaultTask() { "fullyQualifiedGeneratorClass" to "${packageName.get()}.$klass", "openapiGeneratorVersion" to currentVersion) - val generator = DefaultGenerator() supportingFiles.map { try { val destinationFolder = File(File(dir.absolutePath), it.folder) destinationFolder.mkdirs() val outputFile = File(destinationFolder, it.destinationFilename) - val template = generator.readTemplate(File("codegen", it.templateFile).path) + val templateProcessor = TemplateManager( + TemplateManagerOptions(false, false), + MustacheEngineAdapter(), + arrayOf(CommonTemplateContentLocator("codegen")) + ) + + val template = templateProcessor.getFullTemplateContents(it.templateFile) var formatted = template + val loader = Mustache.TemplateLoader { name -> + templateProcessor.getTemplateReader("$name.mustache") + } + if (it.templateFile.endsWith(".mustache")) { formatted = Mustache.compiler() - .withLoader(loader(generator)) + .withLoader(loader) .defaultValue("") .compile(template).execute(data) } @@ -115,12 +126,6 @@ open class MetaTask : DefaultTask() { out.formatln("Created generator %s", klass) } - private fun loader(generator: DefaultGenerator): Mustache.TemplateLoader { - return Mustache.TemplateLoader { name -> - generator.getTemplateReader("codegen${File.separator}$name.mustache") - } - } - private fun String.titleCasedTextOnly(): String = this.split(Regex("[^a-zA-Z0-9]")).joinToString(separator = "", transform = String::capitalize) diff --git a/modules/openapi-generator-gradle-plugin/src/test/kotlin/GenerateTaskDslTest.kt b/modules/openapi-generator-gradle-plugin/src/test/kotlin/GenerateTaskDslTest.kt index 6aecc119252..5586a1d3fbf 100644 --- a/modules/openapi-generator-gradle-plugin/src/test/kotlin/GenerateTaskDslTest.kt +++ b/modules/openapi-generator-gradle-plugin/src/test/kotlin/GenerateTaskDslTest.kt @@ -152,13 +152,14 @@ class GenerateTaskDslTest : TestBase() { // Act val result = GradleRunner.create() .withProjectDir(temp) - .withArguments("openApiGenerate") + .withArguments("openApiGenerate", "--stacktrace") .withPluginClasspath() .buildAndFail() // Assert // rather than write out full handlebars generator templates, we'll just test that the configurator has set handlebars as the engine. - assertTrue(result.output.contains("kotlin-client/model.handlebars (No such file or directory)"), "Build should have attempted to use handlebars.") + assertTrue(result.output.contains("HandlebarsException"), "Stack should expose an exception for missing templates.") + assertTrue(result.output.contains("handlebars"), "Build should have attempted to use handlebars.") assertEquals(TaskOutcome.FAILED, result.task(":openApiGenerate")?.outcome, "Expected a failed run, but found ${result.task(":openApiGenerate")?.outcome}") } diff --git a/modules/openapi-generator-gradle-plugin/src/test/kotlin/MetaTaskDslTest.kt b/modules/openapi-generator-gradle-plugin/src/test/kotlin/MetaTaskDslTest.kt index fe857d1b94a..62e600a92eb 100644 --- a/modules/openapi-generator-gradle-plugin/src/test/kotlin/MetaTaskDslTest.kt +++ b/modules/openapi-generator-gradle-plugin/src/test/kotlin/MetaTaskDslTest.kt @@ -29,7 +29,7 @@ class MetaTaskDslTest : TestBase() { // Act val result = GradleRunner.create() .withProjectDir(temp) - .withArguments("openApiMeta") + .withArguments("openApiMeta", "--stacktrace") .withPluginClasspath() .build() diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/AbstractGenerator.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/AbstractGenerator.java deleted file mode 100644 index 3a2fecbc541..00000000000 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/AbstractGenerator.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech) - * Copyright 2018 SmartBear Software - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.openapitools.codegen; - -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; -import java.util.Arrays; -import org.apache.commons.lang3.StringUtils; -import org.openapitools.codegen.api.TemplatingGenerator; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.*; -import java.nio.file.Paths; -import java.util.HashMap; -import java.util.Map; -import java.util.Scanner; -import java.util.regex.Pattern; - -public abstract class AbstractGenerator implements TemplatingGenerator { - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractGenerator.class); - protected boolean dryRun = false; - protected Map dryRunStatusMap = new HashMap<>(); - - /** - * Is the minimal-file-update option enabled? - * - * @return Option value - */ - public abstract boolean getEnableMinimalUpdate(); - - /** - * Write String to a file, formatting as UTF-8 - * - * @param filename The name of file to write - * @param contents The contents string. - * @return File representing the written file. - * @throws IOException If file cannot be written. - */ - public File writeToFile(String filename, String contents) throws IOException { - return writeToFile(filename, contents.getBytes(StandardCharsets.UTF_8)); - } - - /** - * Write bytes to a file - * - * @param filename The name of file to write - * @param contents The contents bytes. Typically, this is a UTF-8 formatted string. - * @return File representing the written file. - * @throws IOException If file cannot be written. - */ - @SuppressWarnings("static-method") - public File writeToFile(String filename, byte[] contents) throws IOException { - if (getEnableMinimalUpdate()) { - String tempFilename = filename + ".tmp"; - // Use Paths.get here to normalize path (for Windows file separator, space escaping on Linux/Mac, etc) - File outputFile = Paths.get(filename).toFile(); - File tempFile = null; - try { - tempFile = writeToFileRaw(tempFilename, contents); - if (!filesEqual(tempFile, outputFile)) { - LOGGER.info("writing file " + filename); - Files.move(tempFile.toPath(), outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - tempFile = null; - } else { - LOGGER.info("skipping unchanged file " + filename); - } - } finally { - if (tempFile != null && tempFile.exists()) { - try { - tempFile.delete(); - } catch (Exception ex) { - LOGGER.error("Error removing temporary file " + tempFile, ex); - } - } - } - return outputFile; - } else { - LOGGER.info("writing file " + filename); - return writeToFileRaw(filename, contents); - } - } - - private boolean filesEqual(File file1, File file2) throws IOException { - return file1.exists() && file2.exists() && Arrays.equals(Files.readAllBytes(file1.toPath()), Files.readAllBytes(file2.toPath())); - } - - private File writeToFileRaw(String filename, byte[] contents) throws IOException { - // Use Paths.get here to normalize path (for Windows file separator, space escaping on Linux/Mac, etc) - File output = Paths.get(filename).toFile(); - if (output.getParent() != null && !new File(output.getParent()).exists()) { - File parent = Paths.get(output.getParent()).toFile(); - parent.mkdirs(); - } - Files.write(output.toPath(), contents); - return output; - } - - public String readTemplate(String name) { - try { - Reader reader = getTemplateReader(name); - if (reader == null) { - throw new RuntimeException("no file found"); - } - Scanner s = new Scanner(reader).useDelimiter("\\A"); - return s.hasNext() ? s.next() : ""; - } catch (Exception e) { - LOGGER.error(e.getMessage()); - } - throw new RuntimeException("can't load template " + name); - } - - @SuppressWarnings("squid:S2095") - // ignored rule as used in the CLI and it's required to return a reader - public Reader getTemplateReader(String name) { - InputStream is = null; - try { - is = this.getClass().getClassLoader().getResourceAsStream(getCPResourcePath(name)); - if (is == null) { - is = new FileInputStream(new File(name)); // May throw but never return a null value - } - return new InputStreamReader(is, "UTF-8"); - } catch (FileNotFoundException | UnsupportedEncodingException e) { - LOGGER.error(e.getMessage()); - throw new RuntimeException("can't load template " + name); - } - } - - private String buildLibraryFilePath(String dir, String library, String file) { - return dir + File.separator + "libraries" + File.separator + library + File.separator + file; - } - - /** - * Get the template file path with template dir prepended, and use the - * library template if exists. - * - * @param config Codegen config - * @param templateFile Template file - * @return String Full template file path - */ - public String getFullTemplateFile(CodegenConfig config, String templateFile) { - //1st the code will check if there's a