From 1d89ab6e08efb744ad54f4bf7a691a2591dc7fb1 Mon Sep 17 00:00:00 2001 From: Benjamin Gill Date: Thu, 19 Oct 2017 10:37:02 +0100 Subject: [PATCH] [New Generator] Rust API client/server generator (#6613) * Rust API client/server generator * `Future::boxed()` has been deprecated - replace with `Box::new(...)` * rebasing to rust * MMMLS211 use empty vec over none * MMMLS211 rebuild after merge from rust * MMMLS211 YAML array examples not wrapped in Some() * MMMLS211 Array parameters bad mustache fix * MMMLS211 don't parse map containers * MMMLS211 Tidy container types * MMMLS-211 rebuild example * MMMLS211 mvn rebuild * Percent-decode parameters contained in the path * Produce warnings when unknown fields are present We still accept unknown fields and discard them. However, to improve diagnosability, we now write a warning log and return a `Warning` header. Note that this is server-only * Markup * MMMLS211: Make optional arrays Options again * 211 markups * Temporary attempt at tweaking Cow ownership tweak while merging changes from rust branch * Remove to_string call while parsing path parameters, which requires definining a temporary var in a block because rust can't tell where a Cow reference gets dropped * Fix rustfmt to the correct version * Fix rustfmt to the correct version * Add more response information to ApiError in client * Re-add missing brace * Code review markups * Allow converting out of wrapper types * Store arrays in new-types too * Use a new hyper_client every request * Add vec-like traits to array types * Xml support - new branch * Moved conversion from serde_xml_rs::Error to ApiError from swagger-rs to client code until upstream PR is accepted * MMSUB-172 Don't set Content-Type when there's no body. If we don't have a body we've serialized, then don't declare any content type for the nonexistent body. This is really important for 204 No Content responses, but it's also morally important for all other non-bodied responses. * MMSUB-172 Move to swagger 0.6. * Manually implement debug for the client * Allow `Context` to be bound to `Api`, and not passed on every function call * Support "." in parameter names * Support generate's "--reserved-words-mappings" option * Support "." in parameter names * Support generate's "--reserved-words-mappings" option --- README.md | 2 + bin/rust2-petstore.sh | 31 + .../java/io/swagger/codegen/CodegenModel.java | 1 - .../codegen/languages/Rust2Codegen.java | 963 +++++++ .../services/io.swagger.codegen.CodegenConfig | 1 + .../src/main/resources/rust2/Cargo.mustache | 34 + .../src/main/resources/rust2/README.mustache | 59 + .../src/main/resources/rust2/cargo-config | 18 + .../src/main/resources/rust2/client.mustache | 336 +++ .../src/main/resources/rust2/example-ca.pem | 17 + .../resources/rust2/example-client.mustache | 59 + .../resources/rust2/example-server-chain.pem | 66 + .../resources/rust2/example-server-key.pem | 28 + .../resources/rust2/example-server.mustache | 58 + .../rust2/example-server_lib.mustache | 31 + .../src/main/resources/rust2/gitignore | 2 + .../src/main/resources/rust2/lib.mustache | 96 + .../main/resources/rust2/mimetypes.mustache | 21 + .../src/main/resources/rust2/models.mustache | 175 ++ .../src/main/resources/rust2/server.mustache | 338 +++ .../src/main/resources/rust2/swagger.mustache | 1 + .../codegen/options/Rust2OptionsProvider.java | 22 + ...ith-fake-endpoints-models-for-testing.yaml | 34 +- samples/client/petstore/rust2/.cargo/config | 18 + samples/client/petstore/rust2/.gitignore | 2 + .../petstore/rust2/.swagger-codegen-ignore | 23 + .../petstore/rust2/.swagger-codegen/VERSION | 1 + samples/client/petstore/rust2/Cargo.toml | 34 + samples/client/petstore/rust2/README.md | 85 + .../client/petstore/rust2/api/swagger.yaml | 2020 +++++++++++++ samples/client/petstore/rust2/examples/ca.pem | 17 + .../client/petstore/rust2/examples/client.rs | 275 ++ .../petstore/rust2/examples/server-chain.pem | 66 + .../petstore/rust2/examples/server-key.pem | 28 + .../client/petstore/rust2/examples/server.rs | 58 + .../petstore/rust2/examples/server_lib/mod.rs | 279 ++ samples/client/petstore/rust2/src/client.rs | 1970 +++++++++++++ samples/client/petstore/rust2/src/lib.rs | 606 ++++ .../client/petstore/rust2/src/mimetypes.rs | 125 + samples/client/petstore/rust2/src/models.rs | 1136 ++++++++ samples/client/petstore/rust2/src/server.rs | 2518 +++++++++++++++++ 41 files changed, 11651 insertions(+), 3 deletions(-) create mode 100755 bin/rust2-petstore.sh create mode 100755 modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/Rust2Codegen.java create mode 100644 modules/swagger-codegen/src/main/resources/rust2/Cargo.mustache create mode 100644 modules/swagger-codegen/src/main/resources/rust2/README.mustache create mode 100644 modules/swagger-codegen/src/main/resources/rust2/cargo-config create mode 100644 modules/swagger-codegen/src/main/resources/rust2/client.mustache create mode 100644 modules/swagger-codegen/src/main/resources/rust2/example-ca.pem create mode 100644 modules/swagger-codegen/src/main/resources/rust2/example-client.mustache create mode 100644 modules/swagger-codegen/src/main/resources/rust2/example-server-chain.pem create mode 100644 modules/swagger-codegen/src/main/resources/rust2/example-server-key.pem create mode 100644 modules/swagger-codegen/src/main/resources/rust2/example-server.mustache create mode 100644 modules/swagger-codegen/src/main/resources/rust2/example-server_lib.mustache create mode 100644 modules/swagger-codegen/src/main/resources/rust2/gitignore create mode 100644 modules/swagger-codegen/src/main/resources/rust2/lib.mustache create mode 100644 modules/swagger-codegen/src/main/resources/rust2/mimetypes.mustache create mode 100755 modules/swagger-codegen/src/main/resources/rust2/models.mustache create mode 100644 modules/swagger-codegen/src/main/resources/rust2/server.mustache create mode 100644 modules/swagger-codegen/src/main/resources/rust2/swagger.mustache create mode 100644 modules/swagger-codegen/src/test/java/io/swagger/codegen/options/Rust2OptionsProvider.java create mode 100644 samples/client/petstore/rust2/.cargo/config create mode 100644 samples/client/petstore/rust2/.gitignore create mode 100644 samples/client/petstore/rust2/.swagger-codegen-ignore create mode 100644 samples/client/petstore/rust2/.swagger-codegen/VERSION create mode 100644 samples/client/petstore/rust2/Cargo.toml create mode 100644 samples/client/petstore/rust2/README.md create mode 100644 samples/client/petstore/rust2/api/swagger.yaml create mode 100644 samples/client/petstore/rust2/examples/ca.pem create mode 100644 samples/client/petstore/rust2/examples/client.rs create mode 100644 samples/client/petstore/rust2/examples/server-chain.pem create mode 100644 samples/client/petstore/rust2/examples/server-key.pem create mode 100644 samples/client/petstore/rust2/examples/server.rs create mode 100644 samples/client/petstore/rust2/examples/server_lib/mod.rs create mode 100644 samples/client/petstore/rust2/src/client.rs create mode 100644 samples/client/petstore/rust2/src/lib.rs create mode 100644 samples/client/petstore/rust2/src/mimetypes.rs create mode 100644 samples/client/petstore/rust2/src/models.rs create mode 100644 samples/client/petstore/rust2/src/server.rs diff --git a/README.md b/README.md index 96a9d2ad0ee2..ed4a2870fb77 100644 --- a/README.md +++ b/README.md @@ -988,6 +988,7 @@ Here is a list of template creators: * PowerShell: @beatcracker * R: @ramnov * Rust: @farcaller + * Rust (rust-server): @metaswitch * Scala (scalaz & http4s): @tbrown1979 * Swift: @tkqubo * Swift 3: @hexelon @@ -1018,6 +1019,7 @@ Here is a list of template creators: * PHP Symfony: @ksm2 * PHP Zend Expressive (with Path Handler): @Articus * Ruby on Rails 5: @zlx + * Rust (rust-server): @metaswitch * Scala Finch: @jimschubert * Documentation * HTML Doc 2: @jhitchcock diff --git a/bin/rust2-petstore.sh b/bin/rust2-petstore.sh new file mode 100755 index 000000000000..8428f974cdd7 --- /dev/null +++ b/bin/rust2-petstore.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +SCRIPT="$0" + +while [ -h "$SCRIPT" ] ; do + ls=`ls -ld "$SCRIPT"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + SCRIPT="$link" + else + SCRIPT=`dirname "$SCRIPT"`/"$link" + fi +done + +if [ ! -d "${APP_DIR}" ]; then + APP_DIR=`dirname "$SCRIPT"`/.. + APP_DIR=`cd "${APP_DIR}"; pwd` +fi + +executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar" + +if [ ! -f "$executable" ] +then + mvn clean package +fi + +# if you've executed sbt assembly previously it will use that instead. +export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" +ags="$@ generate -t modules/swagger-codegen/src/main/resources/rust2 -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l rust2 -o samples/client/petstore/rust2 -DpackageName=petstore_api" + +java $JAVA_OPTS -jar $executable $ags diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenModel.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenModel.java index 76eccdfa0393..7b8cf07c471d 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenModel.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenModel.java @@ -9,7 +9,6 @@ import java.util.Objects; import io.swagger.models.ExternalDocs; - public class CodegenModel { public String parent, parentSchema; public List interfaces; diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/Rust2Codegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/Rust2Codegen.java new file mode 100755 index 000000000000..76f218aa50f0 --- /dev/null +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/Rust2Codegen.java @@ -0,0 +1,963 @@ +package io.swagger.codegen.languages; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Lists; +import com.google.common.collect.Multimap; +import io.swagger.codegen.*; +import io.swagger.models.*; +import io.swagger.models.parameters.BodyParameter; +import io.swagger.models.parameters.Parameter; +import io.swagger.models.properties.ArrayProperty; +import io.swagger.models.properties.MapProperty; +import io.swagger.models.properties.RefProperty; +import io.swagger.models.properties.*; +import io.swagger.util.Yaml; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.math.BigDecimal; +import java.util.*; +import java.util.Map.Entry; +import org.apache.commons.lang3.StringUtils; + +public class Rust2Codegen extends DefaultCodegen implements CodegenConfig { + + private static final Logger LOGGER = LoggerFactory.getLogger(Rust2Codegen.class); + + private HashMap modelXmlNames = new HashMap(); + + protected String apiVersion = "1.0.0"; + protected int serverPort = 8080; + protected String projectName = "swagger-server"; + protected String apiPath = "rust2"; + protected String packageName; + protected String packageVersion; + protected String externCrateName; + + public Rust2Codegen() { + super(); + + // set the output folder here + outputFolder = "generated-code/rust2"; + + /* + * Models. You can write model files using the modelTemplateFiles map. + * if you want to create one template for file, you can do so here. + * for multiple files for model, just put another entry in the `modelTemplateFiles` with + * a different extension + */ + modelTemplateFiles.clear(); + + /* + * Api classes. You can write classes for each Api file with the apiTemplateFiles map. + * as with models, add multiple entries with different extensions for multiple files per + * class + */ + apiTemplateFiles.clear(); + + /* + * Template Location. This is the location which templates will be read from. The generator + * will use the resource stream to attempt to read the templates. + */ + embeddedTemplateDir = templateDir = "rust2"; + + /* + * Reserved words. Override this with reserved words specific to your language + */ + setReservedWordsLowerCase( + Arrays.asList( + // From https://doc.rust-lang.org/grammar.html#keywords + "abstract", "alignof", "as", "become", "box", "break", "const", + "continue", "crate", "do", "else", "enum", "extern", "false", + "final", "fn", "for", "if", "impl", "in", "let", "loop", "macro", + "match", "mod", "move", "mut", "offsetof", "override", "priv", + "proc", "pub", "pure", "ref", "return", "Self", "self", "sizeof", + "static", "struct", "super", "trait", "true", "type", "typeof", + "unsafe", "unsized", "use", "virtual", "where", "while", "yield" + ) + ); + + defaultIncludes = new HashSet( + Arrays.asList( + "map", + "array") + ); + + languageSpecificPrimitives = new HashSet( + Arrays.asList( + "bool", + "char", + "i8", + "i16", + "i32", + "i64", + "u8", + "u16", + "u32", + "u64", + "isize", + "usize", + "f32", + "f64", + "str") + ); + + instantiationTypes.clear(); + instantiationTypes.put("array", "Vec"); + instantiationTypes.put("map", "Map"); + + typeMapping.clear(); + typeMapping.put("number", "f64"); + typeMapping.put("integer", "i32"); + typeMapping.put("long", "i64"); + typeMapping.put("float", "f32"); + typeMapping.put("double", "f64"); + typeMapping.put("string", "String"); + typeMapping.put("UUID", "uuid::Uuid"); + typeMapping.put("byte", "u8"); + typeMapping.put("ByteArray", "swagger::ByteArray"); + typeMapping.put("binary", "swagger::ByteArray"); + typeMapping.put("boolean", "bool"); + typeMapping.put("date", "chrono::DateTime"); + typeMapping.put("DateTime", "chrono::DateTime"); + typeMapping.put("password", "String"); + typeMapping.put("File", "Box, Error=Error> + Send>"); + typeMapping.put("file", "Box, Error=Error> + Send>"); + typeMapping.put("array", "Vec"); + typeMapping.put("map", "HashMap"); + + importMapping = new HashMap(); + + cliOptions.clear(); + cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, + "Rust crate name (convention: snake_case).") + .defaultValue("swagger_client")); + cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, + "Rust crate version.") + .defaultValue("1.0.0")); + + /* + * Additional Properties. These values can be passed to the templates and + * are available in models, apis, and supporting files + */ + additionalProperties.put("apiVersion", apiVersion); + additionalProperties.put("serverPort", serverPort); + additionalProperties.put("apiPath", apiPath); + + /* + * Supporting Files. You can write single files for the generator with the + * entire object tree available. If the input file has a suffix of `.mustache + * it will be processed by the template engine. Otherwise, it will be copied + */ + supportingFiles.add(new SupportingFile("swagger.mustache", "api", "swagger.yaml")); + supportingFiles.add(new SupportingFile("Cargo.mustache", "", "Cargo.toml")); + supportingFiles.add(new SupportingFile("cargo-config", ".cargo", "config")); + supportingFiles.add(new SupportingFile("gitignore", "", ".gitignore")); + supportingFiles.add(new SupportingFile("lib.mustache", "src", "lib.rs")); + supportingFiles.add(new SupportingFile("models.mustache", "src", "models.rs")); + supportingFiles.add(new SupportingFile("server.mustache", "src", "server.rs")); + supportingFiles.add(new SupportingFile("client.mustache", "src", "client.rs")); + supportingFiles.add(new SupportingFile("mimetypes.mustache", "src", "mimetypes.rs")); + supportingFiles.add(new SupportingFile("example-server.mustache", "examples", "server.rs")); + supportingFiles.add(new SupportingFile("example-client.mustache", "examples", "client.rs")); + supportingFiles.add(new SupportingFile("example-server_lib.mustache", "examples/server_lib", "mod.rs")); + supportingFiles.add(new SupportingFile("example-ca.pem", "examples", "ca.pem")); + supportingFiles.add(new SupportingFile("example-server-chain.pem", "examples", "server-chain.pem")); + supportingFiles.add(new SupportingFile("example-server-key.pem", "examples", "server-key.pem")); + writeOptional(outputFolder, new SupportingFile("README.mustache", "", "README.md")); + } + + @Override + public void processOpts() { + super.processOpts(); + + if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) { + setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME)); + } + else { + setPackageName("swagger_client"); + } + + if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) { + setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION)); + } + else { + setPackageVersion("1.0.0"); + } + + additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName); + additionalProperties.put(CodegenConstants.PACKAGE_VERSION, packageVersion); + additionalProperties.put("externCrateName", externCrateName); + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + + // Also set the extern crate name, which has any '-' replace with a '_'. + this.externCrateName = packageName.replace('-', '_'); + } + + public void setPackageVersion(String packageVersion) { + this.packageVersion = packageVersion; + } + + @Override + public String apiPackage() { + return apiPath; + } + + /** + * Configures the type of generator. + * + * @return the CodegenType for this generator + * @see io.swagger.codegen.CodegenType + */ + @Override + public CodegenType getTag() { + return CodegenType.SERVER; + } + + /** + * Configures a friendly name for the generator. This will be used by the generator + * to select the library with the -l flag. + * + * @return the friendly name for the generator + */ + @Override + public String getName() { + return "rust2"; + } + + /** + * Returns human-friendly help for the generator. Provide the consumer with help + * tips, parameters here + * + * @return A string value for the help message + */ + @Override + public String getHelp() { + return "Generates a Rust client/server library using the swagger-codegen project."; + } + + @Override + public void preprocessSwagger(Swagger swagger) { + Info info = swagger.getInfo(); + List versionComponents = new ArrayList(Arrays.asList(info.getVersion().split("[.]"))); + if (versionComponents.size() < 1) { + versionComponents.add("1"); + } + while (versionComponents.size() < 3) { + versionComponents.add("0"); + } + info.setVersion(StringUtils.join(versionComponents, ".")); + } + + @Override + public String toApiName(String name) { + if (name.length() == 0) { + return "default"; + } + return underscore(name); + } + + /** + * Escapes a reserved word as defined in the `reservedWords` array. Handle escaping + * those terms here. This logic is only called if a variable matches the reseved words + * + * @return the escaped term + */ + @Override + public String escapeReservedWord(String name) { + if (this.reservedWordsMappings().containsKey(name)) { + return this.reservedWordsMappings().get(name); + } + return "_" + name; // add an underscore to the name + } + + /** + * Location to write api files. You can use the apiPackage() as defined when the class is + * instantiated + */ + @Override + public String apiFileFolder() { + return outputFolder + File.separator + apiPackage().replace('.', File.separatorChar); + } + + @Override + public String toModelName(String name) { + // camelize the model name + // phone_number => PhoneNumber + String camelizedName = camelize(toModelFilename(name)); + + // model name cannot use reserved keyword, e.g. return + if (isReservedWord(camelizedName)) { + camelizedName = "Model" + camelizedName; + LOGGER.warn(camelizedName + " (reserved word) cannot be used as model name. Renamed to " + camelizedName); + } + + // model name starts with number + else if (name.matches("^\\d.*")) { + // e.g. 200Response => Model200Response (after camelize) + camelizedName = "Model" + camelizedName; + LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + camelizedName); + } + + return camelizedName; + + } + + @Override + public String toParamName(String name) { + // should be the same as variable name (stolen from RubyClientCodegen) + return toVarName(name); + } + + @Override + public String toVarName(String name) { + String sanitizedName = super.sanitizeName(name); + // for reserved word or word starting with number, append _ + if (isReservedWord(sanitizedName) || sanitizedName.matches("^\\d.*")) { + sanitizedName = escapeReservedWord(sanitizedName); + } + + return underscore(sanitizedName); + } + + @Override + public String toOperationId(String operationId) { + // method name cannot use reserved keyword, e.g. return + if (isReservedWord(operationId)) { + LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + camelize(sanitizeName("call_" + operationId))); + operationId = "call_" + operationId; + } + + return camelize(operationId); + } + + @Override + public String toModelFilename(String name) { + if (!StringUtils.isEmpty(modelNamePrefix)) { + name = modelNamePrefix + "_" + name; + } + + if (!StringUtils.isEmpty(modelNameSuffix)) { + name = name + "_" + modelNameSuffix; + } + + name = sanitizeName(name); + + // model name cannot use reserved keyword, e.g. return + if (isReservedWord(name)) { + LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + camelize("model_" + name)); + name = "model_" + name; // e.g. return => ModelReturn (after camelize) + } + + return underscore(name); + } + + @Override + public String toEnumName(CodegenProperty property) { + return sanitizeName(camelize(property.name)) + "Enum"; + } + + @Override + public String toEnumVarName(String value, String datatype) { + String var = null; + if (value.length() == 0) { + var = "EMPTY"; + } + + // for symbol, e.g. $, # + else if (getSymbolName(value) != null) { + var = getSymbolName(value).toUpperCase(); + } + + // number + else if ("Integer".equals(datatype) || "Long".equals(datatype) || + "Float".equals(datatype) || "Double".equals(datatype)) { + String varName = "NUMBER_" + value; + varName = varName.replaceAll("-", "MINUS_"); + varName = varName.replaceAll("\\+", "PLUS_"); + varName = varName.replaceAll("\\.", "_DOT_"); + var = varName; + } + + // string + var = value.replaceAll("\\W+", "_").toUpperCase(); + if (var.matches("\\d.*")) { + var = "_" + var; + } else { + var = sanitizeName(var); + } + return var; + } + + @Override + public String toEnumValue(String value, String datatype) { + if ("Integer".equals(datatype) || "Long".equals(datatype) || + "Float".equals(datatype) || "Double".equals(datatype)) { + return value; + } else { + return "\"" + escapeText(value) + "\""; + } + } + + @Override + public String toApiFilename(String name) { + // replace - with _ e.g. created-at => created_at + name = name.replaceAll("-", "_"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. + + // e.g. PetApi.go => pet_api.go + return underscore(name); + } + + @Override + public String escapeQuotationMark(String input) { + // remove " to avoid code injection + return input.replace("\"", ""); + } + + @Override + public String escapeUnsafeCharacters(String input) { + return input.replace("*/", "*_/").replace("/*", "/_*"); + } + + @Override + public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, Map definitions, Swagger swagger) { + CodegenOperation op = super.fromOperation(path, httpMethod, operation, definitions, swagger); + op.vendorExtensions.put("operation_id", underscore(op.operationId)); + op.vendorExtensions.put("uppercase_operation_id", underscore(op.operationId).toUpperCase()); + op.vendorExtensions.put("path", op.path.replace("{", ":").replace("}", "")); + op.vendorExtensions.put("HttpMethod", Character.toUpperCase(op.httpMethod.charAt(0)) + op.httpMethod.substring(1).toLowerCase()); + op.vendorExtensions.put("httpmethod", op.httpMethod.toLowerCase()); + for (CodegenParameter param : op.allParams) { + String example = null; + + if (param.isString) { + if (param.dataFormat != null && param.dataFormat.equals("byte")) { + param.vendorExtensions.put("formatString", "\\\"{:?}\\\""); + example = "swagger::ByteArray(\"" + ((param.example != null) ? param.example : "") + "\".to_string().into_bytes())"; + } else { + param.vendorExtensions.put("formatString", "\\\"{}\\\""); + example = "\"" + ((param.example != null) ? param.example : "") + "\".to_string()"; + } + } else if (param.isPrimitiveType) { + if ((param.isByteArray) || + (param.isBinary)) { + // Binary primitive types don't implement `Display`. + param.vendorExtensions.put("formatString", "{:?}"); + example = "swagger::ByteArray(Vec::from(\"" + ((param.example != null) ? param.example : "") + "\"))"; + } else { + param.vendorExtensions.put("formatString", "{}"); + example = (param.example != null) ? param.example : ""; + } + } else if (param.isListContainer) { + param.vendorExtensions.put("formatString", "{:?}"); + example = (param.example != null) ? param.example : "&Vec::new()"; + } else if (param.isFile) { + param.vendorExtensions.put("formatString", "{:?}"); + op.vendorExtensions.put("hasFile", true); + additionalProperties.put("apiHasFile", true); + example = "Box::new(stream::once(Ok(b\"hello\".to_vec()))) as Box + Send>"; + } else { + param.vendorExtensions.put("formatString", "{:?}"); + if (param.example != null) { + example = "serde_json::from_str::<" + param.dataType + ">(\"" + param.example + "\").expect(\"Failed to parse JSON example\")"; + } + } + + if (param.required) { + if (example != null) { + param.vendorExtensions.put("example", example); + } else if (param.isListContainer) { + // Use the empty list if we don't have an example + param.vendorExtensions.put("example", "&Vec::new()"); + } + else { + // If we don't have an example that we can provide, we need to disable the client example, as it won't build. + param.vendorExtensions.put("example", "???"); + op.vendorExtensions.put("noClientExample", Boolean.TRUE); + } + } else if ((param.dataFormat != null)&&((param.dataFormat.equals("date-time")) || (param.dataFormat.equals("date")))) { + param.vendorExtensions.put("formatString", "{:?}"); + param.vendorExtensions.put("example", "None"); + } else { + // Not required, so override the format string and example + param.vendorExtensions.put("formatString", "{:?}"); + if (param.isFile) { + // Optional file types are wrapped in a future + param.vendorExtensions.put("example", (example != null) ? "Box::new(future::ok(Some(" + example + "))) as Box + Send>" : "None"); + } else { + param.vendorExtensions.put("example", (example != null) ? "Some(" + example + ")" : "None"); + } + } + } + + List consumes = new ArrayList(); + if (operation.getConsumes() != null) { + if (operation.getConsumes().size() > 0) { + // use consumes defined in the operation + consumes = operation.getConsumes(); + } + } else if (swagger != null && swagger.getConsumes() != null && swagger.getConsumes().size() > 0) { + // use consumes defined globally + consumes = swagger.getConsumes(); + LOGGER.debug("No consumes defined in operation. Using global consumes (" + swagger.getConsumes() + ") for " + op.operationId); + } + + boolean consumesXml = false; + // if "consumes" is defined (per operation or using global definition) + if (consumes != null && !consumes.isEmpty()) { + List> c = new ArrayList>(); + for (String key : consumes) { + Map mediaType = new HashMap(); + String mimeType = processMimeType(key); + + if (mimeType.startsWith("Application/Xml")) { + additionalProperties.put("usesXml", true); + consumesXml = true; + } + + mediaType.put("mediaType", mimeType); + c.add(mediaType); + } + op.consumes = c; + op.hasConsumes = true; + } + + List produces = new ArrayList(); + if (operation.getProduces() != null) { + if (operation.getProduces().size() > 0) { + // use produces defined in the operation + produces = operation.getProduces(); + } + } else if (swagger != null && swagger.getProduces() != null && swagger.getProduces().size() > 0) { + // use produces defined globally + produces = swagger.getProduces(); + LOGGER.debug("No produces defined in operation. Using global produces (" + swagger.getProduces() + ") for " + op.operationId); + } + + boolean producesXml = false; + if (produces != null && !produces.isEmpty()) { + List> c = new ArrayList>(); + for (String key : produces) { + Map mediaType = new HashMap(); + String mimeType = processMimeType(key); + + if (mimeType.startsWith("Application/Xml")) { + additionalProperties.put("usesXml", true); + producesXml = true; + } + + mediaType.put("mediaType", mimeType); + c.add(mediaType); + } + op.produces = c; + op.hasProduces = true; + } + + if (op.bodyParam != null) { + + if (paramHasXmlNamespace(op.bodyParam, definitions)){ + op.bodyParam.vendorExtensions.put("has_namespace", "true"); + } + for (String key : definitions.keySet()) { + op.bodyParam.vendorExtensions.put("model_key", key); + } + + op.bodyParam.vendorExtensions.put("uppercase_operation_id", underscore(op.operationId).toUpperCase()); + if (consumesXml) { + op.bodyParam.vendorExtensions.put("consumesXml", true); + } + + } + for (CodegenParameter param : op.bodyParams) { + + if (paramHasXmlNamespace(param, definitions)){ + param.vendorExtensions.put("has_namespace", "true"); + } + + param.vendorExtensions.put("uppercase_operation_id", underscore(op.operationId).toUpperCase()); + + if (consumesXml) { + param.vendorExtensions.put("consumesXml", true); + } + } + for (CodegenParameter param : op.headerParams) { + // Give header params a name in camel case. CodegenParameters don't have a nameInCamelCase property. + param.vendorExtensions.put("typeName", toModelName(param.baseName)); + } + for (CodegenResponse rsp : op.responses) { + rsp.message = camelize(rsp.message.split("[^A-Za-z ]")[0].replace(" ", "_")); + rsp.vendorExtensions.put("uppercase_operation_id", underscore(op.operationId).toUpperCase()); + rsp.vendorExtensions.put("uppercase_message", underscore(rsp.message).toUpperCase()); + if (rsp.dataType != null) { + rsp.vendorExtensions.put("uppercase_data_type", (rsp.dataType.replace("models::", "")).toUpperCase()); + + if (producesXml) { + rsp.vendorExtensions.put("producesXml", true); + } + + // Check whether we're returning an object with a defined XML namespace. + Object property = rsp.schema; + if ((property != null) && (property instanceof RefProperty)){ + + RefProperty refProperty = (RefProperty) property; + String refName = refProperty.get$ref(); + if (refName.indexOf("#/definitions/") == 0) { + refName = refName.substring("#/definitions/".length()); + } + + Model model = definitions.get(refName); + + if ((model != null) && (model instanceof ModelImpl)) { + Xml xml = ((ModelImpl) model).getXml(); + if ((xml != null) && (xml.getNamespace() != null)){ + rsp.vendorExtensions.put("has_namespace", "true"); + } + } + } + } + for (CodegenProperty header : rsp.headers) { + header.nameInCamelCase = toModelName(header.baseName); + } + } + for (CodegenProperty header : op.responseHeaders) { + header.nameInCamelCase = toModelName(header.baseName); + } + + return op; + } + + @Override + public boolean isDataTypeFile(final String dataType) { + return dataType != null && dataType.equals(typeMapping.get("File").toString()); + } + + @Override + public String getTypeDeclaration(Property p) { + if (p instanceof ArrayProperty) { + ArrayProperty ap = (ArrayProperty) p; + Property inner = ap.getItems(); + String innerType = getTypeDeclaration(inner); + StringBuilder typeDeclaration = new StringBuilder(typeMapping.get("array")).append("<"); + if (inner instanceof RefProperty) { + typeDeclaration.append("models::"); + } + typeDeclaration.append(innerType).append(">"); + return typeDeclaration.toString(); + } else if (p instanceof MapProperty) { + MapProperty mp = (MapProperty) p; + Property inner = mp.getAdditionalProperties(); + String innerType = getTypeDeclaration(inner); + StringBuilder typeDeclaration = new StringBuilder(typeMapping.get("map")).append("<").append(typeMapping.get("string")).append(", "); + if (inner instanceof RefProperty) { + typeDeclaration.append("models::"); + } + typeDeclaration.append(innerType).append(">"); + return typeDeclaration.toString(); + } else if (p instanceof RefProperty) { + String datatype; + try { + RefProperty r = (RefProperty) p; + datatype = r.get$ref(); + if (datatype.indexOf("#/definitions/") == 0) { + datatype = toModelName(datatype.substring("#/definitions/".length())); + } + } catch (Exception e) { + LOGGER.warn("Error obtaining the datatype from RefProperty:" + p + ". Datatype default to Object"); + datatype = "Object"; + LOGGER.error(e.getMessage(), e); + } + return datatype; + } else if (p instanceof FileProperty) { + return typeMapping.get("File").toString(); + } + return super.getTypeDeclaration(p); + } + + @Override + public CodegenParameter fromParameter(Parameter param, Set imports) { + CodegenParameter parameter = super.fromParameter(param, imports); + if(param instanceof BodyParameter) { + BodyParameter bp = (BodyParameter) param; + Model model = bp.getSchema(); + if (model instanceof RefModel) { + String name = ((RefModel) model).getSimpleRef(); + name = toModelName(name); + // We need to be able to look up the model in the model definitions later. + parameter.vendorExtensions.put("uppercase_data_type", name.toUpperCase()); + + name = "models::" + getTypeDeclaration(name); + parameter.baseType = name; + parameter.dataType = name; + + String refName = ((RefModel) model).get$ref(); + if (refName.indexOf("#/definitions/") == 0) { + refName = refName.substring("#/definitions/".length()); + } + parameter.vendorExtensions.put("refName", refName); + + } else if (model instanceof ModelImpl) { + parameter.vendorExtensions.put("refName", ((ModelImpl) model).getName()); + } + } + return parameter; + } + + @Override + public CodegenProperty fromProperty(String name, Property p) { + CodegenProperty property = super.fromProperty(name, p); + if (p instanceof RefProperty) { + property.datatype = "models::" + property.datatype; + } + return property; + } + + @Override + public String toInstantiationType(Property p) { + if (p instanceof ArrayProperty) { + ArrayProperty ap = (ArrayProperty) p; + Property inner = ap.getItems(); + return instantiationTypes.get("array") + "<" + getSwaggerType(inner) + ">"; + } else if (p instanceof MapProperty) { + MapProperty mp = (MapProperty) p; + Property inner = mp.getAdditionalProperties(); + return instantiationTypes.get("map") + "<" + typeMapping.get("string") + ", " + getSwaggerType(inner) + ">"; + } else { + return null; + } + } + + @Override + public CodegenModel fromModel(String name, Model model) { + return fromModel(name, model, null); + } + + @Override + public CodegenModel fromModel(String name, Model model, Map allDefinitions) { + CodegenModel mdl = super.fromModel(name, model, allDefinitions); + mdl.vendorExtensions.put("upperCaseName", name.toUpperCase()); + if (model instanceof ModelImpl) { + ModelImpl modelImpl = (ModelImpl) model; + mdl.dataType = typeMapping.get(modelImpl.getType()); + } + if (model instanceof ArrayModel) { + ArrayModel am = (ArrayModel) model; + if ((am.getItems() != null) && + (am.getItems().getXml() != null)){ + + // If this model's items require wrapping in xml, squirrel + // away the xml name so we can insert it into the relevant model fields. + String xmlName = am.getItems().getXml().getName(); + if (xmlName != null) { + mdl.vendorExtensions.put("itemXmlName", xmlName); + modelXmlNames.put("models::" + mdl.classname, xmlName); + } + } + mdl.arrayModelType = toModelName(mdl.arrayModelType); + } + + if (mdl.xmlNamespace != null) { + additionalProperties.put("usesXmlNamespaces", true); + } + + return mdl; + } + + @Override + public Map postProcessAllModels(Map objs){ + Map newObjs = super.postProcessAllModels(objs); + + //Index all CodegenModels by model name. + HashMap allModels = new HashMap(); + for (Entry entry : objs.entrySet()) { + String modelName = toModelName(entry.getKey()); + Map inner = (Map) entry.getValue(); + List> models = (List>) inner.get("models"); + for (Map mo : models) { + CodegenModel cm = (CodegenModel) mo.get("model"); + allModels.put(modelName, cm); + } + } + + for (Entry entry : allModels.entrySet()){ + String modelName = entry.getKey(); + CodegenModel model = entry.getValue(); + + for(CodegenProperty prop : model.vars){ + String xmlName = modelXmlNames.get(prop.datatype); + if (xmlName != null){ + prop.vendorExtensions.put("itemXmlName", xmlName); + } + } + } + + return newObjs; + } + + @Override + public Map postProcessSupportingFileData(Map objs) { + Swagger swagger = (Swagger)objs.get("swagger"); + if(swagger != null) { + try { + objs.put("swagger-yaml", Yaml.mapper().writeValueAsString(swagger)); + } catch (JsonProcessingException e) { + LOGGER.error(e.getMessage(), e); + } + } + return super.postProcessSupportingFileData(objs); + } + + @Override + public String toDefaultValue(Property p) { + if (p instanceof StringProperty) { + StringProperty dp = (StringProperty) p; + if (dp.getDefault() != null) { + return "\"" + dp.getDefault() + "\".to_string()"; + } + } else if (p instanceof BooleanProperty) { + BooleanProperty dp = (BooleanProperty) p; + if (dp.getDefault() != null) { + if (dp.getDefault().toString().equalsIgnoreCase("false")) + return "false"; + else + return "true"; + } + } else if (p instanceof DoubleProperty) { + DoubleProperty dp = (DoubleProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString(); + } + } else if (p instanceof FloatProperty) { + FloatProperty dp = (FloatProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString(); + } + } else if (p instanceof IntegerProperty) { + IntegerProperty dp = (IntegerProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString(); + } + } else if (p instanceof LongProperty) { + LongProperty dp = (LongProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString(); + } + } + + return null; + } + + @Override + public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { + super.postProcessModelProperty(model, property); + if(!languageSpecificPrimitives.contains(property.datatype)) { + // If we use a more qualified model name, then only camelize the actual type, not the qualifier. + if(property.datatype.contains(":")) { + int position = property.datatype.lastIndexOf(":"); + property.datatype = property.datatype.substring(0, position) + camelize(property.datatype.substring(position)); + } else { + property.datatype = camelize(property.datatype, false); + } + } + + // Handle custom unsigned integer formats. + if ("integer".equals(property.baseType)) { + if ("uint32".equals(property.dataFormat)) { + property.datatype = "u32"; + } else if ("uint64".equals(property.dataFormat)) { + property.datatype = "u64"; + } + } + + property.name = underscore(property.name); + + if (!property.required) { + property.defaultValue = (property.defaultValue != null) ? "Some(" + property.defaultValue + ")" : "None"; + } + } + + @Override + public Map postProcessModels(Map objs) { + return super.postProcessModelsEnum(objs); + + } + + private boolean paramHasXmlNamespace(CodegenParameter param, Map definitions){ + Object refName = param.vendorExtensions.get("refName"); + + if ((refName != null) && (refName instanceof String)) { + String name = (String) refName; + Model model = definitions.get(name); + + if ((model != null) && (model instanceof ModelImpl)) { + Xml xml = ((ModelImpl) model).getXml(); + if ((xml != null) && (xml.getNamespace() != null)) { + return true; + } + } + } + return false; + } + + private String processMimeType(String mimeType){ + // Transform mime type into a form that the hyper mime! macro can handle. + String result = ""; + + String[] split_attributes = mimeType.split(";"); + String media = split_attributes[0]; + String[] mediaTypes = media.split("/"); + + if (mediaTypes.length == 2) { + + if (mediaTypes[0].equals("*")){ + result += "Star"; + } else { + result += escapeText(escapeQuotationMark(initialCaps(mediaTypes[0]))); + } + + result += "/"; + + if (mediaTypes[1].equals("*")) { + result += "Star"; + } else { + result += escapeText(escapeQuotationMark(initialCaps(mediaTypes[1]))); + } + } else { + LOGGER.error("Failed to parse media type: " + + mimeType + + ", media types should have exactly one /"); + } + + if (split_attributes.length == 2) { + String attributes = ""; + String[] attrs = split_attributes[1].split(","); + + for (String attr : attrs) { + String[] keyValuePair =attr.split("="); + if (keyValuePair.length == 2) { + attributes += "(\"" + + escapeText(escapeQuotationMark(keyValuePair[0].trim())) + + "\")=(\"" + + escapeText(escapeQuotationMark(keyValuePair[1].trim())) + + "\")"; + } else { + LOGGER.error("Failed to parse parameter attributes: " + + split_attributes[1] + + ", attributes must be a comma separated list of 'key=value' pairs"); + } + } + result += "; " + attributes; + } + + return result; + } +} diff --git a/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig index 356c310e1dfd..c1cd7c726414 100644 --- a/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig +++ b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig @@ -55,6 +55,7 @@ io.swagger.codegen.languages.RClientCodegen io.swagger.codegen.languages.Rails5ServerCodegen io.swagger.codegen.languages.RestbedCodegen io.swagger.codegen.languages.RubyClientCodegen +io.swagger.codegen.languages.Rust2Codegen io.swagger.codegen.languages.RustClientCodegen io.swagger.codegen.languages.ScalaClientCodegen io.swagger.codegen.languages.ScalatraServerCodegen diff --git a/modules/swagger-codegen/src/main/resources/rust2/Cargo.mustache b/modules/swagger-codegen/src/main/resources/rust2/Cargo.mustache new file mode 100644 index 000000000000..8cab22ff5134 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/rust2/Cargo.mustache @@ -0,0 +1,34 @@ +[package] +name = "{{packageName}}" +version = "{{appVersion}}" +authors = [{{#infoEmail}}"{{infoEmail}}"{{/infoEmail}}] + +[features] +default = ["client", "server"] +client = ["serde_json", {{#usesXml}}"serde-xml-rs", {{/usesXml}}"serde_ignored", "hyper", "hyper-openssl", "uuid"{{#apiHasFile}}, "multipart"{{/apiHasFile}}] +server = ["serde_json", {{#usesXml}}"serde-xml-rs", {{/usesXml}}"serde_ignored", "hyper", "iron", "router", "bodyparser", "urlencoded", "uuid"{{#apiHasFile}}, "multipart"{{/apiHasFile}}] + +[dependencies] +bodyparser = {version = "0.7", optional = true} +chrono = { version = "0.4", features = ["serde"] } +futures = "0.1" +hyper = {version = "0.10", optional = true} +hyper-openssl = {version = "0.2", optional = true } +iron = {version = "0.5", optional = true} +lazy_static = "0.2" +log = "0.3.0" +multipart = {version = "0.13", optional = true} +router = {version = "0.5", optional = true} +serde = "1.0" +serde_derive = "1.0" +serde_ignored = {version = "0.0.4", optional = true} +serde_json = {version = "1.0", optional = true} +swagger = "0.7" +urlencoded = {version = "0.5", optional = true} +uuid = {version = "0.5", optional = true, features = ["serde", "v4"]} +# ToDo: this should be updated to point at the official crate once +# https://github.com/RReverser/serde-xml-rs/pull/45 is accepted upstream +{{#usesXml}}serde-xml-rs = {git = "git://github.com/Metaswitch/serde-xml-rs.git" , branch = "master", optional = true}{{/usesXml}} + +[dev-dependencies] +clap = "2.25" diff --git a/modules/swagger-codegen/src/main/resources/rust2/README.mustache b/modules/swagger-codegen/src/main/resources/rust2/README.mustache new file mode 100644 index 000000000000..c790d7d68b08 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/rust2/README.mustache @@ -0,0 +1,59 @@ +# Rust API for {{packageName}} + +{{#appDescription}} +{{{appDescription}}} +{{/appDescription}} + +## Overview +This client/server was generated by the [swagger-codegen] +(https://github.com/swagger-api/swagger-codegen) project. +By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub. +- + +To see how to make this your own, look here: + +[README](https://github.com/swagger-api/swagger-codegen/blob/master/README.md) + +- API version: {{appVersion}} +- Build date: {{generatedDate}} +{{#infoUrl}} +For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) +{{/infoUrl}} + +## Examples + +Run examples with: + +``` +cargo run --example +``` + +To pass in arguments to the examples, put them after `--`, for example: + +``` +cargo run --example client -- --help +``` + +### Running the server +To run the server, follow these simple steps: + +``` +cargo run --example server +``` + +### Running a client +To run a client, follow one of the following simple steps: + +```{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}} +cargo run --example client {{operationId}}{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} +``` + +### HTTPS +The examples can be run in HTTPS mode by passing in the flag `--https`, for example: + +``` +cargo run --example server -- --https +``` + +This will use the keys/certificates from the examples directory. Note that the server chain is signed with +`CN=localhost`. diff --git a/modules/swagger-codegen/src/main/resources/rust2/cargo-config b/modules/swagger-codegen/src/main/resources/rust2/cargo-config new file mode 100644 index 000000000000..b8acc9c00c8c --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/rust2/cargo-config @@ -0,0 +1,18 @@ +[build] +rustflags = [ + "-W", "missing_docs", # detects missing documentation for public members + + "-W", "trivial_casts", # detects trivial casts which could be removed + + "-W", "trivial_numeric_casts", # detects trivial casts of numeric types which could be removed + + "-W", "unsafe_code", # usage of `unsafe` code + + "-W", "unused_qualifications", # detects unnecessarily qualified names + + "-W", "unused_extern_crates", # extern crates that are never used + + "-W", "unused_import_braces", # unnecessary braces around an imported item + + "-D", "warnings", # all warnings should be denied +] diff --git a/modules/swagger-codegen/src/main/resources/rust2/client.mustache b/modules/swagger-codegen/src/main/resources/rust2/client.mustache new file mode 100644 index 000000000000..c168f502698b --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/rust2/client.mustache @@ -0,0 +1,336 @@ +#![allow(unused_extern_crates)] +extern crate hyper_openssl; +extern crate chrono; +{{#apiHasFile}}extern crate multipart;{{/apiHasFile}} + +{{#apiHasFile}}use multipart::client::lazy::Multipart;{{/apiHasFile}} +use hyper; +use hyper::client::IntoUrl; +use hyper::mime; +use hyper::header::{Headers, ContentType}; +use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value}; +use hyper::Url; +use self::hyper_openssl::openssl; +use futures; +use futures::{Future, Stream}; +use futures::{future, stream}; +use std::borrow::Cow; +use std::io::{Read, Error}; +use std::error; +use std::fmt; +use std::path::Path; +use std::sync::Arc; +use std::str; + +use mimetypes; + +use serde_json; +{{#usesXml}}use serde_xml_rs;{{/usesXml}} + +#[allow(unused_imports)] +use std::collections::{HashMap, BTreeMap}; +#[allow(unused_imports)] +use swagger; + +use swagger::{Context, ApiError, XSpanId}; + +use {Api{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}, + {{operationId}}Response{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} + }; +use models; + +/// Convert input into a base path, e.g. "http://example:123". Also checks the scheme as it goes. +fn into_base_path(input: T, correct_scheme: Option<&'static str>) -> Result { + // First convert to Url, since a base path is a subset of Url. + let url = input.into_url()?; + + let scheme = url.scheme(); + + // Check the scheme if necessary + if let Some(correct_scheme) = correct_scheme { + if scheme != correct_scheme { + return Err(ClientInitError::InvalidScheme); + } + } + + let host = url.host().ok_or_else(|| ClientInitError::MissingHost)?; + let port = url.port().map(|x| format!(":{}", x)).unwrap_or_default(); + Ok(format!("{}://{}{}", scheme, host, port)) +} + +/// A client that implements the API by making HTTP calls out to a server. +#[derive(Clone)] +pub struct Client { + base_path: String, + hyper_client: Arc hyper::client::Client + Sync + Send>, +} + +impl fmt::Debug for Client { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Client {{ base_path: {} }}", self.base_path) + } +} + +impl Client { + pub fn try_new_http(base_path: T) -> Result + where T: IntoUrl + { + Ok(Client { + base_path: into_base_path(base_path, Some("http"))?, + hyper_client: Arc::new(hyper::client::Client::new), + }) + } + + pub fn try_new_https(base_path: T, + ca_certificate: CA) + -> Result + where T: IntoUrl, + CA: AsRef + { + let ca_certificate = ca_certificate.as_ref().to_owned(); + + let https_hyper_client = move || { + // SSL implementation + let mut ssl = openssl::ssl::SslConnectorBuilder::new(openssl::ssl::SslMethod::tls()).unwrap(); + + // Server authentication + ssl.builder_mut().set_ca_file(ca_certificate.clone()).unwrap(); + + let ssl = hyper_openssl::OpensslClient::from(ssl.build()); + let connector = hyper::net::HttpsConnector::new(ssl); + hyper::client::Client::with_connector(connector) + }; + + Ok(Client { + base_path: into_base_path(base_path, Some("https"))?, + hyper_client: Arc::new(https_hyper_client), + }) + } + + pub fn try_new_https_mutual(base_path: T, + ca_certificate: CA, + client_key: K, + client_certificate: C) + -> Result + where T: IntoUrl, + CA: AsRef, + K: AsRef, + C: AsRef + { + let ca_certificate = ca_certificate.as_ref().to_owned(); + let client_key = client_key.as_ref().to_owned(); + let client_certificate = client_certificate.as_ref().to_owned(); + + let https_mutual_hyper_client = move || { + // SSL implementation + let mut ssl = openssl::ssl::SslConnectorBuilder::new(openssl::ssl::SslMethod::tls()).unwrap(); + + // Server authentication + ssl.builder_mut().set_ca_file(ca_certificate.clone()).unwrap(); + + // Client authentication + ssl.builder_mut().set_private_key_file(client_key.clone(), openssl::x509::X509_FILETYPE_PEM).unwrap(); + ssl.builder_mut().set_certificate_chain_file(client_certificate.clone()).unwrap(); + ssl.builder_mut().check_private_key().unwrap(); + + let ssl = hyper_openssl::OpensslClient::from(ssl.build()); + let connector = hyper::net::HttpsConnector::new(ssl); + hyper::client::Client::with_connector(connector) + }; + + Ok(Client { + base_path: into_base_path(base_path, Some("https"))?, + hyper_client: Arc::new(https_mutual_hyper_client) + }) + } + + /// Constructor for creating a `Client` by passing in a pre-made `hyper` client. + /// + /// One should avoid relying on this function if possible, since it adds a dependency on the underlying transport + /// implementation, which it would be better to abstract away. Therefore, using this function may lead to a loss of + /// code generality, which may make it harder to move the application to a serverless environment, for example. + /// + /// The reason for this function's existence is to support legacy test code, which did mocking at the hyper layer. + /// This is not a recommended way to write new tests. If other reasons are found for using this function, they + /// should be mentioned here. + pub fn try_new_with_hyper_client(base_path: T, + hyper_client: Arc hyper::client::Client + Sync + Send>) + -> Result + where T: IntoUrl + { + Ok(Client { + base_path: into_base_path(base_path, None)?, + hyper_client: hyper_client + }) + } +} + +impl Api for Client { +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}} + fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, param_{{paramName}}: {{^required}}{{#isFile}}Box{{#isFile}}, Error=Error> + Send>{{/isFile}}{{/required}}{{/allParams}}, context: &Context) -> Box + Send> { +{{#queryParams}}{{#-first}} + // Query parameters +{{/-first}}{{#required}} let query_{{paramName}} = format!("{{baseName}}={{=<% %>=}}{<% paramName %>}<%={{ }}=%>&", {{paramName}}=param_{{paramName}}{{#isListContainer}}.join(","){{/isListContainer}}{{^isListContainer}}.to_string(){{/isListContainer}}); +{{/required}}{{^required}} let query_{{paramName}} = param_{{paramName}}.map_or_else(String::new, |query| format!("{{baseName}}={{=<% %>=}}{<% paramName %>}<%={{ }}=%>&", {{paramName}}=query{{#isListContainer}}.join(","){{/isListContainer}}{{^isListContainer}}.to_string(){{/isListContainer}})); +{{/required}}{{/queryParams}} + + let url = format!("{}{{basePathWithoutHost}}{{path}}?{{#queryParams}}{{=<% %>=}}{<% paramName %>}<%={{ }}=%>{{/queryParams}}", self.base_path{{#pathParams}}, {{baseName}}=param_{{paramName}}.to_string(){{/pathParams}}{{#queryParams}}, {{paramName}}=query_{{paramName}}{{/queryParams}}); + +{{#vendorExtensions}}{{#hasFile}} // Form data body + let mut multipart = Multipart::new();{{/hasFile}}{{/vendorExtensions}}{{#formParams}}{{#isFile}} + +{{^required}} if let Ok(Some(param_{{paramName}})) = param_{{paramName}}.wait() { {{/required}} +{{^required}} {{/required}} match convert_stream_to_string(param_{{paramName}}) { +{{^required}} {{/required}} Ok(param_{{paramName}}) => { + // Add file to multipart form. + multipart.add_text("{{paramName}}", param_{{paramName}}); + }, +{{^required}} {{/required}} Err(err) => return Box::new(futures::done(Err(err))), +{{^required}} {{/required}} } + {{^required}}}{{/required}}{{/isFile}}{{/formParams}}{{#vendorExtensions}}{{#hasFile}} + + let mut fields = match multipart.prepare() { + Ok(fields) => fields, + Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to build request: {}", err))))), + }; + + let mut body_string = String::new(); + let body = fields.to_body().read_to_string(&mut body_string); + let boundary = fields.boundary(); + let multipart_header = Mime(TopLevel::Multipart, SubLevel::FormData, vec![(Attr::Boundary, Value::Ext(boundary.to_string()))]);{{/hasFile}}{{/vendorExtensions}}{{#bodyParam}}{{#-first}} + // Body parameter +{{/-first}}{{#required}}{{#vendorExtensions}}{{#consumesXml}} +{{^has_namespace}} let body = serde_xml_rs::to_string(¶m_{{paramName}}).expect("impossible to fail to serialize");{{/has_namespace}}{{#has_namespace}} + let mut namespaces = BTreeMap::new(); + // An empty string is used to indicate a global namespace in xmltree. + namespaces.insert("".to_string(), models::namespaces::{{uppercase_data_type}}.clone()); + let body = serde_xml_rs::to_string_with_namespaces(¶m_{{paramName}}, namespaces).expect("impossible to fail to serialize");{{/has_namespace}}{{/consumesXml}}{{^consumesXml}} + let body = serde_json::to_string(¶m_{{paramName}}).expect("impossible to fail to serialize");{{/consumesXml}}{{/vendorExtensions}} +{{/required}}{{^required}} let body = param_{{paramName}}.map(|ref body| { +{{#vendorExtensions}}{{#consumesXml}} +{{^has_namespace}} serde_xml_rs::to_string(body).expect("impossible to fail to serialize"){{/has_namespace}}{{#has_namespace}} + let mut namespaces = BTreeMap::new(); + // An empty string is used to indicate a global namespace in xmltree. + namespaces.insert("".to_string(), models::namespaces::{{uppercase_data_type}}.clone()); + serde_xml_rs::to_string_with_namespaces(body, namespaces).expect("impossible to fail to serialize"){{/has_namespace}}{{/consumesXml}}{{^consumesXml}} + serde_json::to_string(body).expect("impossible to fail to serialize"){{/consumesXml}}{{/vendorExtensions}} + });{{/required}}{{/bodyParam}} + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::{{#vendorExtensions}}{{HttpMethod}}{{/vendorExtensions}}, &url); + let mut custom_headers = hyper::header::Headers::new(); + +{{#bodyParam}}{{#required}} let request = request.body(&body); +{{/required}}{{^required}} let request = match body { + Some(ref body) => request.body(body), + None => request, + }; +{{/required}} + + custom_headers.set(ContentType(mimetypes::requests::{{#vendorExtensions}}{{uppercase_operation_id}}{{/vendorExtensions}}.clone())); +{{/bodyParam}} + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); +{{#headerParams}}{{#-first}} + // Header parameters +{{/-first}}{{^isMapContainer}} header! { (Request{{vendorExtensions.typeName}}, "{{baseName}}") => {{#isListContainer}}({{{baseType}}})*{{/isListContainer}}{{^isListContainer}}[{{{dataType}}}]{{/isListContainer}} } +{{#required}} custom_headers.set(Request{{vendorExtensions.typeName}}(param_{{paramName}}{{#isListContainer}}.clone(){{/isListContainer}})); +{{/required}}{{^required}} param_{{paramName}}.map(|header| custom_headers.set(Request{{vendorExtensions.typeName}}(header{{#isListContainer}}.clone(){{/isListContainer}}))); +{{/required}}{{/isMapContainer}}{{#isMapContainer}} let param_{{paramName}}: Option<{{{dataType}}}> = None; +{{/isMapContainer}}{{/headerParams}} + + let request = request.headers(custom_headers);{{#vendorExtensions}}{{#hasFile}} + let request = request.header(ContentType(multipart_header)) + .body(&body_string); +{{/hasFile}}{{/vendorExtensions}} + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result<{{operationId}}Response, ApiError> { + match response.status.to_u16() { +{{#responses}} + {{code}} => { +{{#dataType}}{{^isFile}} let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?;{{#vendorExtensions}}{{#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 + let body = serde_xml_rs::from_str::<{{{dataType}}}>(&buf) + .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e)))?;{{/producesXml}}{{^producesXml}} + let body = serde_json::from_str::<{{{dataType}}}>(&buf)?; +{{/producesXml}}{{/vendorExtensions}}{{/isFile}}{{#isFile}} let mut buf = Vec::new(); + response.read_to_end(&mut buf).map_err(|e| ApiError(format!("Received error reading response: {}", e)))?; + let body = Box::new(stream::once(Ok(buf)));{{/isFile}} +{{/dataType}} + +{{#headers}} header! { (Response{{nameInCamelCase}}, "{{baseName}}") => [{{{datatype}}}] } + let response_{{name}} = response.headers.get::().ok_or_else(|| "Required response header {{baseName}} for response {{code}} was not found.")?; +{{/headers}} + +{{#dataType}} Ok({{operationId}}Response::{{message}}{{^headers}}(body){{/headers}}{{#headers}}{{#-first}}{ body: body, {{/-first}}{{name}}: response_{{name}}.0.clone(){{^-last}}, {{/-last}}{{#-last}} }{{/-last}}{{/headers}}) +{{/dataType}}{{^dataType}} Ok({{operationId}}Response::{{message}}{{#headers}}{{#-first}}{ {{/-first}}{{^-first}}, {{/-first}}{{name}}: response_{{name}}.0.clone(){{#-last}} }{{/-last}}{{/headers}}) +{{/dataType}} + }, +{{/responses}} + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + }{{#vendorExtensions}}{{#hasFile}} + + // Helper function to convert a Stream into a String. The String can then be used to build the HTTP body. + fn convert_stream_to_string(stream: Box, Error=Error> + Send>) -> Result { + + stream.fold(Vec::new(), |mut body, chunk| { + body.extend(chunk.iter()); + future::ok::,Error>(body) + }).wait() + .map_err(|e| ApiError(format!("Unable to fold stream: {}", e))) + .and_then(|body| String::from_utf8(body) + .map_err(|e| ApiError(format!("Failed to convert utf8 stream to String: {}", e)))) + }{{/hasFile}}{{/vendorExtensions}} + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} +} + +#[derive(Debug)] +pub enum ClientInitError { + InvalidScheme, + InvalidUrl(hyper::error::ParseError), + MissingHost, + SslError(openssl::error::ErrorStack) +} + +impl From for ClientInitError { + fn from(err: hyper::error::ParseError) -> ClientInitError { + ClientInitError::InvalidUrl(err) + } +} + +impl From for ClientInitError { + fn from(err: openssl::error::ErrorStack) -> ClientInitError { + ClientInitError::SslError(err) + } +} + +impl fmt::Display for ClientInitError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + (self as &fmt::Debug).fmt(f) + } +} + +impl error::Error for ClientInitError { + fn description(&self) -> &str { + "Failed to produce a hyper client." + } +} diff --git a/modules/swagger-codegen/src/main/resources/rust2/example-ca.pem b/modules/swagger-codegen/src/main/resources/rust2/example-ca.pem new file mode 100644 index 000000000000..d2317fb5db7d --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/rust2/example-ca.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICtjCCAZ4CCQDpKecRERZ0xDANBgkqhkiG9w0BAQsFADAdMQswCQYDVQQGEwJV +UzEOMAwGA1UEAxMFTXkgQ0EwHhcNMTcwNTIzMTYwMDIzWhcNMTcwNjIyMTYwMDIz +WjAdMQswCQYDVQQGEwJVUzEOMAwGA1UEAxMFTXkgQ0EwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCt66py3x7sCSASRF2D05L5wkNDxAUjQKYx23W8Gbwv +GMGykk89BIdU5LX1JB1cKiUOkoIxfwAYuWc2V/wzTvVV7+11besnk3uX1c9KiqUF +LIX7kn/z5hzS4aelhKvH+MJlSZCSlp1ytpZbwo5GB5Pi2SGH56jDBiBoDRNBVdWL +z4wH7TdrQjqWwNxIZumD5OGMtcfJyuX08iPiEOaslOeoMqzObhvjc9aUgjVjhqyA +FkJGTXsi0oaD7oml+NE+mTNfEeZvEJQpLSjBY0OvQHzuHkyGBShBnfu/9x7/NRwd +WaqsLiF7/re9KDGYdJwP7Cu6uxYfKAyWarp6h2mG/GIdAgMBAAEwDQYJKoZIhvcN +AQELBQADggEBAGIl/VVIafeq/AJOQ9r7TzzB2ABJYr7NZa6bTu5O1jSp1Fonac15 +SZ8gvRxODgH22ZYSqghPG4xzq4J3hkytlQqm57ZEt2I2M3OqIp17Ndcc1xDYzpLl +tA0FrVn6crQTM8vQkTDtGesaCWX+7Fir5dK7HnYWzfpSmsOpST07PfbNisEXKOxG +Dj4lBL1OnhTjsJeymVS1pFvkKkrcEJO+IxFiHL3CDsWjcXB0Z+E1zBtPoYyYsNsO +rBrjUxcZewF4xqWZhpW90Mt61fY2nRgU0uUwHcvDQUqvmzKcsqYa4mPKzfBI5mxo +01Ta96cDD6pS5Y1hOflZ0g84f2g/7xBLLDA= +-----END CERTIFICATE----- diff --git a/modules/swagger-codegen/src/main/resources/rust2/example-client.mustache b/modules/swagger-codegen/src/main/resources/rust2/example-client.mustache new file mode 100644 index 000000000000..2d76fcb47d48 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/rust2/example-client.mustache @@ -0,0 +1,59 @@ +#![allow(missing_docs, unused_variables, trivial_casts)] + +extern crate {{externCrateName}}; +#[allow(unused_extern_crates)] +extern crate futures; +#[allow(unused_extern_crates)] +extern crate swagger; +#[allow(unused_extern_crates)] +extern crate uuid; +extern crate clap; + +#[allow(unused_imports)] +use futures::{Future, future, Stream, stream}; +#[allow(unused_imports)] +use {{externCrateName}}::{ApiNoContext, ContextWrapperExt, + ApiError{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}, + {{operationId}}Response{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} + }; +use clap::{App, Arg}; + +fn main() { + let matches = App::new("client") + .arg(Arg::with_name("operation") + .help("Sets the operation to run") + .possible_values(&[ +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}{{#vendorExtensions}}{{^noClientExample}} "{{operationId}}", +{{/noClientExample}}{{/vendorExtensions}}{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}]) + .required(true) + .index(1)) + .arg(Arg::with_name("https") + .long("https") + .help("Whether to use HTTPS or not")) + .get_matches(); + + let client = if matches.is_present("https") { + // Using Simple HTTPS + {{externCrateName}}::Client::try_new_https("https://localhost:{{serverPort}}", "examples/ca.pem").expect("Failed to create HTTPS client") + } else { + // Using HTTP + {{externCrateName}}::Client::try_new_http("http://localhost:{{serverPort}}").expect("Failed to create HTTP client") + }; + + // Using a non-default `Context` is not required; this is just an example! + let client = client.with_context({{externCrateName}}::Context::new_with_span_id(self::uuid::Uuid::new_v4().to_string())); + + match matches.value_of("operation") { +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}} + {{#vendorExtensions}}{{#noClientExample}}// Disabled because there's no example. + // {{/noClientExample}}Some("{{operationId}}") => { + {{#noClientExample}}// {{/noClientExample}} let result = client.{{operation_id}}{{/vendorExtensions}}({{#allParams}}{{^-first}}, {{/-first}}{{#vendorExtensions}}{{{example}}}{{/vendorExtensions}}{{/allParams}}).wait(); + {{#vendorExtensions}}{{#noClientExample}}// {{/noClientExample}}{{/vendorExtensions}} println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + {{#vendorExtensions}}{{#noClientExample}}// {{/noClientExample}}{{/vendorExtensions}} }, +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} + _ => { + panic!("Invalid operation provided") + } + } +} + diff --git a/modules/swagger-codegen/src/main/resources/rust2/example-server-chain.pem b/modules/swagger-codegen/src/main/resources/rust2/example-server-chain.pem new file mode 100644 index 000000000000..47d7e2014046 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/rust2/example-server-chain.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 1 (0x0) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, CN=My CA + Validity + Not Before: May 23 16:00:23 2017 GMT + Not After : Apr 29 16:00:23 2117 GMT + Subject: CN=localhost, C=US + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:c9:d4:43:60:50:fc:d6:0f:38:4d:5d:5e:aa:7c: + c0:5e:a9:ec:d9:93:78:d3:93:72:28:41:f5:08:a5: + ea:ac:67:07:d7:1f:f7:7d:74:69:7e:46:89:20:4b: + 7a:2d:9b:02:08:e7:6f:0f:1d:0c:0f:c7:60:69:19: + 4b:df:7e:ca:75:94:0b:49:71:e3:6d:f2:e8:79:fd: + ed:0a:94:67:55:f3:ca:6b:61:ba:58:b7:2e:dd:7b: + ca:b9:02:9f:24:36:ac:26:8f:04:8f:81:c8:35:10: + f4:aa:33:b2:24:16:f8:f7:1e:ea:f7:16:fe:fa:34: + c3:dd:bb:2c:ba:7a:df:4d:e2:da:1e:e5:d2:28:44: + 6e:c8:96:e0:fd:09:0c:14:0c:31:dc:e0:ca:c1:a7: + 9b:bf:16:8c:f7:36:3f:1b:2e:dd:90:eb:45:78:51: + bf:59:22:1e:c6:8c:0a:69:88:e5:03:5e:73:b7:fc: + 93:7f:1b:46:1b:97:68:c5:c0:8b:35:1f:bb:1e:67: + 7f:55:b7:3b:55:3f:ea:f2:ca:db:cc:52:cd:16:89: + db:15:47:bd:f2:cd:6c:7a:d7:b4:1a:ac:c8:15:6c: + 6a:fb:77:c4:e9:f2:30:e0:14:24:66:65:6f:2a:e5: + 2d:cc:f6:81:ae:57:c8:d1:9b:38:90:dc:60:93:02: + 5e:cb + Exponent: 65537 (0x10001) + Signature Algorithm: sha256WithRSAEncryption + 1c:7c:39:e8:3d:49:b2:09:1e:68:5a:2f:74:18:f4:63:b5:8c: + f6:e6:a1:e3:4d:95:90:99:ef:32:5c:34:40:e8:55:13:0e:e0: + 1c:be:cd:ab:3f:64:38:99:5e:2b:c1:81:53:a0:18:a8:f6:ee: + 6a:33:73:6c:9a:73:9d:86:08:5d:c7:11:38:46:4c:cd:a0:47: + 37:8f:fe:a6:50:a9:02:21:99:42:86:5e:47:fe:65:56:60:1d: + 16:53:86:bd:e4:63:c5:69:cf:fa:30:51:ab:a1:c3:50:53:cc: + 66:1c:4c:ff:3f:2a:39:4d:a2:8f:9d:d1:a7:8b:22:e4:78:69: + 24:06:83:4d:cc:0a:c0:87:69:9b:bc:80:a9:d2:b7:a5:23:84: + 7e:a2:32:26:7c:78:0e:bd:db:cd:3b:69:18:33:b8:44:ef:96: + b4:99:86:ee:06:bd:51:1c:c7:a1:a4:0c:c4:4c:51:a0:df:ac: + 14:07:88:8e:d7:39:45:fe:52:e0:a3:4c:db:5d:7a:ab:4d:e4: + ca:06:e8:bd:74:6f:46:e7:93:4a:4f:1b:67:e7:a5:9f:ef:9c: + 02:49:d1:f2:d5:e9:53:ee:09:21:ac:08:c8:15:f7:af:35:b9: + 4f:11:0f:43:ae:46:8e:fd:5b:8d:a3:4e:a7:2c:b7:25:ed:e4: + e5:94:1d:e3 +-----BEGIN CERTIFICATE----- +MIICtTCCAZ0CAhAAMA0GCSqGSIb3DQEBCwUAMB0xCzAJBgNVBAYTAlVTMQ4wDAYD +VQQDEwVNeSBDQTAgFw0xNzA1MjMxNjAwMjNaGA8yMTE3MDQyOTE2MDAyM1owITES +MBAGA1UEAxMJbG9jYWxob3N0MQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAMnUQ2BQ/NYPOE1dXqp8wF6p7NmTeNOTcihB9Qil6qxn +B9cf9310aX5GiSBLei2bAgjnbw8dDA/HYGkZS99+ynWUC0lx423y6Hn97QqUZ1Xz +ymthuli3Lt17yrkCnyQ2rCaPBI+ByDUQ9KozsiQW+Pce6vcW/vo0w927LLp6303i +2h7l0ihEbsiW4P0JDBQMMdzgysGnm78WjPc2Pxsu3ZDrRXhRv1kiHsaMCmmI5QNe +c7f8k38bRhuXaMXAizUfux5nf1W3O1U/6vLK28xSzRaJ2xVHvfLNbHrXtBqsyBVs +avt3xOnyMOAUJGZlbyrlLcz2ga5XyNGbOJDcYJMCXssCAwEAATANBgkqhkiG9w0B +AQsFAAOCAQEAHHw56D1JsgkeaFovdBj0Y7WM9uah402VkJnvMlw0QOhVEw7gHL7N +qz9kOJleK8GBU6AYqPbuajNzbJpznYYIXccROEZMzaBHN4/+plCpAiGZQoZeR/5l +VmAdFlOGveRjxWnP+jBRq6HDUFPMZhxM/z8qOU2ij53Rp4si5HhpJAaDTcwKwIdp +m7yAqdK3pSOEfqIyJnx4Dr3bzTtpGDO4RO+WtJmG7ga9URzHoaQMxExRoN+sFAeI +jtc5Rf5S4KNM2116q03kygbovXRvRueTSk8bZ+eln++cAknR8tXpU+4JIawIyBX3 +rzW5TxEPQ65Gjv1bjaNOpyy3Je3k5ZQd4w== +-----END CERTIFICATE----- diff --git a/modules/swagger-codegen/src/main/resources/rust2/example-server-key.pem b/modules/swagger-codegen/src/main/resources/rust2/example-server-key.pem new file mode 100644 index 000000000000..29c006829229 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/rust2/example-server-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDJ1ENgUPzWDzhN +XV6qfMBeqezZk3jTk3IoQfUIpeqsZwfXH/d9dGl+RokgS3otmwII528PHQwPx2Bp +GUvffsp1lAtJceNt8uh5/e0KlGdV88prYbpYty7de8q5Ap8kNqwmjwSPgcg1EPSq +M7IkFvj3Hur3Fv76NMPduyy6et9N4toe5dIoRG7IluD9CQwUDDHc4MrBp5u/Foz3 +Nj8bLt2Q60V4Ub9ZIh7GjAppiOUDXnO3/JN/G0Ybl2jFwIs1H7seZ39VtztVP+ry +ytvMUs0WidsVR73yzWx617QarMgVbGr7d8Tp8jDgFCRmZW8q5S3M9oGuV8jRmziQ +3GCTAl7LAgMBAAECggEBAKEd1q9j14KWYc64s6KLthGbutyxsinMMbxbct11fdIk +6YhdF3fJ35ETg9IJDr6rWEN9ZRX+jStncNpVfFEs6ThVd3Eo/nI+EEGaaIkikR93 +X2a7fEPn7/yVHu70XdBN6L1bPDvHUeiy4W2hmRrgT90OjGm1rNRWHOm7yugOwIZu +HclzbR9Ca7EInFnotUiDQm9sw9VKHbJHqWx6OORdZrxR2ytYs0Qkq0XpGMvti2HW +7WAmKTg5QM8myXW7+/4iqb/u68wVBR2BBalShKmIf7lim9O3W2a1RjDdsvm/wNe9 +I+D+Iq825vpqkKXcrxYlpVg7hYiaQaW/MNsEb7lQRjECgYEA/RJYby0POW+/k0Jn +jO8UmJVEMiuGa8WIUu/JJWMOmzRCukjSRNQOkt7niQrZPJYE8W6clM6RJTolWf9L +IL6mIb+mRaoudUk8SHGDq7ho1iMg9GK8lhYxvKh1Q6uv8EyVSkgLknAEY0NANKC1 +zNdU5Dhven9aRX2gq9vP4XwMz2MCgYEAzCogQ7IFk+gkp3k491dOZnrGRoRCfuzo +4CJtyKFgOSd7BjmpcKkj0IPfVBjw6GjMIxfQRMTQmxAjjWevH45vG8l0Iiwz/gSp +81b5nsDEX5uv2Olcmcz5zxRFy36jOZ9ihMWinxcIlT2oDbyCdbruDKZq9ieJ9S8g +4qGx0OkwE3kCgYEA7CmAiU89U9YqqttfEq/RQoqY91CSwmO10d+ej9seuEtOsdRf +FIfnibulycdr7hP5TOxyBpO1802NqayJiWcgVYIpQf2MGTtcnCYCP+95NcvWZvj1 +EAJqK6nwtFO1fcOZ1ZXh5qfOEGujsPkAbsXLnKXlsiTCMvMHSxl3pu5Cbg0CgYBf +JjbZNctRrjv+7Qj2hPLd4dQsIxGWc7ToWENP4J2mpVa5hQAJqFovoHXhjKohtk2F +AWEn243Y5oGbMjo0e74edhmwn2cvuF64MM2vBem/ISCn98IXT6cQskMA3qkVfsl8 +VVs/x41ReGWs2TD3y0GMFbb9t1mdMfSiincDhNnKCQKBgGfeT4jKyYeCoCw4OLI1 +G75Gd0METt/IkppwODPpNwj3Rp9I5jctWZFA/3wCX/zk0HgBeou5AFNS4nQZ/X/L +L9axbSdR7UJTGkT1r4gu3rLkPV4Tk+8XM03/JT2cofMlzQBuhvl1Pn4SgKowz7hl +lS76ECw4Av3T0S34VW9Z5oye +-----END PRIVATE KEY----- diff --git a/modules/swagger-codegen/src/main/resources/rust2/example-server.mustache b/modules/swagger-codegen/src/main/resources/rust2/example-server.mustache new file mode 100644 index 000000000000..7da74ee26e78 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/rust2/example-server.mustache @@ -0,0 +1,58 @@ +#![allow(missing_docs)] + +extern crate {{externCrateName}}; +extern crate iron; +extern crate futures; +extern crate hyper_openssl; +extern crate clap; +extern crate swagger; + +use hyper_openssl::OpensslServer; +use hyper_openssl::openssl::x509::X509_FILETYPE_PEM; +use hyper_openssl::openssl::ssl::{SslAcceptorBuilder, SslMethod}; +use hyper_openssl::openssl::error::ErrorStack; +use clap::{App, Arg}; +use iron::{Iron, Chain}; +use swagger::auth::AllowAllMiddleware; + +// Import the module that defines the Server struct. +mod server_lib; + +/// Builds an SSL implementation for Simple HTTPS from some hard-coded file names +fn ssl() -> Result { + let mut ssl = SslAcceptorBuilder::mozilla_intermediate_raw(SslMethod::tls())?; + + // Server authentication + ssl.builder_mut().set_private_key_file("examples/server-key.pem", X509_FILETYPE_PEM)?; + ssl.builder_mut().set_certificate_chain_file("examples/server-chain.pem")?; + ssl.builder_mut().check_private_key()?; + + Ok(OpensslServer::from(ssl.build())) +} + +/// Create custom server, wire it to the autogenerated router, +/// and pass it to the web server. +fn main() { + let matches = App::new("server") + .arg(Arg::with_name("https") + .long("https") + .help("Whether to use HTTPS or not")) + .get_matches(); + + let server = server_lib::Server{}; + let router = {{externCrateName}}::router(server); + + let mut chain = Chain::new(router); + chain.link_before({{externCrateName}}::server::ExtractAuthData); + // add authentication middlewares into the chain here + // for the purpose of this example, pretend we have authenticated a user + chain.link_before(AllowAllMiddleware::new("cosmo")); + + if matches.is_present("https") { + // Using Simple HTTPS + Iron::new(chain).https("localhost:{{serverPort}}", ssl().expect("Failed to load SSL keys")).expect("Failed to start HTTPS server"); + } else { + // Using HTTP + Iron::new(chain).http("localhost:{{serverPort}}").expect("Failed to start HTTP server"); + } +} diff --git a/modules/swagger-codegen/src/main/resources/rust2/example-server_lib.mustache b/modules/swagger-codegen/src/main/resources/rust2/example-server_lib.mustache new file mode 100644 index 000000000000..b9288a38cc80 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/rust2/example-server_lib.mustache @@ -0,0 +1,31 @@ +#![allow(missing_docs, unused_extern_crates)] +extern crate chrono; +extern crate swagger; + +use futures::{self, Future}; +{{#apiHasFile}}use futures::Stream;{{/apiHasFile}} + +#[allow(unused_imports)] +use std::collections::HashMap; +{{#apiHasFile}}use std::io::Error;{{/apiHasFile}} + +use {{externCrateName}}::{Api, ApiError, Context{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}, + {{operationId}}Response{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} +}; +#[allow(unused_imports)] +use {{externCrateName}}::models; + +#[derive(Copy, Clone)] +pub struct Server; + +impl Api for Server { +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}} +{{#summary}} /// {{{summary}}}{{/summary}} + fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, {{paramName}}: {{^required}}{{#isFile}}Box{{#isFile}}, Error=Error> + Send>{{/isFile}}{{/required}}{{/allParams}}, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("{{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}({{#allParams}}{{^isFile}}{{#vendorExtensions}}{{{formatString}}}{{/vendorExtensions}}{{#hasMore}}, {{/hasMore}}{{/isFile}}{{/allParams}}) - X-Span-ID: {:?}"{{#allParams}}{{^isFile}}, {{paramName}}{{/isFile}}{{/allParams}}, context.x_span_id.unwrap_or(String::from("")).clone());{{#allParams}}{{#isFile}} + let _ = {{paramName}}; //Suppresses unused param warning{{/isFile}}{{/allParams}} + Box::new(futures::failed("Generic failure".into())) + } +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} +} diff --git a/modules/swagger-codegen/src/main/resources/rust2/gitignore b/modules/swagger-codegen/src/main/resources/rust2/gitignore new file mode 100644 index 000000000000..a9d37c560c6a --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/rust2/gitignore @@ -0,0 +1,2 @@ +target +Cargo.lock diff --git a/modules/swagger-codegen/src/main/resources/rust2/lib.mustache b/modules/swagger-codegen/src/main/resources/rust2/lib.mustache new file mode 100644 index 000000000000..2c913125401d --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/rust2/lib.mustache @@ -0,0 +1,96 @@ +#![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)] +extern crate serde; +#[macro_use] +extern crate serde_derive; +extern crate serde_json; +{{#usesXml}}extern crate serde_xml_rs;{{/usesXml}} +extern crate futures; +extern crate chrono; +{{#apiHasFile}}extern crate multipart;{{/apiHasFile}} +#[macro_use] +extern crate lazy_static; +#[macro_use] +extern crate log; + +// Logically this should be in the client and server modules, but rust doesn't allow `macro_use` from a module. +#[cfg(any(feature = "client", feature = "server"))] +#[macro_use] +extern crate hyper; + +extern crate swagger; + +use futures::Stream; +use std::io::Error; + +#[allow(unused_imports)] +use std::collections::HashMap; + +pub use futures::Future; + +#[cfg(any(feature = "client", feature = "server"))] +mod mimetypes; + +pub use swagger::{ApiError, Context, ContextWrapper}; + +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}} +{{^isResponseFile}} +#[derive(Debug, PartialEq)] +{{/isResponseFile}} +pub enum {{operationId}}Response { +{{#responses}} {{message}} {{#dataType}}{{^headers}}( {{{dataType}}} ) {{/headers}}{{#headers}}{{#-first}}{ body: {{{dataType}}}{{/-first}}{{/headers}}{{/dataType}}{{#headers}}{{#-first}}{{^dataType}} { {{/dataType}}{{#dataType}}, {{/dataType}}{{/-first}}{{^-first}}, {{/-first}}{{name}}: {{{datatype}}}{{#-last}} } {{/-last}}{{/headers}}, +{{/responses}} +} +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} + +/// API +pub trait Api { +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}} +{{#summary}} /// {{{summary}}}{{/summary}} + fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, {{paramName}}: {{^required}}{{#isFile}}Box{{#isFile}}, Error=Error> + Send>{{/isFile}}{{/required}}{{/allParams}}, context: &Context) -> Box + Send>; +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} +} + +/// API without a `Context` +pub trait ApiNoContext { +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}} +{{#summary}} /// {{{summary}}}{{/summary}} + fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, {{paramName}}: {{^required}}{{#isFile}}Box{{#isFile}}, Error=Error> + Send>{{/isFile}}{{/required}}{{/allParams}}) -> Box + Send>; +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} +} + +/// Trait to extend an API to make it easy to bind it to a context. +pub trait ContextWrapperExt<'a> where Self: Sized { + /// Binds this API to a context. + fn with_context(self: &'a Self, context: Context) -> ContextWrapper<'a, Self>; +} + +impl<'a, T: Api + Sized> ContextWrapperExt<'a> for T { + fn with_context(self: &'a T, context: Context) -> ContextWrapper<'a, T> { + ContextWrapper::::new(self, context) + } +} + +impl<'a, T: Api> ApiNoContext for ContextWrapper<'a, T> { +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}} +{{#summary}} /// {{{summary}}}{{/summary}} + fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, {{paramName}}: {{^required}}{{#isFile}}Box{{#isFile}}, Error=Error> + Send>{{/isFile}}{{/required}}{{/allParams}}) -> Box + Send> { + self.api().{{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}({{#allParams}}{{paramName}}, {{/allParams}}&self.context()) + } +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} +} + +#[cfg(feature = "client")] +pub mod client; + +// Re-export Client as a top-level name +#[cfg(feature = "client")] +pub use self::client::Client; + +#[cfg(feature = "server")] +pub mod server; + +// Re-export router() as a top-level name +#[cfg(feature = "server")] +pub use self::server::router; + +pub mod models; diff --git a/modules/swagger-codegen/src/main/resources/rust2/mimetypes.mustache b/modules/swagger-codegen/src/main/resources/rust2/mimetypes.mustache new file mode 100644 index 000000000000..336e12dfe649 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/rust2/mimetypes.mustache @@ -0,0 +1,21 @@ +/// mime types for requests and responses + +pub mod responses { + use hyper::mime::*; + + // The macro is called per-operation to beat the recursion limit +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}{{#responses}}{{#produces}}{{#-first}}{{#dataType}} /// Create Mime objects for the response content types for {{operationId}} + lazy_static! { + pub static ref {{#vendorExtensions}}{{uppercase_operation_id}}_{{uppercase_message}}{{/vendorExtensions}}: Mime = mime!({{{mediaType}}}); + } +{{/dataType}}{{/-first}}{{/produces}}{{/responses}}{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} +} + +pub mod requests { + use hyper::mime::*; +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}{{#bodyParam}} /// Create Mime objects for the request content types for {{operationId}} + lazy_static! { + pub static ref {{#vendorExtensions}}{{uppercase_operation_id}}{{/vendorExtensions}}: Mime = mime!({{#consumes}}{{#-first}}{{{mediaType}}}{{/-first}}{{/consumes}}{{^consumes}}Application/Json{{/consumes}}); + } +{{/bodyParam}}{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} +} diff --git a/modules/swagger-codegen/src/main/resources/rust2/models.mustache b/modules/swagger-codegen/src/main/resources/rust2/models.mustache new file mode 100755 index 000000000000..4c31931dde02 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/rust2/models.mustache @@ -0,0 +1,175 @@ +#![allow(unused_imports, unused_qualifications, unused_extern_crates)] +extern crate chrono; +extern crate uuid; + +{{#usesXml}}use serde_xml_rs;{{/usesXml}} +use serde::ser::Serializer; + +use std::collections::HashMap; +use models; +use swagger; + +{{#models}}{{#model}} +{{#description}}/// {{{description}}} +{{/description}}{{#isEnum}}/// Enumeration of values. +/// Since this enum's variants do not hold data, we can easily define them them as `#[repr(C)]` +/// which helps with FFI. +#[allow(non_camel_case_types)] +#[repr(C)] +#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize)]{{#xmlName}} +#[serde(rename = "{{xmlName}}")]{{/xmlName}} +pub enum {{classname}} { {{#allowableValues}}{{#enumVars}} + #[serde(rename = {{{value}}})] + {{name}},{{/enumVars}}{{/allowableValues}} +} + +impl ::std::fmt::Display for {{classname}} { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match *self { {{#allowableValues}}{{#enumVars}} + {{classname}}::{{name}} => write!(f, "{}", {{{value}}}),{{/enumVars}}{{/allowableValues}} + } + } +} + +impl ::std::str::FromStr for {{classname}} { + type Err = (); + fn from_str(s: &str) -> Result { + match s { +{{#allowableValues}}{{#enumVars}} {{{value}}} => Ok({{classname}}::{{name}}), +{{/enumVars}}{{/allowableValues}} _ => Err(()), + } + } +} +{{/isEnum}}{{^isEnum}}{{#dataType}}{{! newtype}}#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)] +{{#xmlName}}#[serde(rename = "{{xmlName}}")]{{/xmlName}} +pub struct {{classname}}({{{dataType}}}); + +impl ::std::convert::From<{{dataType}}> for {{classname}} { + fn from(x: {{dataType}}) -> Self { + {{classname}}(x) + } +} + +impl ::std::convert::From<{{classname}}> for {{dataType}} { + fn from(x: {{classname}}) -> Self { + x.0 + } +} + +impl ::std::ops::Deref for {{classname}} { + type Target = {{{dataType}}}; + fn deref(&self) -> &{{{dataType}}} { + &self.0 + } +} + +impl ::std::ops::DerefMut for {{classname}} { + fn deref_mut(&mut self) -> &mut {{{dataType}}} { + &mut self.0 + } +} + +{{/dataType}}{{^dataType}}{{#arrayModelType}}{{#vendorExtensions}}{{#itemXmlName}}// Utility function for wrapping list elements when serializing xml +fn wrap_in_{{itemXmlName}}(item: &Vec<{{arrayModelType}}>, serializer: S) -> Result +where + S: Serializer, +{ + serde_xml_rs::wrap_primitives(item, serializer, "{{itemXmlName}}") +} + +{{/itemXmlName}}{{/vendorExtensions}}{{! vec}}#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct {{classname}}(Vec<{{{arrayModelType}}}>); + +impl ::std::convert::From> for {{classname}} { + fn from(x: Vec<{{arrayModelType}}>) -> Self { + {{classname}}(x) + } +} + +impl ::std::convert::From<{{classname}}> for Vec<{{arrayModelType}}> { + fn from(x: {{classname}}) -> Self { + x.0 + } +} + +impl ::std::iter::FromIterator<{{arrayModelType}}> for {{classname}} { + fn from_iter>(u: U) -> Self { + {{classname}}(Vec::<{{arrayModelType}}>::from_iter(u)) + } +} + +impl ::std::iter::IntoIterator for {{classname}} { + type Item = {{arrayModelType}}; + type IntoIter = ::std::vec::IntoIter<{{arrayModelType}}>; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +impl<'a> ::std::iter::IntoIterator for &'a {{classname}} { + type Item = &'a {{arrayModelType}}; + type IntoIter = ::std::slice::Iter<'a, {{arrayModelType}}>; + + fn into_iter(self) -> Self::IntoIter { + (&self.0).into_iter() + } +} + +impl<'a> ::std::iter::IntoIterator for &'a mut {{classname}} { + type Item = &'a mut {{arrayModelType}}; + type IntoIter = ::std::slice::IterMut<'a, {{arrayModelType}}>; + + fn into_iter(self) -> Self::IntoIter { + (&mut self.0).into_iter() + } +} + +impl ::std::ops::Deref for {{classname}} { + type Target = Vec<{{{arrayModelType}}}>; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl ::std::ops::DerefMut for {{classname}} { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +{{/arrayModelType}}{{^arrayModelType}}{{! general struct}}#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]{{#xmlName}} +#[serde(rename = "{{xmlName}}")]{{/xmlName}} +pub struct {{classname}} { +{{#vars}}{{#description}} /// {{{description}}} +{{/description}}{{#isEnum}} // Note: inline enums are not fully supported by swagger-codegen +{{/isEnum}} #[serde(rename = "{{baseName}}")]{{#vendorExtensions}}{{#itemXmlName}} + #[serde(serialize_with = "wrap_in_{{itemXmlName}}")]{{/itemXmlName}}{{/vendorExtensions}}{{#required}} + pub {{name}}: {{#vendorExtensions}}{{#x-nullable}}swagger::Nullable<{{/x-nullable}}{{/vendorExtensions}}{{{datatype}}}{{#vendorExtensions}}{{#x-nullable}}>{{/x-nullable}}{{/vendorExtensions}}, +{{/required}}{{^required}}{{#vendorExtensions}}{{#x-nullable}} #[serde(deserialize_with = "swagger::nullable_format::deserialize_optional_nullable")] + #[serde(default = "swagger::nullable_format::default_optional_nullable")] +{{/x-nullable}}{{/vendorExtensions}} + #[serde(skip_serializing_if="Option::is_none")] + pub {{name}}: Option<{{#vendorExtensions}}{{#x-nullable}}swagger::Nullable<{{/x-nullable}}{{/vendorExtensions}}{{#isListContainer}}Vec<{{#items}}{{{datatype}}}{{/items}}>{{/isListContainer}}{{^isListContainer}}{{{datatype}}}{{/isListContainer}}{{#vendorExtensions}}{{#x-nullable}}>{{/x-nullable}}{{/vendorExtensions}}>, +{{/required}} + +{{/vars}} +} + +impl {{classname}} { + pub fn new({{#vars}}{{^defaultValue}}{{name}}: {{#vendorExtensions}}{{#x-nullable}}swagger::Nullable<{{/x-nullable}}{{/vendorExtensions}}{{{datatype}}}{{#vendorExtensions}}{{#x-nullable}}>{{/x-nullable}}{{/vendorExtensions}}, {{/defaultValue}}{{/vars}}) -> {{classname}} { + {{classname}} { +{{#vars}} {{name}}: {{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}{{name}}{{/defaultValue}}, +{{/vars}} + } + } +} +{{/arrayModelType}}{{/dataType}}{{/isEnum}}{{/model}}{{/models}}{{#usesXmlNamespaces}} +//XML namespaces +pub mod namespaces { + lazy_static!{ + {{#models}}{{#model}}{{#xmlNamespace}}pub static ref {{#vendorExtensions}}{{upperCaseName}}{{/vendorExtensions}}: String = "{{xmlNamespace}}".to_string(); + {{/xmlNamespace}}{{/model}}{{/models}} + } +} +{{/usesXmlNamespaces}} diff --git a/modules/swagger-codegen/src/main/resources/rust2/server.mustache b/modules/swagger-codegen/src/main/resources/rust2/server.mustache new file mode 100644 index 000000000000..6091527455fd --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/rust2/server.mustache @@ -0,0 +1,338 @@ +#![allow(unused_extern_crates)] +extern crate serde_ignored; +extern crate iron; +extern crate router; +extern crate bodyparser; +extern crate urlencoded; +extern crate uuid; +extern crate chrono; +{{#apiHasFile}}extern crate multipart;{{/apiHasFile}} + +use futures::Future; +use futures::future; +use futures::{stream, Stream}; +use hyper; +use hyper::header::{Headers, ContentType}; +use self::iron::prelude::*; +use self::iron::{status, modifiers, BeforeMiddleware}; +use self::iron::url::percent_encoding::percent_decode; +use self::router::Router; +use self::urlencoded::UrlEncodedQuery; +use mimetypes; +{{#apiHasFile}}use multipart::server::{Multipart, SaveResult};{{/apiHasFile}} + +use serde_json; +{{#usesXml}}use serde_xml_rs;{{/usesXml}} + +#[allow(unused_imports)] +use std::collections::{HashMap, BTreeMap}; +#[allow(unused_imports)] +use swagger; +use std::io::Error; + +#[allow(unused_imports)] +use std::collections::BTreeSet; + +use swagger::auth::{Authorization, AuthData, Scopes}; +use swagger::{ApiError, Context, XSpanId}; + +use {Api{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}, + {{operationId}}Response{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} + }; +#[allow(unused_imports)] +use models; + +header! { (Warning, "Warning") => [String] } + +/// Create a new router for `Api` +pub fn router(api: T) -> Router where T: Api + Send + Sync + Clone + 'static { + let mut router = Router::new(); + add_routes(&mut router, api); + router +} + +/// Add routes for `Api` to a provided router. +/// +/// Note that these routes are added straight onto the router. This means that if the router +/// already has a route for an endpoint which clashes with those provided by this API, then the +/// old route will be lost. +/// +/// It is generally a bad idea to add routes in this way to an existing router, which may have +/// routes on it for other APIs. Distinct APIs should be behind distinct paths to encourage +/// separation of interfaces, which this function does not enforce. APIs should not overlap. +/// +/// Alternative approaches include: +/// +/// - generate an `iron::middleware::Handler` (usually a `router::Router` or +/// `iron::middleware::chain`) for each interface, and add those handlers inside an existing +/// router, mounted at different paths - so the interfaces are separated by path +/// - use a different instance of `iron::Iron` for each interface - so the interfaces are +/// separated by the address/port they listen on +/// +/// This function exists to allow legacy code, which doesn't separate its APIs properly, to make +/// use of this crate. +#[deprecated(note="APIs should not overlap - only for use in legacy code.")] +pub fn route(router: &mut Router, api: T) where T: Api + Send + Sync + Clone + 'static { + add_routes(router, api) +} + +/// Add routes for `Api` to a provided router +fn add_routes(router: &mut Router, api: T) where T: Api + Send + Sync + Clone + 'static { +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}} + let api_clone = api.clone(); + router.{{#vendorExtensions}}{{httpmethod}}{{/vendorExtensions}}( + "{{#vendorExtensions}}{{basePathWithoutHost}}{{path}}{{/vendorExtensions}}", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + {{#hasAuthMethods}} + let authorization = context.authorization.as_ref().ok_or_else(|| { + Response::with(( + status::Forbidden, + "Unauthenticated".to_string() + )) + })?; + + {{#authMethods}} + {{#isOAuth}} + // Authorization + if let Scopes::Some(ref scopes) = authorization.scopes { + let required_scopes: BTreeSet = vec![ + {{#scopes}} + "{{scope}}".to_string(), // {{description}} + {{/scopes}} + ].into_iter().collect(); + + if !required_scopes.is_subset(scopes) { + let missing_scopes = required_scopes.difference(scopes); + return Err(Response::with(( + status::Forbidden, + missing_scopes.fold( + "Insufficient authorization, missing scopes".to_string(), + |s, scope| format!("{} {}", s, scope) + ) + ))); + } + } + {{/isOAuth}} + {{/authMethods}} + {{/hasAuthMethods}} + +{{#pathParams}}{{#-first}} + // Path parameters +{{/-first}} let param_{{paramName}} = { + let param = req.extensions.get::().ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("{{baseName}}").ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter {{baseName}}".to_string())))?; + percent_decode(param.as_bytes()).decode_utf8() + .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? + .parse().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter {{baseName}}: {}", e))))? + }; +{{/pathParams}} +{{#headerParams}}{{#-first}} + // Header parameters +{{/-first}} header! { (Request{{vendorExtensions.typeName}}, "{{baseName}}") => {{#isListContainer}}({{{baseType}}})*{{/isListContainer}}{{^isListContainer}}[{{{dataType}}}]{{/isListContainer}} } +{{#required}} let param_{{paramName}} = req.headers.get::().ok_or_else(|| Response::with((status::BadRequest, "Missing or invalid required header {{baseName}}".to_string())))?.0.clone(); +{{/required}}{{^required}} let param_{{paramName}} = req.headers.get::().map(|header| header.0.clone()); +{{/required}}{{/headerParams}} +{{#queryParams}}{{#-first}} + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) + let query_params = req.get::().unwrap_or_default(); +{{/-first}} let param_{{paramName}} = query_params.get("{{baseName}}") +{{#required}} .ok_or_else(|| Response::with((status::BadRequest, "Missing required query parameter {{baseName}}".to_string())))? +{{#isListContainer}} .iter().flat_map(|x| x.parse::<{{{baseType}}}>()).collect::>(); +{{/isListContainer}}{{^isListContainer}} .first().ok_or_else(|| Response::with((status::BadRequest, "Required query parameter {{baseName}} was empty".to_string())))? + .parse::<{{{dataType}}}>().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse query parameter {{baseName}} - doesn't match schema: {}", e))))?; +{{/isListContainer}}{{/required}}{{^required}}{{#isListContainer}} .map(|list| list.iter().flat_map(|x| x.parse::<{{{baseType}}}>()).collect::>()); +{{/isListContainer}}{{^isListContainer}} .and_then(|list| list.first()).and_then(|x| x.parse::<{{{dataType}}}>().ok()); +{{/isListContainer}}{{/required}}{{/queryParams}} +{{#bodyParams}}{{#-first}} // 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. +{{/-first}}{{#required}} + let param_{{paramName}}_raw = req.get::().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter {{baseName}} - not valid UTF-8: {}", e))))?; +{{/required}}{{^required}} + let param_{{paramName}}_raw = req.get::().unwrap_or(None); +{{/required}} + let mut unused_elements = Vec::new(); + + let param_{{paramName}} = if let Some(param_{{paramName}}_raw) = param_{{paramName}}_raw { {{#vendorExtensions}}{{#consumesXml}} + let deserializer = &mut serde_xml_rs::de::Deserializer::new_from_reader(param_{{paramName}}_raw.as_bytes());{{/consumesXml}}{{^consumesXml}} + let deserializer = &mut serde_json::Deserializer::from_str(¶m_{{paramName}}_raw);{{/consumesXml}}{{/vendorExtensions}} + + let param_{{paramName}}: Option<{{{dataType}}}> = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }){{#required}}.map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter {{baseName}} - doesn't match schema: {}", e))))?{{/required}}{{^required}}.unwrap_or(None){{/required}}; + + param_{{paramName}} + } else { + None + };{{#required}} + let param_{{paramName}} = param_{{paramName}}.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter {{baseName}}".to_string())))?{{/required}}; + +{{/bodyParams}} +{{#formParams}} + {{#-first}} + // Form parameters +{{/-first}}{{/formParams}}{{#vendorExtensions}}{{#hasFile}} + // Expecting a multipart form, extract and parse it now. + let mut entries = match Multipart::from_request(req) { + Ok(mut multipart) => { + + match multipart.save().temp() { + SaveResult::Full(entries) => { + Ok(entries) + }, + _ => { + Err(Response::with((status::InternalServerError, format!("Unable to process all message parts")))) + }, + } + }, + Err(e) => { + // Unable to parse as multipart + Err(Response::with((status::BadRequest, format!("Couldn't parse body as multipart")))) + } + }?; + +{{/hasFile}}{{/vendorExtensions}}{{#allParams}}{{#isFormParam}}{{#isFile}} + + let param_{{paramName}} = entries.fields.remove("{{paramName}}"); + + let param_{{paramName}} = match param_{{paramName}} { + Some(body) => { + Ok({let bytes = body.as_bytes(); + {{^required}}Some({{/required}} + Box::new(stream::once(Ok(bytes.to_vec()))) as Box, Error=Error> + Send> + {{^required}}){{/required}}} + ) + } + None => {Err(Response::with((status::BadRequest, format!("Body part not found!"))))} + }?; +{{/isFile}} + let param_{{paramName}} = {{#isFile}}{{^required}}Box::new(future::ok({{/required}}param_{{paramName}}{{^required}})){{/required}};{{/isFile}}{{^isFile}}{{^isContainer}}{{#vendorExtensions}}{{{example}}};{{/vendorExtensions}}{{/isContainer}}{{#isListContainer}}{{#required}}Vec::new();{{/required}}{{^required}}None;{{/required}}{{/isListContainer}}{{#isMapContainer}}None;{{/isMapContainer}}{{/isFile}} + {{/isFormParam}} +{{/allParams}} + + match api.{{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}({{#allParams}}param_{{paramName}}{{#isListContainer}}.as_ref(){{/isListContainer}}, {{/allParams}}context).wait() { + Ok(rsp) => match rsp { +{{#responses}} + {{operationId}}Response::{{message}}{{#dataType}}{{^headers}}(body){{/headers}}{{#headers}}{{#-first}}{ body{{/-first}}{{/headers}}{{/dataType}}{{#headers}}{{#-first}}{{^dataType}}{ {{/dataType}}{{#dataType}}, {{/dataType}}{{/-first}}{{^-first}}, {{/-first}}{{name}}{{#-last}} }{{/-last}}{{/headers}} => { +{{^isFile}} +{{#dataType}}{{#vendorExtensions}}{{#producesXml}} +{{^has_namespace}} let body_string = serde_xml_rs::to_string(&body).expect("impossible to fail to serialize");{{/has_namespace}}{{#has_namespace}} + let mut namespaces = BTreeMap::new(); + // An empty string is used to indicate a global namespace in xmltree. + namespaces.insert("".to_string(), models::namespaces::{{uppercase_data_type}}.clone()); + let body_string = serde_xml_rs::to_string_with_namespaces(&body, namespaces).expect("impossible to fail to serialize");{{/has_namespace}}{{/producesXml}}{{^producesXml}} + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize");{{/producesXml}}{{/vendorExtensions}}{{/dataType}} + + let mut response = Response::with((status::Status::from_u16({{code}}){{#dataType}}, body_string{{/dataType}}));{{/isFile}}{{#isFile}} body.fold(Vec::new(), |mut body, chunk| { + body.extend(chunk.iter()); + future::ok::, Error>(body) + }) + + // Block whilst waiting for the stream to complete + .wait() + + // It's possible that errors were received in the stream, if this is the case then we can't return a success response to the client and instead must return an internal error. + .map_err(|_| Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + + // Assuming no errors then create an Iron response. + .map(|rsp| { + let mut response = Response::new(); + response.status = Some(status::Status::from_u16({{code}})); + response.body = Some(Box::new(rsp)); +{{/isFile}} +{{#headers}}{{#isFile}} {{/isFile}} header! { (Response{{nameInCamelCase}}, "{{baseName}}") => [{{{datatype}}}] } +{{#isFile}} {{/isFile}} response.headers.set(Response{{nameInCamelCase}}({{name}})); +{{/headers}} + {{#produces}}{{#-first}} +{{#dataType}}{{#isFile}} {{/isFile}} response.headers.set(ContentType(mimetypes::responses::{{#vendorExtensions}}{{uppercase_operation_id}}_{{uppercase_message}}{{/vendorExtensions}}.clone()));{{/dataType}} +{{/-first}}{{/produces}} +{{#isFile}} {{/isFile}} context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); +{{#bodyParams}} if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + }{{/bodyParams}} + {{^isFile}}Ok(response){{/isFile}}{{#isFile}} response + }){{/isFile}} + }, +{{/responses}} + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "{{operationId}}"); +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} +} + +/// Middleware to extract authentication data from request +pub struct ExtractAuthData; + +impl BeforeMiddleware for ExtractAuthData { + fn before(&self, req: &mut Request) -> IronResult<()> { + {{#authMethods}} + {{#isBasic}} + { + use hyper::header::{Authorization, Basic, Bearer}; + use std::ops::Deref; + if let Some(basic) = req.headers.get::>() { + req.extensions.insert::(AuthData::Basic(basic.deref().clone())); + return Ok(()); + } + } + {{/isBasic}} + {{#isOAuth}} + { + use hyper::header::{Authorization, Basic, Bearer}; + use std::ops::Deref; + if let Some(bearer) = req.headers.get::>() { + req.extensions.insert::(AuthData::Bearer(bearer.deref().clone())); + return Ok(()); + } + } + {{/isOAuth}} + {{#isApiKey}} + {{#isKeyInHeader}} + { + header! { (ApiKey{{-index}}, "{{keyParamName}}") => [String] } + if let Some(header) = req.headers.get::() { + req.extensions.insert::(AuthData::ApiKey(header.0.clone())); + return Ok(()); + } + } + {{/isKeyInHeader}} + {{#isKeyInQuery}} + { + let header = match req.get_ref::() { + Ok(query) => query.get("{{keyParamName}}").map(|v| v[0].clone()), + _ => None + }; + if let Some(key) = header { + req.extensions.insert::(AuthData::ApiKey(key)); + return Ok(()); + } + } + {{/isKeyInQuery}} + {{/isApiKey}} + {{/authMethods}} + + Ok(()) + } +} diff --git a/modules/swagger-codegen/src/main/resources/rust2/swagger.mustache b/modules/swagger-codegen/src/main/resources/rust2/swagger.mustache new file mode 100644 index 000000000000..51560926bba1 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/rust2/swagger.mustache @@ -0,0 +1 @@ +{{{swagger-yaml}}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/Rust2OptionsProvider.java b/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/Rust2OptionsProvider.java new file mode 100644 index 000000000000..68c0d94088d6 --- /dev/null +++ b/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/Rust2OptionsProvider.java @@ -0,0 +1,22 @@ +package io.swagger.codegen.options; + +import com.google.common.collect.ImmutableMap; + +import java.util.Map; + +public class Rust2OptionsProvider implements OptionsProvider { + @Override + public String getLanguage() { + return "rust2"; + } + + @Override + public Map createOptions() { + return ImmutableMap.of(); + } + + @Override + public boolean isServer() { + return true; + } +} diff --git a/modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml b/modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml index c947e95d926a..d7ba1c465892 100644 --- a/modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml +++ b/modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml @@ -898,6 +898,35 @@ paths: responses: '200': description: successful operation + /fake/xmlFeatures: + get: + summary: Get some XML + operationId: getXmlFeatures + produces: + - application/xml + consumes: + - application/xml + responses: + 200: + description: Success + schema: + $ref: '#/definitions/xmlObject' + post: + parameters: + - name: xmlObject + in: body + required: true + schema: + $ref: '#/definitions/xmlObject' + summary: Post some xml + operationId: postXmlFeatures + produces: + - application/xml + consumes: + - application/xml + responses: + 200: + description: Success /fake/inline-additionalProperties: post: tags: @@ -942,6 +971,7 @@ paths: description: successful operation schema: $ref: '#/definitions/Client' + securityDefinitions: petstore_auth: type: oauth2 @@ -957,7 +987,7 @@ securityDefinitions: api_key_query: type: apiKey name: api_key_query - in: query + in: query http_basic_test: type: basic definitions: @@ -980,7 +1010,7 @@ definitions: type: string description: Order Status enum: - - placed + - placedtest - approved - delivered complete: diff --git a/samples/client/petstore/rust2/.cargo/config b/samples/client/petstore/rust2/.cargo/config new file mode 100644 index 000000000000..b8acc9c00c8c --- /dev/null +++ b/samples/client/petstore/rust2/.cargo/config @@ -0,0 +1,18 @@ +[build] +rustflags = [ + "-W", "missing_docs", # detects missing documentation for public members + + "-W", "trivial_casts", # detects trivial casts which could be removed + + "-W", "trivial_numeric_casts", # detects trivial casts of numeric types which could be removed + + "-W", "unsafe_code", # usage of `unsafe` code + + "-W", "unused_qualifications", # detects unnecessarily qualified names + + "-W", "unused_extern_crates", # extern crates that are never used + + "-W", "unused_import_braces", # unnecessary braces around an imported item + + "-D", "warnings", # all warnings should be denied +] diff --git a/samples/client/petstore/rust2/.gitignore b/samples/client/petstore/rust2/.gitignore new file mode 100644 index 000000000000..a9d37c560c6a --- /dev/null +++ b/samples/client/petstore/rust2/.gitignore @@ -0,0 +1,2 @@ +target +Cargo.lock diff --git a/samples/client/petstore/rust2/.swagger-codegen-ignore b/samples/client/petstore/rust2/.swagger-codegen-ignore new file mode 100644 index 000000000000..c5fa491b4c55 --- /dev/null +++ b/samples/client/petstore/rust2/.swagger-codegen-ignore @@ -0,0 +1,23 @@ +# Swagger Codegen Ignore +# Generated by swagger-codegen https://github.com/swagger-api/swagger-codegen + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell Swagger Codgen to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/samples/client/petstore/rust2/.swagger-codegen/VERSION b/samples/client/petstore/rust2/.swagger-codegen/VERSION new file mode 100644 index 000000000000..f9f7450d1359 --- /dev/null +++ b/samples/client/petstore/rust2/.swagger-codegen/VERSION @@ -0,0 +1 @@ +2.3.0-SNAPSHOT \ No newline at end of file diff --git a/samples/client/petstore/rust2/Cargo.toml b/samples/client/petstore/rust2/Cargo.toml new file mode 100644 index 000000000000..da42d20714b5 --- /dev/null +++ b/samples/client/petstore/rust2/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "petstore_api" +version = "1.0.0" +authors = ["apiteam@swagger.io"] + +[features] +default = ["client", "server"] +client = ["serde_json", "serde-xml-rs", "serde_ignored", "hyper", "hyper-openssl", "uuid", "multipart"] +server = ["serde_json", "serde-xml-rs", "serde_ignored", "hyper", "iron", "router", "bodyparser", "urlencoded", "uuid", "multipart"] + +[dependencies] +bodyparser = {version = "0.7", optional = true} +chrono = { version = "0.4", features = ["serde"] } +futures = "0.1" +hyper = {version = "0.10", optional = true} +hyper-openssl = {version = "0.2", optional = true } +iron = {version = "0.5", optional = true} +lazy_static = "0.2" +log = "0.3.0" +multipart = {version = "0.13", optional = true} +router = {version = "0.5", optional = true} +serde = "1.0" +serde_derive = "1.0" +serde_ignored = {version = "0.0.4", optional = true} +serde_json = {version = "1.0", optional = true} +swagger = "0.7" +urlencoded = {version = "0.5", optional = true} +uuid = {version = "0.5", optional = true, features = ["serde", "v4"]} +# 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", optional = true} + +[dev-dependencies] +clap = "2.25" diff --git a/samples/client/petstore/rust2/README.md b/samples/client/petstore/rust2/README.md new file mode 100644 index 000000000000..1e98c25281c6 --- /dev/null +++ b/samples/client/petstore/rust2/README.md @@ -0,0 +1,85 @@ +# Rust API for petstore_api + +This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ + +## Overview +This client/server was generated by the [swagger-codegen] +(https://github.com/swagger-api/swagger-codegen) project. +By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub. +- + +To see how to make this your own, look here: + +[README](https://github.com/swagger-api/swagger-codegen/blob/master/README.md) + +- API version: 1.0.0 +- Build date: 2017-09-26T16:36:55.563+01:00 + +## Examples + +Run examples with: + +``` +cargo run --example +``` + +To pass in arguments to the examples, put them after `--`, for example: + +``` +cargo run --example client -- --help +``` + +### Running the server +To run the server, follow these simple steps: + +``` +cargo run --example server +``` + +### Running a client +To run a client, follow one of the following simple steps: + +``` +cargo run --example client TestSpecialTags +cargo run --example client GetXmlFeatures +cargo run --example client PostXmlFeatures +cargo run --example client FakeOuterBooleanSerialize +cargo run --example client FakeOuterCompositeSerialize +cargo run --example client FakeOuterNumberSerialize +cargo run --example client FakeOuterStringSerialize +cargo run --example client TestClientModel +cargo run --example client TestEndpointParameters +cargo run --example client TestEnumParameters +cargo run --example client TestJsonFormData +cargo run --example client TestClassname +cargo run --example client AddPet +cargo run --example client DeletePet +cargo run --example client FindPetsByStatus +cargo run --example client FindPetsByTags +cargo run --example client GetPetById +cargo run --example client UpdatePet +cargo run --example client UpdatePetWithForm +cargo run --example client UploadFile +cargo run --example client DeleteOrder +cargo run --example client GetInventory +cargo run --example client GetOrderById +cargo run --example client PlaceOrder +cargo run --example client CreateUser +cargo run --example client CreateUsersWithArrayInput +cargo run --example client CreateUsersWithListInput +cargo run --example client DeleteUser +cargo run --example client GetUserByName +cargo run --example client LoginUser +cargo run --example client LogoutUser +cargo run --example client UpdateUser +``` + +### HTTPS +The examples can be run in HTTPS mode by passing in the flag `--https`, for example: + +``` +cargo run --example server -- --https +``` + +This will use the keys/certificates from the examples directory. Note that the server chain is signed with +`CN=localhost`. diff --git a/samples/client/petstore/rust2/api/swagger.yaml b/samples/client/petstore/rust2/api/swagger.yaml new file mode 100644 index 000000000000..1dc845be640e --- /dev/null +++ b/samples/client/petstore/rust2/api/swagger.yaml @@ -0,0 +1,2020 @@ +--- +swagger: "2.0" +info: + description: "This spec is mainly for testing Petstore server and contains fake\ + \ endpoints, models. Please do not use this for any other purpose. Special characters:\ + \ \" \\" + version: "1.0.0" + title: "Swagger Petstore" + termsOfService: "http://swagger.io/terms/" + contact: + email: "apiteam@swagger.io" + license: + name: "Apache 2.0" + url: "http://www.apache.org/licenses/LICENSE-2.0.html" +host: "petstore.swagger.io:80" +basePath: "/v2" +tags: +- name: "pet" + description: "Everything about your Pets" + externalDocs: + description: "Find out more" + url: "http://swagger.io" +- name: "store" + description: "Access to Petstore orders" +- name: "user" + description: "Operations about user" + externalDocs: + description: "Find out more about our store" + url: "http://swagger.io" +schemes: +- "http" +paths: + /pet: + post: + tags: + - "pet" + summary: "Add a new pet to the store" + description: "" + operationId: "addPet" + consumes: + - "application/json" + - "application/xml" + produces: + - "application/xml" + - "application/json" + parameters: + - in: "body" + name: "body" + description: "Pet object that needs to be added to the store" + required: true + schema: + $ref: "#/definitions/Pet" + uppercase_data_type: "PET" + refName: "Pet" + formatString: "{:?}" + example: "???" + model_key: "itemList" + uppercase_operation_id: "ADD_PET" + consumesXml: true + responses: + 405: + description: "Invalid input" + uppercase_operation_id: "ADD_PET" + uppercase_message: "INVALID_INPUT" + security: + - petstore_auth: + - "write:pets" + - "read:pets" + operation_id: "add_pet" + uppercase_operation_id: "ADD_PET" + path: "/pet" + HttpMethod: "Post" + httpmethod: "post" + noClientExample: true + put: + tags: + - "pet" + summary: "Update an existing pet" + description: "" + operationId: "updatePet" + consumes: + - "application/json" + - "application/xml" + produces: + - "application/xml" + - "application/json" + parameters: + - in: "body" + name: "body" + description: "Pet object that needs to be added to the store" + required: true + schema: + $ref: "#/definitions/Pet" + uppercase_data_type: "PET" + refName: "Pet" + formatString: "{:?}" + example: "???" + model_key: "itemList" + uppercase_operation_id: "UPDATE_PET" + consumesXml: true + responses: + 400: + description: "Invalid ID supplied" + uppercase_operation_id: "UPDATE_PET" + uppercase_message: "INVALID_ID_SUPPLIED" + 404: + description: "Pet not found" + uppercase_operation_id: "UPDATE_PET" + uppercase_message: "PET_NOT_FOUND" + 405: + description: "Validation exception" + uppercase_operation_id: "UPDATE_PET" + uppercase_message: "VALIDATION_EXCEPTION" + security: + - petstore_auth: + - "write:pets" + - "read:pets" + operation_id: "update_pet" + uppercase_operation_id: "UPDATE_PET" + path: "/pet" + HttpMethod: "Put" + httpmethod: "put" + noClientExample: true + /pet/findByStatus: + get: + tags: + - "pet" + summary: "Finds Pets by status" + description: "Multiple status values can be provided with comma separated strings" + operationId: "findPetsByStatus" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "status" + in: "query" + description: "Status values that need to be considered for filter" + required: true + type: "array" + items: + type: "string" + default: "available" + enum: + - "available" + - "pending" + - "sold" + collectionFormat: "csv" + formatString: "{:?}" + example: "&Vec::new()" + responses: + 200: + description: "successful operation" + schema: + type: "array" + items: + $ref: "#/definitions/Pet" + uppercase_operation_id: "FIND_PETS_BY_STATUS" + uppercase_message: "SUCCESSFUL_OPERATION" + uppercase_data_type: "VEC" + producesXml: true + 400: + description: "Invalid status value" + uppercase_operation_id: "FIND_PETS_BY_STATUS" + uppercase_message: "INVALID_STATUS_VALUE" + security: + - petstore_auth: + - "write:pets" + - "read:pets" + operation_id: "find_pets_by_status" + uppercase_operation_id: "FIND_PETS_BY_STATUS" + path: "/pet/findByStatus" + HttpMethod: "Get" + httpmethod: "get" + /pet/findByTags: + get: + tags: + - "pet" + summary: "Finds Pets by tags" + description: "Multiple tags can be provided with comma separated strings. Use\ + \ tag1, tag2, tag3 for testing." + operationId: "findPetsByTags" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "tags" + in: "query" + description: "Tags to filter by" + required: true + type: "array" + items: + type: "string" + collectionFormat: "csv" + formatString: "{:?}" + example: "&Vec::new()" + responses: + 200: + description: "successful operation" + schema: + type: "array" + items: + $ref: "#/definitions/Pet" + uppercase_operation_id: "FIND_PETS_BY_TAGS" + uppercase_message: "SUCCESSFUL_OPERATION" + uppercase_data_type: "VEC" + producesXml: true + 400: + description: "Invalid tag value" + uppercase_operation_id: "FIND_PETS_BY_TAGS" + uppercase_message: "INVALID_TAG_VALUE" + security: + - petstore_auth: + - "write:pets" + - "read:pets" + deprecated: true + operation_id: "find_pets_by_tags" + uppercase_operation_id: "FIND_PETS_BY_TAGS" + path: "/pet/findByTags" + HttpMethod: "Get" + httpmethod: "get" + /pet/{petId}: + get: + tags: + - "pet" + summary: "Find pet by ID" + description: "Returns a single pet" + operationId: "getPetById" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "petId" + in: "path" + description: "ID of pet to return" + required: true + type: "integer" + format: "int64" + formatString: "{}" + example: "789" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/Pet" + uppercase_operation_id: "GET_PET_BY_ID" + uppercase_message: "SUCCESSFUL_OPERATION" + uppercase_data_type: "PET" + producesXml: true + 400: + description: "Invalid ID supplied" + uppercase_operation_id: "GET_PET_BY_ID" + uppercase_message: "INVALID_ID_SUPPLIED" + 404: + description: "Pet not found" + uppercase_operation_id: "GET_PET_BY_ID" + uppercase_message: "PET_NOT_FOUND" + security: + - api_key: [] + operation_id: "get_pet_by_id" + uppercase_operation_id: "GET_PET_BY_ID" + path: "/pet/:petId" + HttpMethod: "Get" + httpmethod: "get" + post: + tags: + - "pet" + summary: "Updates a pet in the store with form data" + description: "" + operationId: "updatePetWithForm" + consumes: + - "application/x-www-form-urlencoded" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "petId" + in: "path" + description: "ID of pet that needs to be updated" + required: true + type: "integer" + format: "int64" + formatString: "{}" + example: "789" + - name: "name" + in: "formData" + description: "Updated name of the pet" + required: false + type: "string" + formatString: "{:?}" + example: "Some(\"name_example\".to_string())" + - name: "status" + in: "formData" + description: "Updated status of the pet" + required: false + type: "string" + formatString: "{:?}" + example: "Some(\"status_example\".to_string())" + responses: + 405: + description: "Invalid input" + uppercase_operation_id: "UPDATE_PET_WITH_FORM" + uppercase_message: "INVALID_INPUT" + security: + - petstore_auth: + - "write:pets" + - "read:pets" + operation_id: "update_pet_with_form" + uppercase_operation_id: "UPDATE_PET_WITH_FORM" + path: "/pet/:petId" + HttpMethod: "Post" + httpmethod: "post" + delete: + tags: + - "pet" + summary: "Deletes a pet" + description: "" + operationId: "deletePet" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "api_key" + in: "header" + required: false + type: "string" + formatString: "{:?}" + example: "Some(\"api_key_example\".to_string())" + - name: "petId" + in: "path" + description: "Pet id to delete" + required: true + type: "integer" + format: "int64" + formatString: "{}" + example: "789" + responses: + 400: + description: "Invalid pet value" + uppercase_operation_id: "DELETE_PET" + uppercase_message: "INVALID_PET_VALUE" + security: + - petstore_auth: + - "write:pets" + - "read:pets" + operation_id: "delete_pet" + uppercase_operation_id: "DELETE_PET" + path: "/pet/:petId" + HttpMethod: "Delete" + httpmethod: "delete" + /pet/{petId}/uploadImage: + post: + tags: + - "pet" + summary: "uploads an image" + description: "" + operationId: "uploadFile" + consumes: + - "multipart/form-data" + produces: + - "application/json" + parameters: + - name: "petId" + in: "path" + description: "ID of pet to update" + required: true + type: "integer" + format: "int64" + formatString: "{}" + example: "789" + - name: "additionalMetadata" + in: "formData" + description: "Additional data to pass to server" + required: false + type: "string" + formatString: "{:?}" + example: "Some(\"additional_metadata_example\".to_string())" + - name: "file" + in: "formData" + description: "file to upload" + required: false + type: "file" + formatString: "{:?}" + example: "Box::new(future::ok(Some(Box::new(stream::once(Ok(b\"hello\".to_vec())))\ + \ as Box + Send>))) as Box\ + \ + Send>" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/ApiResponse" + uppercase_operation_id: "UPLOAD_FILE" + uppercase_message: "SUCCESSFUL_OPERATION" + uppercase_data_type: "APIRESPONSE" + security: + - petstore_auth: + - "write:pets" + - "read:pets" + operation_id: "upload_file" + uppercase_operation_id: "UPLOAD_FILE" + path: "/pet/:petId/uploadImage" + HttpMethod: "Post" + httpmethod: "post" + hasFile: true + /store/inventory: + get: + tags: + - "store" + summary: "Returns pet inventories by status" + description: "Returns a map of status codes to quantities" + operationId: "getInventory" + produces: + - "application/json" + parameters: [] + responses: + 200: + description: "successful operation" + schema: + type: "object" + additionalProperties: + type: "integer" + format: "int32" + uppercase_operation_id: "GET_INVENTORY" + uppercase_message: "SUCCESSFUL_OPERATION" + uppercase_data_type: "HASHMAP" + security: + - api_key: [] + operation_id: "get_inventory" + uppercase_operation_id: "GET_INVENTORY" + path: "/store/inventory" + HttpMethod: "Get" + httpmethod: "get" + /store/order: + post: + tags: + - "store" + summary: "Place an order for a pet" + description: "" + operationId: "placeOrder" + produces: + - "application/xml" + - "application/json" + parameters: + - in: "body" + name: "body" + description: "order placed for purchasing the pet" + required: true + schema: + $ref: "#/definitions/Order" + uppercase_data_type: "ORDER" + refName: "Order" + formatString: "{:?}" + example: "???" + model_key: "itemList" + uppercase_operation_id: "PLACE_ORDER" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/Order" + uppercase_operation_id: "PLACE_ORDER" + uppercase_message: "SUCCESSFUL_OPERATION" + uppercase_data_type: "ORDER" + producesXml: true + 400: + description: "Invalid Order" + uppercase_operation_id: "PLACE_ORDER" + uppercase_message: "INVALID_ORDER" + operation_id: "place_order" + uppercase_operation_id: "PLACE_ORDER" + path: "/store/order" + HttpMethod: "Post" + httpmethod: "post" + noClientExample: true + /store/order/{order_id}: + get: + tags: + - "store" + summary: "Find purchase order by ID" + description: "For valid response try integer IDs with value <= 5 or > 10. Other\ + \ values will generated exceptions" + operationId: "getOrderById" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "order_id" + in: "path" + description: "ID of pet that needs to be fetched" + required: true + type: "integer" + maximum: 5 + minimum: 1 + format: "int64" + formatString: "{}" + example: "789" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/Order" + uppercase_operation_id: "GET_ORDER_BY_ID" + uppercase_message: "SUCCESSFUL_OPERATION" + uppercase_data_type: "ORDER" + producesXml: true + 400: + description: "Invalid ID supplied" + uppercase_operation_id: "GET_ORDER_BY_ID" + uppercase_message: "INVALID_ID_SUPPLIED" + 404: + description: "Order not found" + uppercase_operation_id: "GET_ORDER_BY_ID" + uppercase_message: "ORDER_NOT_FOUND" + operation_id: "get_order_by_id" + uppercase_operation_id: "GET_ORDER_BY_ID" + path: "/store/order/:order_id" + HttpMethod: "Get" + httpmethod: "get" + delete: + tags: + - "store" + summary: "Delete purchase order by ID" + description: "For valid response try integer IDs with value < 1000. Anything\ + \ above 1000 or nonintegers will generate API errors" + operationId: "deleteOrder" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "order_id" + in: "path" + description: "ID of the order that needs to be deleted" + required: true + type: "string" + formatString: "\\\"{}\\\"" + example: "\"order_id_example\".to_string()" + responses: + 400: + description: "Invalid ID supplied" + uppercase_operation_id: "DELETE_ORDER" + uppercase_message: "INVALID_ID_SUPPLIED" + 404: + description: "Order not found" + uppercase_operation_id: "DELETE_ORDER" + uppercase_message: "ORDER_NOT_FOUND" + operation_id: "delete_order" + uppercase_operation_id: "DELETE_ORDER" + path: "/store/order/:order_id" + HttpMethod: "Delete" + httpmethod: "delete" + /user: + post: + tags: + - "user" + summary: "Create user" + description: "This can only be done by the logged in user." + operationId: "createUser" + produces: + - "application/xml" + - "application/json" + parameters: + - in: "body" + name: "body" + description: "Created user object" + required: true + schema: + $ref: "#/definitions/User" + uppercase_data_type: "USER" + refName: "User" + formatString: "{:?}" + example: "???" + model_key: "itemList" + uppercase_operation_id: "CREATE_USER" + responses: + default: + description: "successful operation" + uppercase_operation_id: "CREATE_USER" + uppercase_message: "SUCCESSFUL_OPERATION" + operation_id: "create_user" + uppercase_operation_id: "CREATE_USER" + path: "/user" + HttpMethod: "Post" + httpmethod: "post" + noClientExample: true + /user/createWithArray: + post: + tags: + - "user" + summary: "Creates list of users with given input array" + description: "" + operationId: "createUsersWithArrayInput" + produces: + - "application/xml" + - "application/json" + parameters: + - in: "body" + name: "body" + description: "List of user object" + required: true + schema: + type: "array" + items: + $ref: "#/definitions/User" + formatString: "{:?}" + example: "&Vec::new()" + model_key: "itemList" + uppercase_operation_id: "CREATE_USERS_WITH_ARRAY_INPUT" + responses: + default: + description: "successful operation" + uppercase_operation_id: "CREATE_USERS_WITH_ARRAY_INPUT" + uppercase_message: "SUCCESSFUL_OPERATION" + operation_id: "create_users_with_array_input" + uppercase_operation_id: "CREATE_USERS_WITH_ARRAY_INPUT" + path: "/user/createWithArray" + HttpMethod: "Post" + httpmethod: "post" + /user/createWithList: + post: + tags: + - "user" + summary: "Creates list of users with given input array" + description: "" + operationId: "createUsersWithListInput" + produces: + - "application/xml" + - "application/json" + parameters: + - in: "body" + name: "body" + description: "List of user object" + required: true + schema: + type: "array" + items: + $ref: "#/definitions/User" + formatString: "{:?}" + example: "&Vec::new()" + model_key: "itemList" + uppercase_operation_id: "CREATE_USERS_WITH_LIST_INPUT" + responses: + default: + description: "successful operation" + uppercase_operation_id: "CREATE_USERS_WITH_LIST_INPUT" + uppercase_message: "SUCCESSFUL_OPERATION" + operation_id: "create_users_with_list_input" + uppercase_operation_id: "CREATE_USERS_WITH_LIST_INPUT" + path: "/user/createWithList" + HttpMethod: "Post" + httpmethod: "post" + /user/login: + get: + tags: + - "user" + summary: "Logs user into the system" + description: "" + operationId: "loginUser" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "username" + in: "query" + description: "The user name for login" + required: true + type: "string" + formatString: "\\\"{}\\\"" + example: "\"username_example\".to_string()" + - name: "password" + in: "query" + description: "The password for login in clear text" + required: true + type: "string" + formatString: "\\\"{}\\\"" + example: "\"password_example\".to_string()" + responses: + 200: + description: "successful operation" + schema: + type: "string" + headers: + X-Rate-Limit: + type: "integer" + format: "int32" + description: "calls per hour allowed by the user" + X-Expires-After: + type: "string" + format: "date-time" + description: "date in UTC when toekn expires" + uppercase_operation_id: "LOGIN_USER" + uppercase_message: "SUCCESSFUL_OPERATION" + uppercase_data_type: "STRING" + producesXml: true + 400: + description: "Invalid username/password supplied" + uppercase_operation_id: "LOGIN_USER" + uppercase_message: "INVALID_USERNAME" + operation_id: "login_user" + uppercase_operation_id: "LOGIN_USER" + path: "/user/login" + HttpMethod: "Get" + httpmethod: "get" + /user/logout: + get: + tags: + - "user" + summary: "Logs out current logged in user session" + description: "" + operationId: "logoutUser" + produces: + - "application/xml" + - "application/json" + parameters: [] + responses: + default: + description: "successful operation" + uppercase_operation_id: "LOGOUT_USER" + uppercase_message: "SUCCESSFUL_OPERATION" + operation_id: "logout_user" + uppercase_operation_id: "LOGOUT_USER" + path: "/user/logout" + HttpMethod: "Get" + httpmethod: "get" + /user/{username}: + get: + tags: + - "user" + summary: "Get user by user name" + description: "" + operationId: "getUserByName" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "username" + in: "path" + description: "The name that needs to be fetched. Use user1 for testing. " + required: true + type: "string" + formatString: "\\\"{}\\\"" + example: "\"username_example\".to_string()" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/User" + uppercase_operation_id: "GET_USER_BY_NAME" + uppercase_message: "SUCCESSFUL_OPERATION" + uppercase_data_type: "USER" + producesXml: true + 400: + description: "Invalid username supplied" + uppercase_operation_id: "GET_USER_BY_NAME" + uppercase_message: "INVALID_USERNAME_SUPPLIED" + 404: + description: "User not found" + uppercase_operation_id: "GET_USER_BY_NAME" + uppercase_message: "USER_NOT_FOUND" + operation_id: "get_user_by_name" + uppercase_operation_id: "GET_USER_BY_NAME" + path: "/user/:username" + HttpMethod: "Get" + httpmethod: "get" + put: + tags: + - "user" + summary: "Updated user" + description: "This can only be done by the logged in user." + operationId: "updateUser" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "username" + in: "path" + description: "name that need to be deleted" + required: true + type: "string" + formatString: "\\\"{}\\\"" + example: "\"username_example\".to_string()" + - in: "body" + name: "body" + description: "Updated user object" + required: true + schema: + $ref: "#/definitions/User" + uppercase_data_type: "USER" + refName: "User" + formatString: "{:?}" + example: "???" + model_key: "itemList" + uppercase_operation_id: "UPDATE_USER" + responses: + 400: + description: "Invalid user supplied" + uppercase_operation_id: "UPDATE_USER" + uppercase_message: "INVALID_USER_SUPPLIED" + 404: + description: "User not found" + uppercase_operation_id: "UPDATE_USER" + uppercase_message: "USER_NOT_FOUND" + operation_id: "update_user" + uppercase_operation_id: "UPDATE_USER" + path: "/user/:username" + HttpMethod: "Put" + httpmethod: "put" + noClientExample: true + delete: + tags: + - "user" + summary: "Delete user" + description: "This can only be done by the logged in user." + operationId: "deleteUser" + produces: + - "application/xml" + - "application/json" + parameters: + - name: "username" + in: "path" + description: "The name that needs to be deleted" + required: true + type: "string" + formatString: "\\\"{}\\\"" + example: "\"username_example\".to_string()" + responses: + 400: + description: "Invalid username supplied" + uppercase_operation_id: "DELETE_USER" + uppercase_message: "INVALID_USERNAME_SUPPLIED" + 404: + description: "User not found" + uppercase_operation_id: "DELETE_USER" + uppercase_message: "USER_NOT_FOUND" + operation_id: "delete_user" + uppercase_operation_id: "DELETE_USER" + path: "/user/:username" + HttpMethod: "Delete" + httpmethod: "delete" + /fake_classname_test: + patch: + tags: + - "fake_classname_tags 123#$%^" + summary: "To test class name in snake case" + operationId: "testClassname" + consumes: + - "application/json" + produces: + - "application/json" + parameters: + - in: "body" + name: "body" + description: "client model" + required: true + schema: + $ref: "#/definitions/Client" + uppercase_data_type: "CLIENT" + refName: "Client" + formatString: "{:?}" + example: "???" + model_key: "itemList" + uppercase_operation_id: "TEST_CLASSNAME" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/Client" + uppercase_operation_id: "TEST_CLASSNAME" + uppercase_message: "SUCCESSFUL_OPERATION" + uppercase_data_type: "CLIENT" + security: + - api_key_query: [] + operation_id: "test_classname" + uppercase_operation_id: "TEST_CLASSNAME" + path: "/fake_classname_test" + HttpMethod: "Patch" + httpmethod: "patch" + noClientExample: true + /fake: + get: + tags: + - "fake" + summary: "To test enum parameters" + description: "To test enum parameters" + operationId: "testEnumParameters" + consumes: + - "*/*" + produces: + - "*/*" + parameters: + - name: "enum_form_string_array" + in: "formData" + description: "Form parameter enum test (string array)" + required: false + type: "array" + items: + type: "string" + default: "$" + enum: + - ">" + - "$" + formatString: "{:?}" + example: "Some(&Vec::new())" + - name: "enum_form_string" + in: "formData" + description: "Form parameter enum test (string)" + required: false + type: "string" + default: "-efg" + enum: + - "_abc" + - "-efg" + - "(xyz)" + formatString: "{:?}" + example: "Some(\"enum_form_string_example\".to_string())" + - name: "enum_header_string_array" + in: "header" + description: "Header parameter enum test (string array)" + required: false + type: "array" + items: + type: "string" + default: "$" + enum: + - ">" + - "$" + formatString: "{:?}" + example: "Some(&Vec::new())" + - name: "enum_header_string" + in: "header" + description: "Header parameter enum test (string)" + required: false + type: "string" + default: "-efg" + enum: + - "_abc" + - "-efg" + - "(xyz)" + formatString: "{:?}" + example: "Some(\"enum_header_string_example\".to_string())" + - name: "enum_query_string_array" + in: "query" + description: "Query parameter enum test (string array)" + required: false + type: "array" + items: + type: "string" + default: "$" + enum: + - ">" + - "$" + formatString: "{:?}" + example: "Some(&Vec::new())" + - name: "enum_query_string" + in: "query" + description: "Query parameter enum test (string)" + required: false + type: "string" + default: "-efg" + enum: + - "_abc" + - "-efg" + - "(xyz)" + formatString: "{:?}" + example: "Some(\"enum_query_string_example\".to_string())" + - name: "enum_query_integer" + in: "query" + description: "Query parameter enum test (double)" + required: false + type: "integer" + format: "int32" + enum: + - 1 + - -2 + formatString: "{:?}" + example: "Some(56)" + - name: "enum_query_double" + in: "formData" + description: "Query parameter enum test (double)" + required: false + type: "number" + format: "double" + enum: + - 1.1 + - -1.2 + formatString: "{:?}" + example: "Some(1.2)" + responses: + 400: + description: "Invalid request" + uppercase_operation_id: "TEST_ENUM_PARAMETERS" + uppercase_message: "INVALID_REQUEST" + 404: + description: "Not found" + uppercase_operation_id: "TEST_ENUM_PARAMETERS" + uppercase_message: "NOT_FOUND" + operation_id: "test_enum_parameters" + uppercase_operation_id: "TEST_ENUM_PARAMETERS" + path: "/fake" + HttpMethod: "Get" + httpmethod: "get" + post: + tags: + - "fake" + summary: "Fake endpoint for testing various parameters\n假端點\n偽のエンドポイント\n가짜 엔\ + 드 포인트\n" + description: "Fake endpoint for testing various parameters\n假端點\n偽のエンドポイント\n\ + 가짜 엔드 포인트\n" + operationId: "testEndpointParameters" + consumes: + - "application/xml; charset=utf-8" + - "application/json; charset=utf-8" + produces: + - "application/xml; charset=utf-8" + - "application/json; charset=utf-8" + parameters: + - name: "integer" + in: "formData" + description: "None" + required: false + type: "integer" + maximum: 100 + minimum: 10 + formatString: "{:?}" + example: "Some(56)" + - name: "int32" + in: "formData" + description: "None" + required: false + type: "integer" + maximum: 200 + minimum: 20 + format: "int32" + formatString: "{:?}" + example: "Some(56)" + - name: "int64" + in: "formData" + description: "None" + required: false + type: "integer" + format: "int64" + formatString: "{:?}" + example: "Some(789)" + - name: "number" + in: "formData" + description: "None" + required: true + type: "number" + maximum: 543.2 + minimum: 32.1 + formatString: "{}" + example: "3.4" + - name: "float" + in: "formData" + description: "None" + required: false + type: "number" + maximum: 987.6 + format: "float" + formatString: "{:?}" + example: "Some(3.4)" + - name: "double" + in: "formData" + description: "None" + required: true + type: "number" + maximum: 123.4 + minimum: 67.8 + format: "double" + formatString: "{}" + example: "1.2" + - name: "string" + in: "formData" + description: "None" + required: false + type: "string" + pattern: "/[a-z]/i" + formatString: "{:?}" + example: "Some(\"string_example\".to_string())" + - name: "pattern_without_delimiter" + in: "formData" + description: "None" + required: true + type: "string" + pattern: "^[A-Z].*" + formatString: "\\\"{}\\\"" + example: "\"pattern_without_delimiter_example\".to_string()" + - name: "byte" + in: "formData" + description: "None" + required: true + type: "string" + format: "byte" + formatString: "\\\"{:?}\\\"" + example: "swagger::ByteArray(\"byte_example\".to_string().into_bytes())" + - name: "binary" + in: "formData" + description: "None" + required: false + type: "string" + format: "binary" + formatString: "{:?}" + example: "Some(swagger::ByteArray(Vec::from(\"B\")))" + - name: "date" + in: "formData" + description: "None" + required: false + type: "string" + format: "date" + formatString: "{:?}" + example: "None" + - name: "dateTime" + in: "formData" + description: "None" + required: false + type: "string" + format: "date-time" + formatString: "{:?}" + example: "None" + - name: "password" + in: "formData" + description: "None" + required: false + type: "string" + maxLength: 64 + minLength: 10 + format: "password" + formatString: "{:?}" + example: "Some(\"password_example\".to_string())" + - name: "callback" + in: "formData" + description: "None" + required: false + type: "string" + formatString: "{:?}" + example: "Some(\"callback_example\".to_string())" + responses: + 400: + description: "Invalid username supplied" + uppercase_operation_id: "TEST_ENDPOINT_PARAMETERS" + uppercase_message: "INVALID_USERNAME_SUPPLIED" + 404: + description: "User not found" + uppercase_operation_id: "TEST_ENDPOINT_PARAMETERS" + uppercase_message: "USER_NOT_FOUND" + security: + - http_basic_test: [] + operation_id: "test_endpoint_parameters" + uppercase_operation_id: "TEST_ENDPOINT_PARAMETERS" + path: "/fake" + HttpMethod: "Post" + httpmethod: "post" + patch: + tags: + - "fake" + summary: "To test \"client\" model" + description: "To test \"client\" model" + operationId: "testClientModel" + consumes: + - "application/json" + produces: + - "application/json" + parameters: + - in: "body" + name: "body" + description: "client model" + required: true + schema: + $ref: "#/definitions/Client" + uppercase_data_type: "CLIENT" + refName: "Client" + formatString: "{:?}" + example: "???" + model_key: "itemList" + uppercase_operation_id: "TEST_CLIENT_MODEL" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/Client" + uppercase_operation_id: "TEST_CLIENT_MODEL" + uppercase_message: "SUCCESSFUL_OPERATION" + uppercase_data_type: "CLIENT" + operation_id: "test_client_model" + uppercase_operation_id: "TEST_CLIENT_MODEL" + path: "/fake" + HttpMethod: "Patch" + httpmethod: "patch" + noClientExample: true + /fake/outer/number: + post: + tags: + - "fake" + description: "Test serialization of outer number types" + operationId: "fakeOuterNumberSerialize" + parameters: + - in: "body" + name: "body" + description: "Input number as post body" + required: false + schema: + $ref: "#/definitions/OuterNumber" + uppercase_data_type: "OUTERNUMBER" + refName: "OuterNumber" + formatString: "{:?}" + example: "None" + model_key: "itemList" + uppercase_operation_id: "FAKE_OUTER_NUMBER_SERIALIZE" + responses: + 200: + description: "Output number" + schema: + $ref: "#/definitions/OuterNumber" + uppercase_operation_id: "FAKE_OUTER_NUMBER_SERIALIZE" + uppercase_message: "OUTPUT_NUMBER" + uppercase_data_type: "OUTERNUMBER" + operation_id: "fake_outer_number_serialize" + uppercase_operation_id: "FAKE_OUTER_NUMBER_SERIALIZE" + path: "/fake/outer/number" + HttpMethod: "Post" + httpmethod: "post" + /fake/outer/string: + post: + tags: + - "fake" + description: "Test serialization of outer string types" + operationId: "fakeOuterStringSerialize" + parameters: + - in: "body" + name: "body" + description: "Input string as post body" + required: false + schema: + $ref: "#/definitions/OuterString" + uppercase_data_type: "OUTERSTRING" + refName: "OuterString" + formatString: "{:?}" + example: "None" + model_key: "itemList" + uppercase_operation_id: "FAKE_OUTER_STRING_SERIALIZE" + responses: + 200: + description: "Output string" + schema: + $ref: "#/definitions/OuterString" + uppercase_operation_id: "FAKE_OUTER_STRING_SERIALIZE" + uppercase_message: "OUTPUT_STRING" + uppercase_data_type: "OUTERSTRING" + operation_id: "fake_outer_string_serialize" + uppercase_operation_id: "FAKE_OUTER_STRING_SERIALIZE" + path: "/fake/outer/string" + HttpMethod: "Post" + httpmethod: "post" + /fake/outer/boolean: + post: + tags: + - "fake" + description: "Test serialization of outer boolean types" + operationId: "fakeOuterBooleanSerialize" + parameters: + - in: "body" + name: "body" + description: "Input boolean as post body" + required: false + schema: + $ref: "#/definitions/OuterBoolean" + uppercase_data_type: "OUTERBOOLEAN" + refName: "OuterBoolean" + formatString: "{:?}" + example: "None" + model_key: "itemList" + uppercase_operation_id: "FAKE_OUTER_BOOLEAN_SERIALIZE" + responses: + 200: + description: "Output boolean" + schema: + $ref: "#/definitions/OuterBoolean" + uppercase_operation_id: "FAKE_OUTER_BOOLEAN_SERIALIZE" + uppercase_message: "OUTPUT_BOOLEAN" + uppercase_data_type: "OUTERBOOLEAN" + operation_id: "fake_outer_boolean_serialize" + uppercase_operation_id: "FAKE_OUTER_BOOLEAN_SERIALIZE" + path: "/fake/outer/boolean" + HttpMethod: "Post" + httpmethod: "post" + /fake/outer/composite: + post: + tags: + - "fake" + description: "Test serialization of object with outer number type" + operationId: "fakeOuterCompositeSerialize" + parameters: + - in: "body" + name: "body" + description: "Input composite as post body" + required: false + schema: + $ref: "#/definitions/OuterComposite" + uppercase_data_type: "OUTERCOMPOSITE" + refName: "OuterComposite" + formatString: "{:?}" + example: "None" + model_key: "itemList" + uppercase_operation_id: "FAKE_OUTER_COMPOSITE_SERIALIZE" + responses: + 200: + description: "Output composite" + schema: + $ref: "#/definitions/OuterComposite" + uppercase_operation_id: "FAKE_OUTER_COMPOSITE_SERIALIZE" + uppercase_message: "OUTPUT_COMPOSITE" + uppercase_data_type: "OUTERCOMPOSITE" + operation_id: "fake_outer_composite_serialize" + uppercase_operation_id: "FAKE_OUTER_COMPOSITE_SERIALIZE" + path: "/fake/outer/composite" + HttpMethod: "Post" + httpmethod: "post" + /fake/jsonFormData: + get: + tags: + - "fake" + summary: "test json serialization of form data" + description: "" + operationId: "testJsonFormData" + consumes: + - "application/json" + parameters: + - name: "param" + in: "formData" + description: "field1" + required: true + type: "string" + formatString: "\\\"{}\\\"" + example: "\"param_example\".to_string()" + - name: "param2" + in: "formData" + description: "field2" + required: true + type: "string" + formatString: "\\\"{}\\\"" + example: "\"param2_example\".to_string()" + responses: + 200: + description: "successful operation" + uppercase_operation_id: "TEST_JSON_FORM_DATA" + uppercase_message: "SUCCESSFUL_OPERATION" + operation_id: "test_json_form_data" + uppercase_operation_id: "TEST_JSON_FORM_DATA" + path: "/fake/jsonFormData" + HttpMethod: "Get" + httpmethod: "get" + /fake/xmlFeatures: + get: + summary: "Get some XML" + operationId: "getXmlFeatures" + consumes: + - "application/xml" + produces: + - "application/xml" + parameters: [] + responses: + 200: + description: "Success" + schema: + $ref: "#/definitions/xmlObject" + uppercase_operation_id: "GET_XML_FEATURES" + uppercase_message: "SUCCESS" + uppercase_data_type: "XMLOBJECT" + producesXml: true + has_namespace: "true" + operation_id: "get_xml_features" + uppercase_operation_id: "GET_XML_FEATURES" + path: "/fake/xmlFeatures" + HttpMethod: "Get" + httpmethod: "get" + post: + summary: "Post some xml" + operationId: "postXmlFeatures" + consumes: + - "application/xml" + produces: + - "application/xml" + parameters: + - in: "body" + name: "xmlObject" + required: true + schema: + $ref: "#/definitions/xmlObject" + uppercase_data_type: "XMLOBJECT" + refName: "xmlObject" + formatString: "{:?}" + example: "???" + has_namespace: "true" + model_key: "itemList" + uppercase_operation_id: "POST_XML_FEATURES" + consumesXml: true + responses: + 200: + description: "Success" + uppercase_operation_id: "POST_XML_FEATURES" + uppercase_message: "SUCCESS" + operation_id: "post_xml_features" + uppercase_operation_id: "POST_XML_FEATURES" + path: "/fake/xmlFeatures" + HttpMethod: "Post" + httpmethod: "post" + noClientExample: true + /another-fake/dummy: + patch: + tags: + - "$another-fake?" + summary: "To test special tags" + description: "To test special tags" + operationId: "test_special_tags" + consumes: + - "application/json" + produces: + - "application/json" + parameters: + - in: "body" + name: "body" + description: "client model" + required: true + schema: + $ref: "#/definitions/Client" + uppercase_data_type: "CLIENT" + refName: "Client" + formatString: "{:?}" + example: "???" + model_key: "itemList" + uppercase_operation_id: "TEST_SPECIAL_TAGS" + responses: + 200: + description: "successful operation" + schema: + $ref: "#/definitions/Client" + uppercase_operation_id: "TEST_SPECIAL_TAGS" + uppercase_message: "SUCCESSFUL_OPERATION" + uppercase_data_type: "CLIENT" + operation_id: "test_special_tags" + uppercase_operation_id: "TEST_SPECIAL_TAGS" + path: "/another-fake/dummy" + HttpMethod: "Patch" + httpmethod: "patch" + noClientExample: true +securityDefinitions: + petstore_auth: + type: "oauth2" + authorizationUrl: "http://petstore.swagger.io/api/oauth/dialog" + flow: "implicit" + scopes: + write:pets: "modify pets in your account" + read:pets: "read your pets" + api_key: + type: "apiKey" + name: "api_key" + in: "header" + api_key_query: + type: "apiKey" + name: "api_key_query" + in: "query" + http_basic_test: + type: "basic" +definitions: + Order: + type: "object" + properties: + id: + type: "integer" + format: "int64" + petId: + type: "integer" + format: "int64" + quantity: + type: "integer" + format: "int32" + shipDate: + type: "string" + format: "date-time" + status: + type: "string" + description: "Order Status" + enum: + - "placedtest" + - "approved" + - "delivered" + complete: + type: "boolean" + default: false + example: + petId: 6 + quantity: 1 + id: 0 + shipDate: "2000-01-23T04:56:07.000+00:00" + complete: false + status: "placedtest" + xml: + name: "Order" + upperCaseName: "ORDER" + Category: + type: "object" + properties: + id: + type: "integer" + format: "int64" + name: + type: "string" + example: + name: "name" + id: 6 + xml: + name: "Category" + upperCaseName: "CATEGORY" + User: + type: "object" + properties: + id: + type: "integer" + format: "int64" + x-is-unique: true + username: + type: "string" + firstName: + type: "string" + lastName: + type: "string" + email: + type: "string" + password: + type: "string" + phone: + type: "string" + userStatus: + type: "integer" + format: "int32" + description: "User Status" + example: + firstName: "firstName" + lastName: "lastName" + password: "password" + userStatus: 6 + phone: "phone" + id: 0 + email: "email" + username: "username" + xml: + name: "User" + upperCaseName: "USER" + Tag: + type: "object" + properties: + id: + type: "integer" + format: "int64" + name: + type: "string" + example: + name: "name" + id: 1 + xml: + name: "Tag" + upperCaseName: "TAG" + Pet: + type: "object" + required: + - "name" + - "photoUrls" + properties: + id: + type: "integer" + format: "int64" + x-is-unique: true + category: + $ref: "#/definitions/Category" + name: + type: "string" + example: "doggie" + photoUrls: + type: "array" + xml: + name: "photoUrl" + wrapped: true + items: + type: "string" + tags: + type: "array" + xml: + name: "tag" + wrapped: true + items: + $ref: "#/definitions/Tag" + status: + type: "string" + description: "pet status in the store" + enum: + - "available" + - "pending" + - "sold" + example: + photoUrls: + - "photoUrls" + - "photoUrls" + name: "doggie" + id: 0 + category: + name: "name" + id: 6 + tags: + - name: "name" + id: 1 + - name: "name" + id: 1 + status: "available" + xml: + name: "Pet" + upperCaseName: "PET" + ApiResponse: + type: "object" + properties: + code: + type: "integer" + format: "int32" + type: + type: "string" + message: + type: "string" + example: + code: 0 + type: "type" + message: "message" + upperCaseName: "APIRESPONSE" + $special[model.name]: + properties: + $special[property.name]: + type: "integer" + format: "int64" + xml: + name: "$special[model.name]" + upperCaseName: "$SPECIAL[MODEL.NAME]" + Return: + properties: + return: + type: "integer" + format: "int32" + description: "Model for testing reserved words" + xml: + name: "Return" + upperCaseName: "RETURN" + Name: + required: + - "name" + properties: + name: + type: "integer" + format: "int32" + snake_case: + type: "integer" + format: "int32" + readOnly: true + property: + type: "string" + 123Number: + type: "integer" + readOnly: true + description: "Model for testing model name same as property name" + xml: + name: "Name" + upperCaseName: "NAME" + 200_response: + properties: + name: + type: "integer" + format: "int32" + class: + type: "string" + description: "Model for testing model name starting with number" + xml: + name: "Name" + upperCaseName: "200_RESPONSE" + ClassModel: + properties: + _class: + type: "string" + description: "Model for testing model with \"_class\" property" + upperCaseName: "CLASSMODEL" + Dog: + allOf: + - $ref: "#/definitions/Animal" + - type: "object" + properties: + breed: + type: "string" + upperCaseName: "DOG" + Cat: + allOf: + - $ref: "#/definitions/Animal" + - type: "object" + properties: + declawed: + type: "boolean" + upperCaseName: "CAT" + Animal: + type: "object" + required: + - "className" + discriminator: "className" + properties: + className: + type: "string" + color: + type: "string" + default: "red" + upperCaseName: "ANIMAL" + AnimalFarm: + type: "array" + items: + $ref: "#/definitions/Animal" + upperCaseName: "ANIMALFARM" + format_test: + type: "object" + required: + - "byte" + - "date" + - "number" + - "password" + properties: + integer: + type: "integer" + minimum: 10 + maximum: 100 + int32: + type: "integer" + format: "int32" + minimum: 20 + maximum: 200 + int64: + type: "integer" + format: "int64" + number: + type: "number" + minimum: 32.1 + maximum: 543.2 + float: + type: "number" + format: "float" + minimum: 54.3 + maximum: 987.6 + double: + type: "number" + format: "double" + minimum: 67.8 + maximum: 123.4 + string: + type: "string" + pattern: "/[a-z]/i" + byte: + type: "string" + format: "byte" + pattern: "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$" + binary: + type: "string" + format: "binary" + date: + type: "string" + format: "date" + dateTime: + type: "string" + format: "date-time" + uuid: + type: "string" + format: "uuid" + password: + type: "string" + format: "password" + minLength: 10 + maxLength: 64 + upperCaseName: "FORMAT_TEST" + EnumClass: + type: "string" + enum: + - "_abc" + - "-efg" + - "(xyz)" + default: "-efg" + upperCaseName: "ENUMCLASS" + Enum_Test: + type: "object" + properties: + enum_string: + type: "string" + enum: + - "UPPER" + - "lower" + - "" + enum_integer: + type: "integer" + format: "int32" + enum: + - 1 + - -1 + enum_number: + type: "number" + format: "double" + enum: + - 1.1 + - -1.2 + outerEnum: + $ref: "#/definitions/OuterEnum" + upperCaseName: "ENUM_TEST" + AdditionalPropertiesClass: + type: "object" + properties: + map_property: + type: "object" + additionalProperties: + type: "string" + map_of_map_property: + type: "object" + additionalProperties: + type: "object" + additionalProperties: + type: "string" + upperCaseName: "ADDITIONALPROPERTIESCLASS" + MixedPropertiesAndAdditionalPropertiesClass: + type: "object" + properties: + uuid: + type: "string" + format: "uuid" + dateTime: + type: "string" + format: "date-time" + map: + type: "object" + additionalProperties: + $ref: "#/definitions/Animal" + upperCaseName: "MIXEDPROPERTIESANDADDITIONALPROPERTIESCLASS" + List: + type: "object" + properties: + 123-list: + type: "string" + upperCaseName: "LIST" + Client: + type: "object" + properties: + client: + type: "string" + example: + client: "client" + upperCaseName: "CLIENT" + ReadOnlyFirst: + type: "object" + properties: + bar: + type: "string" + readOnly: true + baz: + type: "string" + upperCaseName: "READONLYFIRST" + hasOnlyReadOnly: + type: "object" + properties: + bar: + type: "string" + readOnly: true + foo: + type: "string" + readOnly: true + upperCaseName: "HASONLYREADONLY" + Capitalization: + type: "object" + properties: + smallCamel: + type: "string" + CapitalCamel: + type: "string" + small_Snake: + type: "string" + Capital_Snake: + type: "string" + SCA_ETH_Flow_Points: + type: "string" + ATT_NAME: + type: "string" + description: "Name of the pet\n" + upperCaseName: "CAPITALIZATION" + MapTest: + type: "object" + properties: + map_map_of_string: + type: "object" + additionalProperties: + type: "object" + additionalProperties: + type: "string" + map_of_enum_string: + type: "object" + additionalProperties: + type: "string" + enum: + - "UPPER" + - "lower" + upperCaseName: "MAPTEST" + ArrayTest: + type: "object" + properties: + array_of_string: + type: "array" + items: + type: "string" + array_array_of_integer: + type: "array" + items: + type: "array" + items: + type: "integer" + format: "int64" + array_array_of_model: + type: "array" + items: + type: "array" + items: + $ref: "#/definitions/ReadOnlyFirst" + upperCaseName: "ARRAYTEST" + NumberOnly: + type: "object" + properties: + JustNumber: + type: "number" + upperCaseName: "NUMBERONLY" + ArrayOfNumberOnly: + type: "object" + properties: + ArrayNumber: + type: "array" + items: + type: "number" + upperCaseName: "ARRAYOFNUMBERONLY" + ArrayOfArrayOfNumberOnly: + type: "object" + properties: + ArrayArrayNumber: + type: "array" + items: + type: "array" + items: + type: "number" + upperCaseName: "ARRAYOFARRAYOFNUMBERONLY" + EnumArrays: + type: "object" + properties: + just_symbol: + type: "string" + enum: + - ">=" + - "$" + array_enum: + type: "array" + items: + type: "string" + enum: + - "fish" + - "crab" + upperCaseName: "ENUMARRAYS" + OuterEnum: + type: "string" + enum: + - "placed" + - "approved" + - "delivered" + upperCaseName: "OUTERENUM" + OuterNumber: + type: "number" + upperCaseName: "OUTERNUMBER" + OuterString: + type: "string" + upperCaseName: "OUTERSTRING" + OuterBoolean: + type: "boolean" + upperCaseName: "OUTERBOOLEAN" + OuterComposite: + type: "object" + properties: + my_number: + $ref: "#/definitions/OuterNumber" + my_string: + $ref: "#/definitions/OuterString" + my_boolean: + $ref: "#/definitions/OuterBoolean" + example: + my_string: {} + my_number: {} + my_boolean: {} + upperCaseName: "OUTERCOMPOSITE" + xmlObject: + required: + - "itemList" + - "name" + properties: + name: + type: "string" + example: "myXmlObject" + itemList: + $ref: "#/definitions/itemList" + itemXmlName: "item" + xml: + name: "group" + namespace: "http://example.com/schema.xsd" + upperCaseName: "XMLOBJECT" + itemList: + type: "array" + items: + type: "string" + example: "my item" + xml: + name: "item" + upperCaseName: "ITEMLIST" + itemXmlName: "item" +externalDocs: + description: "Find out more about Swagger" + url: "http://swagger.io" diff --git a/samples/client/petstore/rust2/examples/ca.pem b/samples/client/petstore/rust2/examples/ca.pem new file mode 100644 index 000000000000..d2317fb5db7d --- /dev/null +++ b/samples/client/petstore/rust2/examples/ca.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICtjCCAZ4CCQDpKecRERZ0xDANBgkqhkiG9w0BAQsFADAdMQswCQYDVQQGEwJV +UzEOMAwGA1UEAxMFTXkgQ0EwHhcNMTcwNTIzMTYwMDIzWhcNMTcwNjIyMTYwMDIz +WjAdMQswCQYDVQQGEwJVUzEOMAwGA1UEAxMFTXkgQ0EwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCt66py3x7sCSASRF2D05L5wkNDxAUjQKYx23W8Gbwv +GMGykk89BIdU5LX1JB1cKiUOkoIxfwAYuWc2V/wzTvVV7+11besnk3uX1c9KiqUF +LIX7kn/z5hzS4aelhKvH+MJlSZCSlp1ytpZbwo5GB5Pi2SGH56jDBiBoDRNBVdWL +z4wH7TdrQjqWwNxIZumD5OGMtcfJyuX08iPiEOaslOeoMqzObhvjc9aUgjVjhqyA +FkJGTXsi0oaD7oml+NE+mTNfEeZvEJQpLSjBY0OvQHzuHkyGBShBnfu/9x7/NRwd +WaqsLiF7/re9KDGYdJwP7Cu6uxYfKAyWarp6h2mG/GIdAgMBAAEwDQYJKoZIhvcN +AQELBQADggEBAGIl/VVIafeq/AJOQ9r7TzzB2ABJYr7NZa6bTu5O1jSp1Fonac15 +SZ8gvRxODgH22ZYSqghPG4xzq4J3hkytlQqm57ZEt2I2M3OqIp17Ndcc1xDYzpLl +tA0FrVn6crQTM8vQkTDtGesaCWX+7Fir5dK7HnYWzfpSmsOpST07PfbNisEXKOxG +Dj4lBL1OnhTjsJeymVS1pFvkKkrcEJO+IxFiHL3CDsWjcXB0Z+E1zBtPoYyYsNsO +rBrjUxcZewF4xqWZhpW90Mt61fY2nRgU0uUwHcvDQUqvmzKcsqYa4mPKzfBI5mxo +01Ta96cDD6pS5Y1hOflZ0g84f2g/7xBLLDA= +-----END CERTIFICATE----- diff --git a/samples/client/petstore/rust2/examples/client.rs b/samples/client/petstore/rust2/examples/client.rs new file mode 100644 index 000000000000..6fd88afc5b63 --- /dev/null +++ b/samples/client/petstore/rust2/examples/client.rs @@ -0,0 +1,275 @@ +#![allow(missing_docs, unused_variables, trivial_casts)] + +extern crate petstore_api; +#[allow(unused_extern_crates)] +extern crate futures; +#[allow(unused_extern_crates)] +extern crate swagger; +#[allow(unused_extern_crates)] +extern crate uuid; +extern crate clap; + +#[allow(unused_imports)] +use futures::{Future, future, Stream, stream}; +#[allow(unused_imports)] +use petstore_api::{ApiNoContext, ContextWrapperExt, + ApiError, + TestSpecialTagsResponse, + GetXmlFeaturesResponse, + PostXmlFeaturesResponse, + FakeOuterBooleanSerializeResponse, + FakeOuterCompositeSerializeResponse, + FakeOuterNumberSerializeResponse, + FakeOuterStringSerializeResponse, + TestClientModelResponse, + TestEndpointParametersResponse, + TestEnumParametersResponse, + TestJsonFormDataResponse, + TestClassnameResponse, + AddPetResponse, + DeletePetResponse, + FindPetsByStatusResponse, + FindPetsByTagsResponse, + GetPetByIdResponse, + UpdatePetResponse, + UpdatePetWithFormResponse, + UploadFileResponse, + DeleteOrderResponse, + GetInventoryResponse, + GetOrderByIdResponse, + PlaceOrderResponse, + CreateUserResponse, + CreateUsersWithArrayInputResponse, + CreateUsersWithListInputResponse, + DeleteUserResponse, + GetUserByNameResponse, + LoginUserResponse, + LogoutUserResponse, + UpdateUserResponse + }; +use clap::{App, Arg}; + +fn main() { + let matches = App::new("client") + .arg(Arg::with_name("operation") + .help("Sets the operation to run") + .possible_values(&[ + "GetXmlFeatures", + "FakeOuterBooleanSerialize", + "FakeOuterCompositeSerialize", + "FakeOuterNumberSerialize", + "FakeOuterStringSerialize", + "TestEndpointParameters", + "TestEnumParameters", + "TestJsonFormData", + "DeletePet", + "FindPetsByStatus", + "FindPetsByTags", + "GetPetById", + "UpdatePetWithForm", + "UploadFile", + "DeleteOrder", + "GetInventory", + "GetOrderById", + "CreateUsersWithArrayInput", + "CreateUsersWithListInput", + "DeleteUser", + "GetUserByName", + "LoginUser", + "LogoutUser", +]) + .required(true) + .index(1)) + .arg(Arg::with_name("https") + .long("https") + .help("Whether to use HTTPS or not")) + .get_matches(); + + let client = if matches.is_present("https") { + // Using Simple HTTPS + petstore_api::Client::try_new_https("https://localhost:8080", "examples/ca.pem").expect("Failed to create HTTPS client") + } else { + // Using HTTP + petstore_api::Client::try_new_http("http://localhost:8080").expect("Failed to create HTTP client") + }; + + // Using a non-default `Context` is not required; this is just an example! + let client = client.with_context(petstore_api::Context::new_with_span_id(self::uuid::Uuid::new_v4().to_string())); + + match matches.value_of("operation") { + + // Disabled because there's no example. + // Some("TestSpecialTags") => { + // let result = client.test_special_tags(???).wait(); + // println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + // }, + + Some("GetXmlFeatures") => { + let result = client.get_xml_features().wait(); + println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + }, + + // Disabled because there's no example. + // Some("PostXmlFeatures") => { + // let result = client.post_xml_features(???).wait(); + // println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + // }, + + Some("FakeOuterBooleanSerialize") => { + let result = client.fake_outer_boolean_serialize(None).wait(); + println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + }, + + Some("FakeOuterCompositeSerialize") => { + let result = client.fake_outer_composite_serialize(None).wait(); + println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + }, + + Some("FakeOuterNumberSerialize") => { + let result = client.fake_outer_number_serialize(None).wait(); + println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + }, + + Some("FakeOuterStringSerialize") => { + let result = client.fake_outer_string_serialize(None).wait(); + println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + }, + + // Disabled because there's no example. + // Some("TestClientModel") => { + // let result = client.test_client_model(???).wait(); + // println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + // }, + + Some("TestEndpointParameters") => { + let result = client.test_endpoint_parameters(3.4, 1.2, "pattern_without_delimiter_example".to_string(), swagger::ByteArray("byte_example".to_string().into_bytes()), Some(56), Some(56), Some(789), Some(3.4), Some("string_example".to_string()), Some(swagger::ByteArray(Vec::from("B"))), None, None, Some("password_example".to_string()), Some("callback_example".to_string())).wait(); + println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + }, + + Some("TestEnumParameters") => { + let result = client.test_enum_parameters(Some(&Vec::new()), Some("enum_form_string_example".to_string()), Some(&Vec::new()), Some("enum_header_string_example".to_string()), Some(&Vec::new()), Some("enum_query_string_example".to_string()), Some(56), Some(1.2)).wait(); + println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + }, + + Some("TestJsonFormData") => { + let result = client.test_json_form_data("param_example".to_string(), "param2_example".to_string()).wait(); + println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + }, + + // Disabled because there's no example. + // Some("TestClassname") => { + // let result = client.test_classname(???).wait(); + // println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + // }, + + // Disabled because there's no example. + // Some("AddPet") => { + // let result = client.add_pet(???).wait(); + // println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + // }, + + Some("DeletePet") => { + let result = client.delete_pet(789, Some("api_key_example".to_string())).wait(); + println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + }, + + Some("FindPetsByStatus") => { + let result = client.find_pets_by_status(&Vec::new()).wait(); + println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + }, + + Some("FindPetsByTags") => { + let result = client.find_pets_by_tags(&Vec::new()).wait(); + println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + }, + + Some("GetPetById") => { + let result = client.get_pet_by_id(789).wait(); + println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + }, + + // Disabled because there's no example. + // Some("UpdatePet") => { + // let result = client.update_pet(???).wait(); + // println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + // }, + + Some("UpdatePetWithForm") => { + let result = client.update_pet_with_form(789, Some("name_example".to_string()), Some("status_example".to_string())).wait(); + println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + }, + + Some("UploadFile") => { + let result = client.upload_file(789, Some("additional_metadata_example".to_string()), Box::new(future::ok(Some(Box::new(stream::once(Ok(b"hello".to_vec()))) as Box + Send>))) as Box + Send>).wait(); + println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + }, + + Some("DeleteOrder") => { + let result = client.delete_order("order_id_example".to_string()).wait(); + println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + }, + + Some("GetInventory") => { + let result = client.get_inventory().wait(); + println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + }, + + Some("GetOrderById") => { + let result = client.get_order_by_id(789).wait(); + println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + }, + + // Disabled because there's no example. + // Some("PlaceOrder") => { + // let result = client.place_order(???).wait(); + // println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + // }, + + // Disabled because there's no example. + // Some("CreateUser") => { + // let result = client.create_user(???).wait(); + // println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + // }, + + Some("CreateUsersWithArrayInput") => { + let result = client.create_users_with_array_input(&Vec::new()).wait(); + println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + }, + + Some("CreateUsersWithListInput") => { + let result = client.create_users_with_list_input(&Vec::new()).wait(); + println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + }, + + Some("DeleteUser") => { + let result = client.delete_user("username_example".to_string()).wait(); + println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + }, + + Some("GetUserByName") => { + let result = client.get_user_by_name("username_example".to_string()).wait(); + println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + }, + + Some("LoginUser") => { + let result = client.login_user("username_example".to_string(), "password_example".to_string()).wait(); + println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + }, + + Some("LogoutUser") => { + let result = client.logout_user().wait(); + println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + }, + + // Disabled because there's no example. + // Some("UpdateUser") => { + // let result = client.update_user("username_example".to_string(), ???).wait(); + // println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from(""))); + // }, + + _ => { + panic!("Invalid operation provided") + } + } +} + diff --git a/samples/client/petstore/rust2/examples/server-chain.pem b/samples/client/petstore/rust2/examples/server-chain.pem new file mode 100644 index 000000000000..47d7e2014046 --- /dev/null +++ b/samples/client/petstore/rust2/examples/server-chain.pem @@ -0,0 +1,66 @@ +Certificate: + Data: + Version: 1 (0x0) + Serial Number: 4096 (0x1000) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, CN=My CA + Validity + Not Before: May 23 16:00:23 2017 GMT + Not After : Apr 29 16:00:23 2117 GMT + Subject: CN=localhost, C=US + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:c9:d4:43:60:50:fc:d6:0f:38:4d:5d:5e:aa:7c: + c0:5e:a9:ec:d9:93:78:d3:93:72:28:41:f5:08:a5: + ea:ac:67:07:d7:1f:f7:7d:74:69:7e:46:89:20:4b: + 7a:2d:9b:02:08:e7:6f:0f:1d:0c:0f:c7:60:69:19: + 4b:df:7e:ca:75:94:0b:49:71:e3:6d:f2:e8:79:fd: + ed:0a:94:67:55:f3:ca:6b:61:ba:58:b7:2e:dd:7b: + ca:b9:02:9f:24:36:ac:26:8f:04:8f:81:c8:35:10: + f4:aa:33:b2:24:16:f8:f7:1e:ea:f7:16:fe:fa:34: + c3:dd:bb:2c:ba:7a:df:4d:e2:da:1e:e5:d2:28:44: + 6e:c8:96:e0:fd:09:0c:14:0c:31:dc:e0:ca:c1:a7: + 9b:bf:16:8c:f7:36:3f:1b:2e:dd:90:eb:45:78:51: + bf:59:22:1e:c6:8c:0a:69:88:e5:03:5e:73:b7:fc: + 93:7f:1b:46:1b:97:68:c5:c0:8b:35:1f:bb:1e:67: + 7f:55:b7:3b:55:3f:ea:f2:ca:db:cc:52:cd:16:89: + db:15:47:bd:f2:cd:6c:7a:d7:b4:1a:ac:c8:15:6c: + 6a:fb:77:c4:e9:f2:30:e0:14:24:66:65:6f:2a:e5: + 2d:cc:f6:81:ae:57:c8:d1:9b:38:90:dc:60:93:02: + 5e:cb + Exponent: 65537 (0x10001) + Signature Algorithm: sha256WithRSAEncryption + 1c:7c:39:e8:3d:49:b2:09:1e:68:5a:2f:74:18:f4:63:b5:8c: + f6:e6:a1:e3:4d:95:90:99:ef:32:5c:34:40:e8:55:13:0e:e0: + 1c:be:cd:ab:3f:64:38:99:5e:2b:c1:81:53:a0:18:a8:f6:ee: + 6a:33:73:6c:9a:73:9d:86:08:5d:c7:11:38:46:4c:cd:a0:47: + 37:8f:fe:a6:50:a9:02:21:99:42:86:5e:47:fe:65:56:60:1d: + 16:53:86:bd:e4:63:c5:69:cf:fa:30:51:ab:a1:c3:50:53:cc: + 66:1c:4c:ff:3f:2a:39:4d:a2:8f:9d:d1:a7:8b:22:e4:78:69: + 24:06:83:4d:cc:0a:c0:87:69:9b:bc:80:a9:d2:b7:a5:23:84: + 7e:a2:32:26:7c:78:0e:bd:db:cd:3b:69:18:33:b8:44:ef:96: + b4:99:86:ee:06:bd:51:1c:c7:a1:a4:0c:c4:4c:51:a0:df:ac: + 14:07:88:8e:d7:39:45:fe:52:e0:a3:4c:db:5d:7a:ab:4d:e4: + ca:06:e8:bd:74:6f:46:e7:93:4a:4f:1b:67:e7:a5:9f:ef:9c: + 02:49:d1:f2:d5:e9:53:ee:09:21:ac:08:c8:15:f7:af:35:b9: + 4f:11:0f:43:ae:46:8e:fd:5b:8d:a3:4e:a7:2c:b7:25:ed:e4: + e5:94:1d:e3 +-----BEGIN CERTIFICATE----- +MIICtTCCAZ0CAhAAMA0GCSqGSIb3DQEBCwUAMB0xCzAJBgNVBAYTAlVTMQ4wDAYD +VQQDEwVNeSBDQTAgFw0xNzA1MjMxNjAwMjNaGA8yMTE3MDQyOTE2MDAyM1owITES +MBAGA1UEAxMJbG9jYWxob3N0MQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAMnUQ2BQ/NYPOE1dXqp8wF6p7NmTeNOTcihB9Qil6qxn +B9cf9310aX5GiSBLei2bAgjnbw8dDA/HYGkZS99+ynWUC0lx423y6Hn97QqUZ1Xz +ymthuli3Lt17yrkCnyQ2rCaPBI+ByDUQ9KozsiQW+Pce6vcW/vo0w927LLp6303i +2h7l0ihEbsiW4P0JDBQMMdzgysGnm78WjPc2Pxsu3ZDrRXhRv1kiHsaMCmmI5QNe +c7f8k38bRhuXaMXAizUfux5nf1W3O1U/6vLK28xSzRaJ2xVHvfLNbHrXtBqsyBVs +avt3xOnyMOAUJGZlbyrlLcz2ga5XyNGbOJDcYJMCXssCAwEAATANBgkqhkiG9w0B +AQsFAAOCAQEAHHw56D1JsgkeaFovdBj0Y7WM9uah402VkJnvMlw0QOhVEw7gHL7N +qz9kOJleK8GBU6AYqPbuajNzbJpznYYIXccROEZMzaBHN4/+plCpAiGZQoZeR/5l +VmAdFlOGveRjxWnP+jBRq6HDUFPMZhxM/z8qOU2ij53Rp4si5HhpJAaDTcwKwIdp +m7yAqdK3pSOEfqIyJnx4Dr3bzTtpGDO4RO+WtJmG7ga9URzHoaQMxExRoN+sFAeI +jtc5Rf5S4KNM2116q03kygbovXRvRueTSk8bZ+eln++cAknR8tXpU+4JIawIyBX3 +rzW5TxEPQ65Gjv1bjaNOpyy3Je3k5ZQd4w== +-----END CERTIFICATE----- diff --git a/samples/client/petstore/rust2/examples/server-key.pem b/samples/client/petstore/rust2/examples/server-key.pem new file mode 100644 index 000000000000..29c006829229 --- /dev/null +++ b/samples/client/petstore/rust2/examples/server-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDJ1ENgUPzWDzhN +XV6qfMBeqezZk3jTk3IoQfUIpeqsZwfXH/d9dGl+RokgS3otmwII528PHQwPx2Bp +GUvffsp1lAtJceNt8uh5/e0KlGdV88prYbpYty7de8q5Ap8kNqwmjwSPgcg1EPSq +M7IkFvj3Hur3Fv76NMPduyy6et9N4toe5dIoRG7IluD9CQwUDDHc4MrBp5u/Foz3 +Nj8bLt2Q60V4Ub9ZIh7GjAppiOUDXnO3/JN/G0Ybl2jFwIs1H7seZ39VtztVP+ry +ytvMUs0WidsVR73yzWx617QarMgVbGr7d8Tp8jDgFCRmZW8q5S3M9oGuV8jRmziQ +3GCTAl7LAgMBAAECggEBAKEd1q9j14KWYc64s6KLthGbutyxsinMMbxbct11fdIk +6YhdF3fJ35ETg9IJDr6rWEN9ZRX+jStncNpVfFEs6ThVd3Eo/nI+EEGaaIkikR93 +X2a7fEPn7/yVHu70XdBN6L1bPDvHUeiy4W2hmRrgT90OjGm1rNRWHOm7yugOwIZu +HclzbR9Ca7EInFnotUiDQm9sw9VKHbJHqWx6OORdZrxR2ytYs0Qkq0XpGMvti2HW +7WAmKTg5QM8myXW7+/4iqb/u68wVBR2BBalShKmIf7lim9O3W2a1RjDdsvm/wNe9 +I+D+Iq825vpqkKXcrxYlpVg7hYiaQaW/MNsEb7lQRjECgYEA/RJYby0POW+/k0Jn +jO8UmJVEMiuGa8WIUu/JJWMOmzRCukjSRNQOkt7niQrZPJYE8W6clM6RJTolWf9L +IL6mIb+mRaoudUk8SHGDq7ho1iMg9GK8lhYxvKh1Q6uv8EyVSkgLknAEY0NANKC1 +zNdU5Dhven9aRX2gq9vP4XwMz2MCgYEAzCogQ7IFk+gkp3k491dOZnrGRoRCfuzo +4CJtyKFgOSd7BjmpcKkj0IPfVBjw6GjMIxfQRMTQmxAjjWevH45vG8l0Iiwz/gSp +81b5nsDEX5uv2Olcmcz5zxRFy36jOZ9ihMWinxcIlT2oDbyCdbruDKZq9ieJ9S8g +4qGx0OkwE3kCgYEA7CmAiU89U9YqqttfEq/RQoqY91CSwmO10d+ej9seuEtOsdRf +FIfnibulycdr7hP5TOxyBpO1802NqayJiWcgVYIpQf2MGTtcnCYCP+95NcvWZvj1 +EAJqK6nwtFO1fcOZ1ZXh5qfOEGujsPkAbsXLnKXlsiTCMvMHSxl3pu5Cbg0CgYBf +JjbZNctRrjv+7Qj2hPLd4dQsIxGWc7ToWENP4J2mpVa5hQAJqFovoHXhjKohtk2F +AWEn243Y5oGbMjo0e74edhmwn2cvuF64MM2vBem/ISCn98IXT6cQskMA3qkVfsl8 +VVs/x41ReGWs2TD3y0GMFbb9t1mdMfSiincDhNnKCQKBgGfeT4jKyYeCoCw4OLI1 +G75Gd0METt/IkppwODPpNwj3Rp9I5jctWZFA/3wCX/zk0HgBeou5AFNS4nQZ/X/L +L9axbSdR7UJTGkT1r4gu3rLkPV4Tk+8XM03/JT2cofMlzQBuhvl1Pn4SgKowz7hl +lS76ECw4Av3T0S34VW9Z5oye +-----END PRIVATE KEY----- diff --git a/samples/client/petstore/rust2/examples/server.rs b/samples/client/petstore/rust2/examples/server.rs new file mode 100644 index 000000000000..f3f3f50de4b6 --- /dev/null +++ b/samples/client/petstore/rust2/examples/server.rs @@ -0,0 +1,58 @@ +#![allow(missing_docs)] + +extern crate petstore_api; +extern crate iron; +extern crate futures; +extern crate hyper_openssl; +extern crate clap; +extern crate swagger; + +use hyper_openssl::OpensslServer; +use hyper_openssl::openssl::x509::X509_FILETYPE_PEM; +use hyper_openssl::openssl::ssl::{SslAcceptorBuilder, SslMethod}; +use hyper_openssl::openssl::error::ErrorStack; +use clap::{App, Arg}; +use iron::{Iron, Chain}; +use swagger::auth::AllowAllMiddleware; + +// Import the module that defines the Server struct. +mod server_lib; + +/// Builds an SSL implementation for Simple HTTPS from some hard-coded file names +fn ssl() -> Result { + let mut ssl = SslAcceptorBuilder::mozilla_intermediate_raw(SslMethod::tls())?; + + // Server authentication + ssl.builder_mut().set_private_key_file("examples/server-key.pem", X509_FILETYPE_PEM)?; + ssl.builder_mut().set_certificate_chain_file("examples/server-chain.pem")?; + ssl.builder_mut().check_private_key()?; + + Ok(OpensslServer::from(ssl.build())) +} + +/// Create custom server, wire it to the autogenerated router, +/// and pass it to the web server. +fn main() { + let matches = App::new("server") + .arg(Arg::with_name("https") + .long("https") + .help("Whether to use HTTPS or not")) + .get_matches(); + + let server = server_lib::Server{}; + let router = petstore_api::router(server); + + let mut chain = Chain::new(router); + chain.link_before(petstore_api::server::ExtractAuthData); + // add authentication middlewares into the chain here + // for the purpose of this example, pretend we have authenticated a user + chain.link_before(AllowAllMiddleware::new("cosmo")); + + if matches.is_present("https") { + // Using Simple HTTPS + Iron::new(chain).https("localhost:8080", ssl().expect("Failed to load SSL keys")).expect("Failed to start HTTPS server"); + } else { + // Using HTTP + Iron::new(chain).http("localhost:8080").expect("Failed to start HTTP server"); + } +} diff --git a/samples/client/petstore/rust2/examples/server_lib/mod.rs b/samples/client/petstore/rust2/examples/server_lib/mod.rs new file mode 100644 index 000000000000..598d4a0e946e --- /dev/null +++ b/samples/client/petstore/rust2/examples/server_lib/mod.rs @@ -0,0 +1,279 @@ +#![allow(missing_docs, unused_extern_crates)] +extern crate chrono; +extern crate swagger; + +use futures::{self, Future}; +use futures::Stream; + +#[allow(unused_imports)] +use std::collections::HashMap; +use std::io::Error; + +use petstore_api::{Api, ApiError, Context, + TestSpecialTagsResponse, + GetXmlFeaturesResponse, + PostXmlFeaturesResponse, + FakeOuterBooleanSerializeResponse, + FakeOuterCompositeSerializeResponse, + FakeOuterNumberSerializeResponse, + FakeOuterStringSerializeResponse, + TestClientModelResponse, + TestEndpointParametersResponse, + TestEnumParametersResponse, + TestJsonFormDataResponse, + TestClassnameResponse, + AddPetResponse, + DeletePetResponse, + FindPetsByStatusResponse, + FindPetsByTagsResponse, + GetPetByIdResponse, + UpdatePetResponse, + UpdatePetWithFormResponse, + UploadFileResponse, + DeleteOrderResponse, + GetInventoryResponse, + GetOrderByIdResponse, + PlaceOrderResponse, + CreateUserResponse, + CreateUsersWithArrayInputResponse, + CreateUsersWithListInputResponse, + DeleteUserResponse, + GetUserByNameResponse, + LoginUserResponse, + LogoutUserResponse, + UpdateUserResponse +}; +#[allow(unused_imports)] +use petstore_api::models; + +#[derive(Copy, Clone)] +pub struct Server; + +impl Api for Server { + + /// To test special tags + fn test_special_tags(&self, body: models::Client, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("test_special_tags({:?}) - X-Span-ID: {:?}", body, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// Get some XML + fn get_xml_features(&self, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("get_xml_features() - X-Span-ID: {:?}", context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// Post some xml + fn post_xml_features(&self, xml_object: models::XmlObject, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("post_xml_features({:?}) - X-Span-ID: {:?}", xml_object, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + + fn fake_outer_boolean_serialize(&self, body: Option, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("fake_outer_boolean_serialize({:?}) - X-Span-ID: {:?}", body, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + + fn fake_outer_composite_serialize(&self, body: Option, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("fake_outer_composite_serialize({:?}) - X-Span-ID: {:?}", body, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + + fn fake_outer_number_serialize(&self, body: Option, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("fake_outer_number_serialize({:?}) - X-Span-ID: {:?}", body, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + + fn fake_outer_string_serialize(&self, body: Option, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("fake_outer_string_serialize({:?}) - X-Span-ID: {:?}", body, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// To test \"client\" model + fn test_client_model(&self, body: models::Client, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("test_client_model({:?}) - X-Span-ID: {:?}", body, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트 + fn test_endpoint_parameters(&self, number: f64, double: f64, pattern_without_delimiter: String, byte: swagger::ByteArray, integer: Option, int32: Option, int64: Option, float: Option, string: Option, binary: Option, date: Option>, date_time: Option>, password: Option, callback: Option, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("test_endpoint_parameters({}, {}, \"{}\", \"{:?}\", {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}) - X-Span-ID: {:?}", number, double, pattern_without_delimiter, byte, integer, int32, int64, float, string, binary, date, date_time, password, callback, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// To test enum parameters + fn test_enum_parameters(&self, enum_form_string_array: Option<&Vec>, enum_form_string: Option, enum_header_string_array: Option<&Vec>, enum_header_string: Option, enum_query_string_array: Option<&Vec>, enum_query_string: Option, enum_query_integer: Option, enum_query_double: Option, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("test_enum_parameters({:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?}) - X-Span-ID: {:?}", enum_form_string_array, enum_form_string, enum_header_string_array, enum_header_string, enum_query_string_array, enum_query_string, enum_query_integer, enum_query_double, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// test json serialization of form data + fn test_json_form_data(&self, param: String, param2: String, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("test_json_form_data(\"{}\", \"{}\") - X-Span-ID: {:?}", param, param2, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// To test class name in snake case + fn test_classname(&self, body: models::Client, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("test_classname({:?}) - X-Span-ID: {:?}", body, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// Add a new pet to the store + fn add_pet(&self, body: models::Pet, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("add_pet({:?}) - X-Span-ID: {:?}", body, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// Deletes a pet + fn delete_pet(&self, pet_id: i64, api_key: Option, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("delete_pet({}, {:?}) - X-Span-ID: {:?}", pet_id, api_key, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// Finds Pets by status + fn find_pets_by_status(&self, status: &Vec, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("find_pets_by_status({:?}) - X-Span-ID: {:?}", status, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// Finds Pets by tags + fn find_pets_by_tags(&self, tags: &Vec, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("find_pets_by_tags({:?}) - X-Span-ID: {:?}", tags, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// Find pet by ID + fn get_pet_by_id(&self, pet_id: i64, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("get_pet_by_id({}) - X-Span-ID: {:?}", pet_id, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// Update an existing pet + fn update_pet(&self, body: models::Pet, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("update_pet({:?}) - X-Span-ID: {:?}", body, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// Updates a pet in the store with form data + fn update_pet_with_form(&self, pet_id: i64, name: Option, status: Option, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("update_pet_with_form({}, {:?}, {:?}) - X-Span-ID: {:?}", pet_id, name, status, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// uploads an image + fn upload_file(&self, pet_id: i64, additional_metadata: Option, file: Box, Error=Error> + Send>>, Error=Error> + Send>, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("upload_file({}, {:?}, ) - X-Span-ID: {:?}", pet_id, additional_metadata, context.x_span_id.unwrap_or(String::from("")).clone()); + let _ = file; //Suppresses unused param warning + Box::new(futures::failed("Generic failure".into())) + } + + /// Delete purchase order by ID + fn delete_order(&self, order_id: String, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("delete_order(\"{}\") - X-Span-ID: {:?}", order_id, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// Returns pet inventories by status + fn get_inventory(&self, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("get_inventory() - X-Span-ID: {:?}", context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// Find purchase order by ID + fn get_order_by_id(&self, order_id: i64, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("get_order_by_id({}) - X-Span-ID: {:?}", order_id, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// Place an order for a pet + fn place_order(&self, body: models::Order, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("place_order({:?}) - X-Span-ID: {:?}", body, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// Create user + fn create_user(&self, body: models::User, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("create_user({:?}) - X-Span-ID: {:?}", body, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// Creates list of users with given input array + fn create_users_with_array_input(&self, body: &Vec, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("create_users_with_array_input({:?}) - X-Span-ID: {:?}", body, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// Creates list of users with given input array + fn create_users_with_list_input(&self, body: &Vec, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("create_users_with_list_input({:?}) - X-Span-ID: {:?}", body, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// Delete user + fn delete_user(&self, username: String, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("delete_user(\"{}\") - X-Span-ID: {:?}", username, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// Get user by user name + fn get_user_by_name(&self, username: String, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("get_user_by_name(\"{}\") - X-Span-ID: {:?}", username, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// Logs user into the system + fn login_user(&self, username: String, password: String, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("login_user(\"{}\", \"{}\") - X-Span-ID: {:?}", username, password, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// Logs out current logged in user session + fn logout_user(&self, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("logout_user() - X-Span-ID: {:?}", context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + + /// Updated user + fn update_user(&self, username: String, body: models::User, context: &Context) -> Box + Send> { + let context = context.clone(); + println!("update_user(\"{}\", {:?}) - X-Span-ID: {:?}", username, body, context.x_span_id.unwrap_or(String::from("")).clone()); + Box::new(futures::failed("Generic failure".into())) + } + +} diff --git a/samples/client/petstore/rust2/src/client.rs b/samples/client/petstore/rust2/src/client.rs new file mode 100644 index 000000000000..b5a5e27bf6ba --- /dev/null +++ b/samples/client/petstore/rust2/src/client.rs @@ -0,0 +1,1970 @@ +#![allow(unused_extern_crates)] +extern crate hyper_openssl; +extern crate chrono; +extern crate multipart; + +use multipart::client::lazy::Multipart; +use hyper; +use hyper::client::IntoUrl; +use hyper::mime; +use hyper::header::{Headers, ContentType}; +use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value}; +use hyper::Url; +use self::hyper_openssl::openssl; +use futures; +use futures::{Future, Stream}; +use futures::{future, stream}; +use std::borrow::Cow; +use std::io::{Read, Error}; +use std::error; +use std::fmt; +use std::path::Path; +use std::sync::Arc; +use std::str; + +use mimetypes; + +use serde_json; +use serde_xml_rs; + +#[allow(unused_imports)] +use std::collections::{HashMap, BTreeMap}; +#[allow(unused_imports)] +use swagger; + +use swagger::{Context, ApiError, XSpanId}; + +use {Api, + TestSpecialTagsResponse, + GetXmlFeaturesResponse, + PostXmlFeaturesResponse, + FakeOuterBooleanSerializeResponse, + FakeOuterCompositeSerializeResponse, + FakeOuterNumberSerializeResponse, + FakeOuterStringSerializeResponse, + TestClientModelResponse, + TestEndpointParametersResponse, + TestEnumParametersResponse, + TestJsonFormDataResponse, + TestClassnameResponse, + AddPetResponse, + DeletePetResponse, + FindPetsByStatusResponse, + FindPetsByTagsResponse, + GetPetByIdResponse, + UpdatePetResponse, + UpdatePetWithFormResponse, + UploadFileResponse, + DeleteOrderResponse, + GetInventoryResponse, + GetOrderByIdResponse, + PlaceOrderResponse, + CreateUserResponse, + CreateUsersWithArrayInputResponse, + CreateUsersWithListInputResponse, + DeleteUserResponse, + GetUserByNameResponse, + LoginUserResponse, + LogoutUserResponse, + UpdateUserResponse + }; +use models; + +/// Convert input into a base path, e.g. "http://example:123". Also checks the scheme as it goes. +fn into_base_path(input: T, correct_scheme: Option<&'static str>) -> Result { + // First convert to Url, since a base path is a subset of Url. + let url = input.into_url()?; + + let scheme = url.scheme(); + + // Check the scheme if necessary + if let Some(correct_scheme) = correct_scheme { + if scheme != correct_scheme { + return Err(ClientInitError::InvalidScheme); + } + } + + let host = url.host().ok_or_else(|| ClientInitError::MissingHost)?; + let port = url.port().map(|x| format!(":{}", x)).unwrap_or_default(); + Ok(format!("{}://{}{}", scheme, host, port)) +} + +/// A client that implements the API by making HTTP calls out to a server. +#[derive(Clone)] +pub struct Client { + base_path: String, + hyper_client: Arc hyper::client::Client + Sync + Send>, +} + +impl fmt::Debug for Client { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Client {{ base_path: {} }}", self.base_path) + } +} + +impl Client { + pub fn try_new_http(base_path: T) -> Result + where T: IntoUrl + { + Ok(Client { + base_path: into_base_path(base_path, Some("http"))?, + hyper_client: Arc::new(hyper::client::Client::new), + }) + } + + pub fn try_new_https(base_path: T, + ca_certificate: CA) + -> Result + where T: IntoUrl, + CA: AsRef + { + let ca_certificate = ca_certificate.as_ref().to_owned(); + + let https_hyper_client = move || { + // SSL implementation + let mut ssl = openssl::ssl::SslConnectorBuilder::new(openssl::ssl::SslMethod::tls()).unwrap(); + + // Server authentication + ssl.builder_mut().set_ca_file(ca_certificate.clone()).unwrap(); + + let ssl = hyper_openssl::OpensslClient::from(ssl.build()); + let connector = hyper::net::HttpsConnector::new(ssl); + hyper::client::Client::with_connector(connector) + }; + + Ok(Client { + base_path: into_base_path(base_path, Some("https"))?, + hyper_client: Arc::new(https_hyper_client), + }) + } + + pub fn try_new_https_mutual(base_path: T, + ca_certificate: CA, + client_key: K, + client_certificate: C) + -> Result + where T: IntoUrl, + CA: AsRef, + K: AsRef, + C: AsRef + { + let ca_certificate = ca_certificate.as_ref().to_owned(); + let client_key = client_key.as_ref().to_owned(); + let client_certificate = client_certificate.as_ref().to_owned(); + + let https_mutual_hyper_client = move || { + // SSL implementation + let mut ssl = openssl::ssl::SslConnectorBuilder::new(openssl::ssl::SslMethod::tls()).unwrap(); + + // Server authentication + ssl.builder_mut().set_ca_file(ca_certificate.clone()).unwrap(); + + // Client authentication + ssl.builder_mut().set_private_key_file(client_key.clone(), openssl::x509::X509_FILETYPE_PEM).unwrap(); + ssl.builder_mut().set_certificate_chain_file(client_certificate.clone()).unwrap(); + ssl.builder_mut().check_private_key().unwrap(); + + let ssl = hyper_openssl::OpensslClient::from(ssl.build()); + let connector = hyper::net::HttpsConnector::new(ssl); + hyper::client::Client::with_connector(connector) + }; + + Ok(Client { + base_path: into_base_path(base_path, Some("https"))?, + hyper_client: Arc::new(https_mutual_hyper_client) + }) + } + + /// Constructor for creating a `Client` by passing in a pre-made `hyper` client. + /// + /// One should avoid relying on this function if possible, since it adds a dependency on the underlying transport + /// implementation, which it would be better to abstract away. Therefore, using this function may lead to a loss of + /// code generality, which may make it harder to move the application to a serverless environment, for example. + /// + /// The reason for this function's existence is to support legacy test code, which did mocking at the hyper layer. + /// This is not a recommended way to write new tests. If other reasons are found for using this function, they + /// should be mentioned here. + pub fn try_new_with_hyper_client(base_path: T, + hyper_client: Arc hyper::client::Client + Sync + Send>) + -> Result + where T: IntoUrl + { + Ok(Client { + base_path: into_base_path(base_path, None)?, + hyper_client: hyper_client + }) + } +} + +impl Api for Client { + + fn test_special_tags(&self, param_body: models::Client, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/another-fake/dummy?", self.base_path); + + + let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Patch, &url); + let mut custom_headers = hyper::header::Headers::new(); + + let request = request.body(&body); + + custom_headers.set(ContentType(mimetypes::requests::TEST_SPECIAL_TAGS.clone())); + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 200 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + + + Ok(TestSpecialTagsResponse::SuccessfulOperation(body)) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn get_xml_features(&self, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/fake/xmlFeatures?", self.base_path); + + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Get, &url); + let mut custom_headers = hyper::header::Headers::new(); + + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 200 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).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::(&buf) + .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e)))?; + + + Ok(GetXmlFeaturesResponse::Success(body)) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn post_xml_features(&self, param_xml_object: models::XmlObject, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/fake/xmlFeatures?", self.base_path); + + + + let mut namespaces = BTreeMap::new(); + // An empty string is used to indicate a global namespace in xmltree. + namespaces.insert("".to_string(), models::namespaces::XMLOBJECT.clone()); + let body = serde_xml_rs::to_string_with_namespaces(¶m_xml_object, namespaces).expect("impossible to fail to serialize"); + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Post, &url); + let mut custom_headers = hyper::header::Headers::new(); + + let request = request.body(&body); + + custom_headers.set(ContentType(mimetypes::requests::POST_XML_FEATURES.clone())); + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 200 => { + + + Ok(PostXmlFeaturesResponse::Success) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn fake_outer_boolean_serialize(&self, param_body: Option, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/fake/outer/boolean?", self.base_path); + + let body = param_body.map(|ref body| { + + serde_json::to_string(body).expect("impossible to fail to serialize") + }); + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Post, &url); + let mut custom_headers = hyper::header::Headers::new(); + + let request = match body { + Some(ref body) => request.body(body), + None => request, + }; + + custom_headers.set(ContentType(mimetypes::requests::FAKE_OUTER_BOOLEAN_SERIALIZE.clone())); + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 200 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + + + Ok(FakeOuterBooleanSerializeResponse::OutputBoolean(body)) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn fake_outer_composite_serialize(&self, param_body: Option, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/fake/outer/composite?", self.base_path); + + let body = param_body.map(|ref body| { + + serde_json::to_string(body).expect("impossible to fail to serialize") + }); + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Post, &url); + let mut custom_headers = hyper::header::Headers::new(); + + let request = match body { + Some(ref body) => request.body(body), + None => request, + }; + + custom_headers.set(ContentType(mimetypes::requests::FAKE_OUTER_COMPOSITE_SERIALIZE.clone())); + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 200 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + + + Ok(FakeOuterCompositeSerializeResponse::OutputComposite(body)) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn fake_outer_number_serialize(&self, param_body: Option, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/fake/outer/number?", self.base_path); + + let body = param_body.map(|ref body| { + + serde_json::to_string(body).expect("impossible to fail to serialize") + }); + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Post, &url); + let mut custom_headers = hyper::header::Headers::new(); + + let request = match body { + Some(ref body) => request.body(body), + None => request, + }; + + custom_headers.set(ContentType(mimetypes::requests::FAKE_OUTER_NUMBER_SERIALIZE.clone())); + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 200 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + + + Ok(FakeOuterNumberSerializeResponse::OutputNumber(body)) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn fake_outer_string_serialize(&self, param_body: Option, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/fake/outer/string?", self.base_path); + + let body = param_body.map(|ref body| { + + serde_json::to_string(body).expect("impossible to fail to serialize") + }); + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Post, &url); + let mut custom_headers = hyper::header::Headers::new(); + + let request = match body { + Some(ref body) => request.body(body), + None => request, + }; + + custom_headers.set(ContentType(mimetypes::requests::FAKE_OUTER_STRING_SERIALIZE.clone())); + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 200 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + + + Ok(FakeOuterStringSerializeResponse::OutputString(body)) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn test_client_model(&self, param_body: models::Client, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/fake?", self.base_path); + + + let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Patch, &url); + let mut custom_headers = hyper::header::Headers::new(); + + let request = request.body(&body); + + custom_headers.set(ContentType(mimetypes::requests::TEST_CLIENT_MODEL.clone())); + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 200 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + + + Ok(TestClientModelResponse::SuccessfulOperation(body)) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn test_endpoint_parameters(&self, param_number: f64, param_double: f64, param_pattern_without_delimiter: String, param_byte: swagger::ByteArray, param_integer: Option, param_int32: Option, param_int64: Option, param_float: Option, param_string: Option, param_binary: Option, param_date: Option>, param_date_time: Option>, param_password: Option, param_callback: Option, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/fake?", self.base_path); + + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Post, &url); + let mut custom_headers = hyper::header::Headers::new(); + + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 400 => { + + + Ok(TestEndpointParametersResponse::InvalidUsernameSupplied) + }, + 404 => { + + + Ok(TestEndpointParametersResponse::UserNotFound) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn test_enum_parameters(&self, param_enum_form_string_array: Option<&Vec>, param_enum_form_string: Option, param_enum_header_string_array: Option<&Vec>, param_enum_header_string: Option, param_enum_query_string_array: Option<&Vec>, param_enum_query_string: Option, param_enum_query_integer: Option, param_enum_query_double: Option, context: &Context) -> Box + Send> { + + // Query parameters + let query_enum_query_string_array = param_enum_query_string_array.map_or_else(String::new, |query| format!("enum_query_string_array={enum_query_string_array}&", enum_query_string_array=query.join(","))); + let query_enum_query_string = param_enum_query_string.map_or_else(String::new, |query| format!("enum_query_string={enum_query_string}&", enum_query_string=query.to_string())); + let query_enum_query_integer = param_enum_query_integer.map_or_else(String::new, |query| format!("enum_query_integer={enum_query_integer}&", enum_query_integer=query.to_string())); + + + let url = format!("{}/v2/fake?{enum_query_string_array}{enum_query_string}{enum_query_integer}", self.base_path, enum_query_string_array=query_enum_query_string_array, enum_query_string=query_enum_query_string, enum_query_integer=query_enum_query_integer); + + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Get, &url); + let mut custom_headers = hyper::header::Headers::new(); + + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + // Header parameters + header! { (RequestEnumHeaderStringArray, "enum_header_string_array") => (String)* } + param_enum_header_string_array.map(|header| custom_headers.set(RequestEnumHeaderStringArray(header.clone()))); + header! { (RequestEnumHeaderString, "enum_header_string") => [String] } + param_enum_header_string.map(|header| custom_headers.set(RequestEnumHeaderString(header))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 400 => { + + + Ok(TestEnumParametersResponse::InvalidRequest) + }, + 404 => { + + + Ok(TestEnumParametersResponse::NotFound) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn test_json_form_data(&self, param_param: String, param_param2: String, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/fake/jsonFormData?", self.base_path); + + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Get, &url); + let mut custom_headers = hyper::header::Headers::new(); + + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 200 => { + + + Ok(TestJsonFormDataResponse::SuccessfulOperation) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn test_classname(&self, param_body: models::Client, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/fake_classname_test?", self.base_path); + + + let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Patch, &url); + let mut custom_headers = hyper::header::Headers::new(); + + let request = request.body(&body); + + custom_headers.set(ContentType(mimetypes::requests::TEST_CLASSNAME.clone())); + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 200 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + + + Ok(TestClassnameResponse::SuccessfulOperation(body)) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn add_pet(&self, param_body: models::Pet, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/pet?", self.base_path); + + + let body = serde_xml_rs::to_string(¶m_body).expect("impossible to fail to serialize"); + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Post, &url); + let mut custom_headers = hyper::header::Headers::new(); + + let request = request.body(&body); + + custom_headers.set(ContentType(mimetypes::requests::ADD_PET.clone())); + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 405 => { + + + Ok(AddPetResponse::InvalidInput) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn delete_pet(&self, param_pet_id: i64, param_api_key: Option, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/pet/{petId}?", self.base_path, petId=param_pet_id.to_string()); + + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Delete, &url); + let mut custom_headers = hyper::header::Headers::new(); + + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + // Header parameters + header! { (RequestApiKey, "api_key") => [String] } + param_api_key.map(|header| custom_headers.set(RequestApiKey(header))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 400 => { + + + Ok(DeletePetResponse::InvalidPetValue) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn find_pets_by_status(&self, param_status: &Vec, context: &Context) -> Box + Send> { + + // Query parameters + let query_status = format!("status={status}&", status=param_status.join(",")); + + + let url = format!("{}/v2/pet/findByStatus?{status}", self.base_path, status=query_status); + + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Get, &url); + let mut custom_headers = hyper::header::Headers::new(); + + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 200 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).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::>(&buf) + .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e)))?; + + + Ok(FindPetsByStatusResponse::SuccessfulOperation(body)) + }, + 400 => { + + + Ok(FindPetsByStatusResponse::InvalidStatusValue) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn find_pets_by_tags(&self, param_tags: &Vec, context: &Context) -> Box + Send> { + + // Query parameters + let query_tags = format!("tags={tags}&", tags=param_tags.join(",")); + + + let url = format!("{}/v2/pet/findByTags?{tags}", self.base_path, tags=query_tags); + + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Get, &url); + let mut custom_headers = hyper::header::Headers::new(); + + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 200 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).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::>(&buf) + .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e)))?; + + + Ok(FindPetsByTagsResponse::SuccessfulOperation(body)) + }, + 400 => { + + + Ok(FindPetsByTagsResponse::InvalidTagValue) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn get_pet_by_id(&self, param_pet_id: i64, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/pet/{petId}?", self.base_path, petId=param_pet_id.to_string()); + + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Get, &url); + let mut custom_headers = hyper::header::Headers::new(); + + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 200 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).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::(&buf) + .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e)))?; + + + Ok(GetPetByIdResponse::SuccessfulOperation(body)) + }, + 400 => { + + + Ok(GetPetByIdResponse::InvalidIDSupplied) + }, + 404 => { + + + Ok(GetPetByIdResponse::PetNotFound) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn update_pet(&self, param_body: models::Pet, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/pet?", self.base_path); + + + let body = serde_xml_rs::to_string(¶m_body).expect("impossible to fail to serialize"); + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Put, &url); + let mut custom_headers = hyper::header::Headers::new(); + + let request = request.body(&body); + + custom_headers.set(ContentType(mimetypes::requests::UPDATE_PET.clone())); + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 400 => { + + + Ok(UpdatePetResponse::InvalidIDSupplied) + }, + 404 => { + + + Ok(UpdatePetResponse::PetNotFound) + }, + 405 => { + + + Ok(UpdatePetResponse::ValidationException) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn update_pet_with_form(&self, param_pet_id: i64, param_name: Option, param_status: Option, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/pet/{petId}?", self.base_path, petId=param_pet_id.to_string()); + + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Post, &url); + let mut custom_headers = hyper::header::Headers::new(); + + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 405 => { + + + Ok(UpdatePetWithFormResponse::InvalidInput) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn upload_file(&self, param_pet_id: i64, param_additional_metadata: Option, param_file: Box, Error=Error> + Send>>, Error=Error> + Send>, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/pet/{petId}/uploadImage?", self.base_path, petId=param_pet_id.to_string()); + + // Form data body + let mut multipart = Multipart::new(); + + if let Ok(Some(param_file)) = param_file.wait() { + match convert_stream_to_string(param_file) { + Ok(param_file) => { + // Add file to multipart form. + multipart.add_text("file", param_file); + }, + Err(err) => return Box::new(futures::done(Err(err))), + } + } + + let mut fields = match multipart.prepare() { + Ok(fields) => fields, + Err(err) => return Box::new(futures::done(Err(ApiError(format!("Unable to build request: {}", err))))), + }; + + let mut body_string = String::new(); + let body = fields.to_body().read_to_string(&mut body_string); + let boundary = fields.boundary(); + let multipart_header = Mime(TopLevel::Multipart, SubLevel::FormData, vec![(Attr::Boundary, Value::Ext(boundary.to_string()))]); + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Post, &url); + let mut custom_headers = hyper::header::Headers::new(); + + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + let request = request.header(ContentType(multipart_header)) + .body(&body_string); + + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 200 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::(&buf)?; + + + + Ok(UploadFileResponse::SuccessfulOperation(body)) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + // Helper function to convert a Stream into a String. The String can then be used to build the HTTP body. + fn convert_stream_to_string(stream: Box, Error=Error> + Send>) -> Result { + + stream.fold(Vec::new(), |mut body, chunk| { + body.extend(chunk.iter()); + future::ok::,Error>(body) + }).wait() + .map_err(|e| ApiError(format!("Unable to fold stream: {}", e))) + .and_then(|body| String::from_utf8(body) + .map_err(|e| ApiError(format!("Failed to convert utf8 stream to String: {}", e)))) + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn delete_order(&self, param_order_id: String, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/store/order/{order_id}?", self.base_path, order_id=param_order_id.to_string()); + + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Delete, &url); + let mut custom_headers = hyper::header::Headers::new(); + + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 400 => { + + + Ok(DeleteOrderResponse::InvalidIDSupplied) + }, + 404 => { + + + Ok(DeleteOrderResponse::OrderNotFound) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn get_inventory(&self, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/store/inventory?", self.base_path); + + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Get, &url); + let mut custom_headers = hyper::header::Headers::new(); + + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 200 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).map_err(|e| ApiError(format!("Response was not valid UTF8: {}", e)))?; + let body = serde_json::from_str::>(&buf)?; + + + + Ok(GetInventoryResponse::SuccessfulOperation(body)) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn get_order_by_id(&self, param_order_id: i64, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/store/order/{order_id}?", self.base_path, order_id=param_order_id.to_string()); + + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Get, &url); + let mut custom_headers = hyper::header::Headers::new(); + + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 200 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).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::(&buf) + .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e)))?; + + + Ok(GetOrderByIdResponse::SuccessfulOperation(body)) + }, + 400 => { + + + Ok(GetOrderByIdResponse::InvalidIDSupplied) + }, + 404 => { + + + Ok(GetOrderByIdResponse::OrderNotFound) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn place_order(&self, param_body: models::Order, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/store/order?", self.base_path); + + + let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Post, &url); + let mut custom_headers = hyper::header::Headers::new(); + + let request = request.body(&body); + + custom_headers.set(ContentType(mimetypes::requests::PLACE_ORDER.clone())); + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 200 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).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::(&buf) + .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e)))?; + + + Ok(PlaceOrderResponse::SuccessfulOperation(body)) + }, + 400 => { + + + Ok(PlaceOrderResponse::InvalidOrder) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn create_user(&self, param_body: models::User, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/user?", self.base_path); + + + let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Post, &url); + let mut custom_headers = hyper::header::Headers::new(); + + let request = request.body(&body); + + custom_headers.set(ContentType(mimetypes::requests::CREATE_USER.clone())); + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 0 => { + + + Ok(CreateUserResponse::SuccessfulOperation) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn create_users_with_array_input(&self, param_body: &Vec, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/user/createWithArray?", self.base_path); + + + let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Post, &url); + let mut custom_headers = hyper::header::Headers::new(); + + let request = request.body(&body); + + custom_headers.set(ContentType(mimetypes::requests::CREATE_USERS_WITH_ARRAY_INPUT.clone())); + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 0 => { + + + Ok(CreateUsersWithArrayInputResponse::SuccessfulOperation) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn create_users_with_list_input(&self, param_body: &Vec, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/user/createWithList?", self.base_path); + + + let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Post, &url); + let mut custom_headers = hyper::header::Headers::new(); + + let request = request.body(&body); + + custom_headers.set(ContentType(mimetypes::requests::CREATE_USERS_WITH_LIST_INPUT.clone())); + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 0 => { + + + Ok(CreateUsersWithListInputResponse::SuccessfulOperation) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn delete_user(&self, param_username: String, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/user/{username}?", self.base_path, username=param_username.to_string()); + + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Delete, &url); + let mut custom_headers = hyper::header::Headers::new(); + + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 400 => { + + + Ok(DeleteUserResponse::InvalidUsernameSupplied) + }, + 404 => { + + + Ok(DeleteUserResponse::UserNotFound) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn get_user_by_name(&self, param_username: String, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/user/{username}?", self.base_path, username=param_username.to_string()); + + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Get, &url); + let mut custom_headers = hyper::header::Headers::new(); + + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 200 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).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::(&buf) + .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e)))?; + + + Ok(GetUserByNameResponse::SuccessfulOperation(body)) + }, + 400 => { + + + Ok(GetUserByNameResponse::InvalidUsernameSupplied) + }, + 404 => { + + + Ok(GetUserByNameResponse::UserNotFound) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn login_user(&self, param_username: String, param_password: String, context: &Context) -> Box + Send> { + + // Query parameters + let query_username = format!("username={username}&", username=param_username.to_string()); + let query_password = format!("password={password}&", password=param_password.to_string()); + + + let url = format!("{}/v2/user/login?{username}{password}", self.base_path, username=query_username, password=query_password); + + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Get, &url); + let mut custom_headers = hyper::header::Headers::new(); + + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 200 => { + let mut buf = String::new(); + response.read_to_string(&mut buf).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::(&buf) + .map_err(|e| ApiError(format!("Response body did not match the schema: {}", e)))?; + + header! { (ResponseXRateLimit, "X-Rate-Limit") => [i32] } + let response_x_rate_limit = response.headers.get::().ok_or_else(|| "Required response header X-Rate-Limit for response 200 was not found.")?; + header! { (ResponseXExpiresAfter, "X-Expires-After") => [chrono::DateTime] } + let response_x_expires_after = response.headers.get::().ok_or_else(|| "Required response header X-Expires-After for response 200 was not found.")?; + + Ok(LoginUserResponse::SuccessfulOperation{ body: body, x_rate_limit: response_x_rate_limit.0.clone(), x_expires_after: response_x_expires_after.0.clone() }) + }, + 400 => { + + + Ok(LoginUserResponse::InvalidUsername) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn logout_user(&self, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/user/logout?", self.base_path); + + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Get, &url); + let mut custom_headers = hyper::header::Headers::new(); + + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 0 => { + + + Ok(LogoutUserResponse::SuccessfulOperation) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + + fn update_user(&self, param_username: String, param_body: models::User, context: &Context) -> Box + Send> { + + + let url = format!("{}/v2/user/{username}?", self.base_path, username=param_username.to_string()); + + + let body = serde_json::to_string(¶m_body).expect("impossible to fail to serialize"); + + let hyper_client = (self.hyper_client)(); + let request = hyper_client.request(hyper::method::Method::Put, &url); + let mut custom_headers = hyper::header::Headers::new(); + + let request = request.body(&body); + + custom_headers.set(ContentType(mimetypes::requests::UPDATE_USER.clone())); + context.x_span_id.as_ref().map(|header| custom_headers.set(XSpanId(header.clone()))); + + + let request = request.headers(custom_headers); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn parse_response(mut response: hyper::client::response::Response) -> Result { + match response.status.to_u16() { + 400 => { + + + Ok(UpdateUserResponse::InvalidUserSupplied) + }, + 404 => { + + + Ok(UpdateUserResponse::UserNotFound) + }, + code => { + let mut buf = [0; 100]; + let debug_body = match response.read(&mut buf) { + Ok(len) => match str::from_utf8(&buf[..len]) { + Ok(body) => Cow::from(body), + Err(_) => Cow::from(format!("", &buf[..len].to_vec())), + }, + Err(e) => Cow::from(format!("", e)), + }; + Err(ApiError(format!("Unexpected response code {}:\n{:?}\n\n{}", + code, + response.headers, + debug_body))) + } + } + } + + let result = request.send().map_err(|e| ApiError(format!("No response received: {}", e))).and_then(parse_response); + Box::new(futures::done(result)) + } + +} + +#[derive(Debug)] +pub enum ClientInitError { + InvalidScheme, + InvalidUrl(hyper::error::ParseError), + MissingHost, + SslError(openssl::error::ErrorStack) +} + +impl From for ClientInitError { + fn from(err: hyper::error::ParseError) -> ClientInitError { + ClientInitError::InvalidUrl(err) + } +} + +impl From for ClientInitError { + fn from(err: openssl::error::ErrorStack) -> ClientInitError { + ClientInitError::SslError(err) + } +} + +impl fmt::Display for ClientInitError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + (self as &fmt::Debug).fmt(f) + } +} + +impl error::Error for ClientInitError { + fn description(&self) -> &str { + "Failed to produce a hyper client." + } +} diff --git a/samples/client/petstore/rust2/src/lib.rs b/samples/client/petstore/rust2/src/lib.rs new file mode 100644 index 000000000000..a923266374c1 --- /dev/null +++ b/samples/client/petstore/rust2/src/lib.rs @@ -0,0 +1,606 @@ +#![allow(missing_docs, trivial_casts, unused_variables, unused_mut, unused_imports, unused_extern_crates, non_camel_case_types)] +extern crate serde; +#[macro_use] +extern crate serde_derive; +extern crate serde_json; +extern crate serde_xml_rs; +extern crate futures; +extern crate chrono; +extern crate multipart; +#[macro_use] +extern crate lazy_static; +#[macro_use] +extern crate log; + +// Logically this should be in the client and server modules, but rust doesn't allow `macro_use` from a module. +#[cfg(any(feature = "client", feature = "server"))] +#[macro_use] +extern crate hyper; + +extern crate swagger; + +use futures::Stream; +use std::io::Error; + +#[allow(unused_imports)] +use std::collections::HashMap; + +pub use futures::Future; + +#[cfg(any(feature = "client", feature = "server"))] +mod mimetypes; + +pub use swagger::{ApiError, Context, ContextWrapper}; + + +#[derive(Debug, PartialEq)] +pub enum TestSpecialTagsResponse { + SuccessfulOperation ( models::Client ) , +} + +#[derive(Debug, PartialEq)] +pub enum GetXmlFeaturesResponse { + Success ( models::XmlObject ) , +} + +#[derive(Debug, PartialEq)] +pub enum PostXmlFeaturesResponse { + Success , +} + +#[derive(Debug, PartialEq)] +pub enum FakeOuterBooleanSerializeResponse { + OutputBoolean ( models::OuterBoolean ) , +} + +#[derive(Debug, PartialEq)] +pub enum FakeOuterCompositeSerializeResponse { + OutputComposite ( models::OuterComposite ) , +} + +#[derive(Debug, PartialEq)] +pub enum FakeOuterNumberSerializeResponse { + OutputNumber ( models::OuterNumber ) , +} + +#[derive(Debug, PartialEq)] +pub enum FakeOuterStringSerializeResponse { + OutputString ( models::OuterString ) , +} + +#[derive(Debug, PartialEq)] +pub enum TestClientModelResponse { + SuccessfulOperation ( models::Client ) , +} + +#[derive(Debug, PartialEq)] +pub enum TestEndpointParametersResponse { + InvalidUsernameSupplied , + UserNotFound , +} + +#[derive(Debug, PartialEq)] +pub enum TestEnumParametersResponse { + InvalidRequest , + NotFound , +} + +#[derive(Debug, PartialEq)] +pub enum TestJsonFormDataResponse { + SuccessfulOperation , +} + +#[derive(Debug, PartialEq)] +pub enum TestClassnameResponse { + SuccessfulOperation ( models::Client ) , +} + +#[derive(Debug, PartialEq)] +pub enum AddPetResponse { + InvalidInput , +} + +#[derive(Debug, PartialEq)] +pub enum DeletePetResponse { + InvalidPetValue , +} + +#[derive(Debug, PartialEq)] +pub enum FindPetsByStatusResponse { + SuccessfulOperation ( Vec ) , + InvalidStatusValue , +} + +#[derive(Debug, PartialEq)] +pub enum FindPetsByTagsResponse { + SuccessfulOperation ( Vec ) , + InvalidTagValue , +} + +#[derive(Debug, PartialEq)] +pub enum GetPetByIdResponse { + SuccessfulOperation ( models::Pet ) , + InvalidIDSupplied , + PetNotFound , +} + +#[derive(Debug, PartialEq)] +pub enum UpdatePetResponse { + InvalidIDSupplied , + PetNotFound , + ValidationException , +} + +#[derive(Debug, PartialEq)] +pub enum UpdatePetWithFormResponse { + InvalidInput , +} + +#[derive(Debug, PartialEq)] +pub enum UploadFileResponse { + SuccessfulOperation ( models::ApiResponse ) , +} + +#[derive(Debug, PartialEq)] +pub enum DeleteOrderResponse { + InvalidIDSupplied , + OrderNotFound , +} + +#[derive(Debug, PartialEq)] +pub enum GetInventoryResponse { + SuccessfulOperation ( HashMap ) , +} + +#[derive(Debug, PartialEq)] +pub enum GetOrderByIdResponse { + SuccessfulOperation ( models::Order ) , + InvalidIDSupplied , + OrderNotFound , +} + +#[derive(Debug, PartialEq)] +pub enum PlaceOrderResponse { + SuccessfulOperation ( models::Order ) , + InvalidOrder , +} + +#[derive(Debug, PartialEq)] +pub enum CreateUserResponse { + SuccessfulOperation , +} + +#[derive(Debug, PartialEq)] +pub enum CreateUsersWithArrayInputResponse { + SuccessfulOperation , +} + +#[derive(Debug, PartialEq)] +pub enum CreateUsersWithListInputResponse { + SuccessfulOperation , +} + +#[derive(Debug, PartialEq)] +pub enum DeleteUserResponse { + InvalidUsernameSupplied , + UserNotFound , +} + +#[derive(Debug, PartialEq)] +pub enum GetUserByNameResponse { + SuccessfulOperation ( models::User ) , + InvalidUsernameSupplied , + UserNotFound , +} + +#[derive(Debug, PartialEq)] +pub enum LoginUserResponse { + SuccessfulOperation { body: String, x_rate_limit: i32, x_expires_after: chrono::DateTime } , + InvalidUsername , +} + +#[derive(Debug, PartialEq)] +pub enum LogoutUserResponse { + SuccessfulOperation , +} + +#[derive(Debug, PartialEq)] +pub enum UpdateUserResponse { + InvalidUserSupplied , + UserNotFound , +} + + +/// API +pub trait Api { + + /// To test special tags + fn test_special_tags(&self, body: models::Client, context: &Context) -> Box + Send>; + + /// Get some XML + fn get_xml_features(&self, context: &Context) -> Box + Send>; + + /// Post some xml + fn post_xml_features(&self, xml_object: models::XmlObject, context: &Context) -> Box + Send>; + + + fn fake_outer_boolean_serialize(&self, body: Option, context: &Context) -> Box + Send>; + + + fn fake_outer_composite_serialize(&self, body: Option, context: &Context) -> Box + Send>; + + + fn fake_outer_number_serialize(&self, body: Option, context: &Context) -> Box + Send>; + + + fn fake_outer_string_serialize(&self, body: Option, context: &Context) -> Box + Send>; + + /// To test \"client\" model + fn test_client_model(&self, body: models::Client, context: &Context) -> Box + Send>; + + /// Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트 + fn test_endpoint_parameters(&self, number: f64, double: f64, pattern_without_delimiter: String, byte: swagger::ByteArray, integer: Option, int32: Option, int64: Option, float: Option, string: Option, binary: Option, date: Option>, date_time: Option>, password: Option, callback: Option, context: &Context) -> Box + Send>; + + /// To test enum parameters + fn test_enum_parameters(&self, enum_form_string_array: Option<&Vec>, enum_form_string: Option, enum_header_string_array: Option<&Vec>, enum_header_string: Option, enum_query_string_array: Option<&Vec>, enum_query_string: Option, enum_query_integer: Option, enum_query_double: Option, context: &Context) -> Box + Send>; + + /// test json serialization of form data + fn test_json_form_data(&self, param: String, param2: String, context: &Context) -> Box + Send>; + + /// To test class name in snake case + fn test_classname(&self, body: models::Client, context: &Context) -> Box + Send>; + + /// Add a new pet to the store + fn add_pet(&self, body: models::Pet, context: &Context) -> Box + Send>; + + /// Deletes a pet + fn delete_pet(&self, pet_id: i64, api_key: Option, context: &Context) -> Box + Send>; + + /// Finds Pets by status + fn find_pets_by_status(&self, status: &Vec, context: &Context) -> Box + Send>; + + /// Finds Pets by tags + fn find_pets_by_tags(&self, tags: &Vec, context: &Context) -> Box + Send>; + + /// Find pet by ID + fn get_pet_by_id(&self, pet_id: i64, context: &Context) -> Box + Send>; + + /// Update an existing pet + fn update_pet(&self, body: models::Pet, context: &Context) -> Box + Send>; + + /// Updates a pet in the store with form data + fn update_pet_with_form(&self, pet_id: i64, name: Option, status: Option, context: &Context) -> Box + Send>; + + /// uploads an image + fn upload_file(&self, pet_id: i64, additional_metadata: Option, file: Box, Error=Error> + Send>>, Error=Error> + Send>, context: &Context) -> Box + Send>; + + /// Delete purchase order by ID + fn delete_order(&self, order_id: String, context: &Context) -> Box + Send>; + + /// Returns pet inventories by status + fn get_inventory(&self, context: &Context) -> Box + Send>; + + /// Find purchase order by ID + fn get_order_by_id(&self, order_id: i64, context: &Context) -> Box + Send>; + + /// Place an order for a pet + fn place_order(&self, body: models::Order, context: &Context) -> Box + Send>; + + /// Create user + fn create_user(&self, body: models::User, context: &Context) -> Box + Send>; + + /// Creates list of users with given input array + fn create_users_with_array_input(&self, body: &Vec, context: &Context) -> Box + Send>; + + /// Creates list of users with given input array + fn create_users_with_list_input(&self, body: &Vec, context: &Context) -> Box + Send>; + + /// Delete user + fn delete_user(&self, username: String, context: &Context) -> Box + Send>; + + /// Get user by user name + fn get_user_by_name(&self, username: String, context: &Context) -> Box + Send>; + + /// Logs user into the system + fn login_user(&self, username: String, password: String, context: &Context) -> Box + Send>; + + /// Logs out current logged in user session + fn logout_user(&self, context: &Context) -> Box + Send>; + + /// Updated user + fn update_user(&self, username: String, body: models::User, context: &Context) -> Box + Send>; + +} + +/// API without a `Context` +pub trait ApiNoContext { + + /// To test special tags + fn test_special_tags(&self, body: models::Client) -> Box + Send>; + + /// Get some XML + fn get_xml_features(&self) -> Box + Send>; + + /// Post some xml + fn post_xml_features(&self, xml_object: models::XmlObject) -> Box + Send>; + + + fn fake_outer_boolean_serialize(&self, body: Option) -> Box + Send>; + + + fn fake_outer_composite_serialize(&self, body: Option) -> Box + Send>; + + + fn fake_outer_number_serialize(&self, body: Option) -> Box + Send>; + + + fn fake_outer_string_serialize(&self, body: Option) -> Box + Send>; + + /// To test \"client\" model + fn test_client_model(&self, body: models::Client) -> Box + Send>; + + /// Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트 + fn test_endpoint_parameters(&self, number: f64, double: f64, pattern_without_delimiter: String, byte: swagger::ByteArray, integer: Option, int32: Option, int64: Option, float: Option, string: Option, binary: Option, date: Option>, date_time: Option>, password: Option, callback: Option) -> Box + Send>; + + /// To test enum parameters + fn test_enum_parameters(&self, enum_form_string_array: Option<&Vec>, enum_form_string: Option, enum_header_string_array: Option<&Vec>, enum_header_string: Option, enum_query_string_array: Option<&Vec>, enum_query_string: Option, enum_query_integer: Option, enum_query_double: Option) -> Box + Send>; + + /// test json serialization of form data + fn test_json_form_data(&self, param: String, param2: String) -> Box + Send>; + + /// To test class name in snake case + fn test_classname(&self, body: models::Client) -> Box + Send>; + + /// Add a new pet to the store + fn add_pet(&self, body: models::Pet) -> Box + Send>; + + /// Deletes a pet + fn delete_pet(&self, pet_id: i64, api_key: Option) -> Box + Send>; + + /// Finds Pets by status + fn find_pets_by_status(&self, status: &Vec) -> Box + Send>; + + /// Finds Pets by tags + fn find_pets_by_tags(&self, tags: &Vec) -> Box + Send>; + + /// Find pet by ID + fn get_pet_by_id(&self, pet_id: i64) -> Box + Send>; + + /// Update an existing pet + fn update_pet(&self, body: models::Pet) -> Box + Send>; + + /// Updates a pet in the store with form data + fn update_pet_with_form(&self, pet_id: i64, name: Option, status: Option) -> Box + Send>; + + /// uploads an image + fn upload_file(&self, pet_id: i64, additional_metadata: Option, file: Box, Error=Error> + Send>>, Error=Error> + Send>) -> Box + Send>; + + /// Delete purchase order by ID + fn delete_order(&self, order_id: String) -> Box + Send>; + + /// Returns pet inventories by status + fn get_inventory(&self) -> Box + Send>; + + /// Find purchase order by ID + fn get_order_by_id(&self, order_id: i64) -> Box + Send>; + + /// Place an order for a pet + fn place_order(&self, body: models::Order) -> Box + Send>; + + /// Create user + fn create_user(&self, body: models::User) -> Box + Send>; + + /// Creates list of users with given input array + fn create_users_with_array_input(&self, body: &Vec) -> Box + Send>; + + /// Creates list of users with given input array + fn create_users_with_list_input(&self, body: &Vec) -> Box + Send>; + + /// Delete user + fn delete_user(&self, username: String) -> Box + Send>; + + /// Get user by user name + fn get_user_by_name(&self, username: String) -> Box + Send>; + + /// Logs user into the system + fn login_user(&self, username: String, password: String) -> Box + Send>; + + /// Logs out current logged in user session + fn logout_user(&self) -> Box + Send>; + + /// Updated user + fn update_user(&self, username: String, body: models::User) -> Box + Send>; + +} + +/// Trait to extend an API to make it easy to bind it to a context. +pub trait ContextWrapperExt<'a> where Self: Sized { + /// Binds this API to a context. + fn with_context(self: &'a Self, context: Context) -> ContextWrapper<'a, Self>; +} + +impl<'a, T: Api + Sized> ContextWrapperExt<'a> for T { + fn with_context(self: &'a T, context: Context) -> ContextWrapper<'a, T> { + ContextWrapper::::new(self, context) + } +} + +impl<'a, T: Api> ApiNoContext for ContextWrapper<'a, T> { + + /// To test special tags + fn test_special_tags(&self, body: models::Client) -> Box + Send> { + self.api().test_special_tags(body, &self.context()) + } + + /// Get some XML + fn get_xml_features(&self) -> Box + Send> { + self.api().get_xml_features(&self.context()) + } + + /// Post some xml + fn post_xml_features(&self, xml_object: models::XmlObject) -> Box + Send> { + self.api().post_xml_features(xml_object, &self.context()) + } + + + fn fake_outer_boolean_serialize(&self, body: Option) -> Box + Send> { + self.api().fake_outer_boolean_serialize(body, &self.context()) + } + + + fn fake_outer_composite_serialize(&self, body: Option) -> Box + Send> { + self.api().fake_outer_composite_serialize(body, &self.context()) + } + + + fn fake_outer_number_serialize(&self, body: Option) -> Box + Send> { + self.api().fake_outer_number_serialize(body, &self.context()) + } + + + fn fake_outer_string_serialize(&self, body: Option) -> Box + Send> { + self.api().fake_outer_string_serialize(body, &self.context()) + } + + /// To test \"client\" model + fn test_client_model(&self, body: models::Client) -> Box + Send> { + self.api().test_client_model(body, &self.context()) + } + + /// Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트 + fn test_endpoint_parameters(&self, number: f64, double: f64, pattern_without_delimiter: String, byte: swagger::ByteArray, integer: Option, int32: Option, int64: Option, float: Option, string: Option, binary: Option, date: Option>, date_time: Option>, password: Option, callback: Option) -> Box + Send> { + self.api().test_endpoint_parameters(number, double, pattern_without_delimiter, byte, integer, int32, int64, float, string, binary, date, date_time, password, callback, &self.context()) + } + + /// To test enum parameters + fn test_enum_parameters(&self, enum_form_string_array: Option<&Vec>, enum_form_string: Option, enum_header_string_array: Option<&Vec>, enum_header_string: Option, enum_query_string_array: Option<&Vec>, enum_query_string: Option, enum_query_integer: Option, enum_query_double: Option) -> Box + Send> { + self.api().test_enum_parameters(enum_form_string_array, enum_form_string, enum_header_string_array, enum_header_string, enum_query_string_array, enum_query_string, enum_query_integer, enum_query_double, &self.context()) + } + + /// test json serialization of form data + fn test_json_form_data(&self, param: String, param2: String) -> Box + Send> { + self.api().test_json_form_data(param, param2, &self.context()) + } + + /// To test class name in snake case + fn test_classname(&self, body: models::Client) -> Box + Send> { + self.api().test_classname(body, &self.context()) + } + + /// Add a new pet to the store + fn add_pet(&self, body: models::Pet) -> Box + Send> { + self.api().add_pet(body, &self.context()) + } + + /// Deletes a pet + fn delete_pet(&self, pet_id: i64, api_key: Option) -> Box + Send> { + self.api().delete_pet(pet_id, api_key, &self.context()) + } + + /// Finds Pets by status + fn find_pets_by_status(&self, status: &Vec) -> Box + Send> { + self.api().find_pets_by_status(status, &self.context()) + } + + /// Finds Pets by tags + fn find_pets_by_tags(&self, tags: &Vec) -> Box + Send> { + self.api().find_pets_by_tags(tags, &self.context()) + } + + /// Find pet by ID + fn get_pet_by_id(&self, pet_id: i64) -> Box + Send> { + self.api().get_pet_by_id(pet_id, &self.context()) + } + + /// Update an existing pet + fn update_pet(&self, body: models::Pet) -> Box + Send> { + self.api().update_pet(body, &self.context()) + } + + /// Updates a pet in the store with form data + fn update_pet_with_form(&self, pet_id: i64, name: Option, status: Option) -> Box + Send> { + self.api().update_pet_with_form(pet_id, name, status, &self.context()) + } + + /// uploads an image + fn upload_file(&self, pet_id: i64, additional_metadata: Option, file: Box, Error=Error> + Send>>, Error=Error> + Send>) -> Box + Send> { + self.api().upload_file(pet_id, additional_metadata, file, &self.context()) + } + + /// Delete purchase order by ID + fn delete_order(&self, order_id: String) -> Box + Send> { + self.api().delete_order(order_id, &self.context()) + } + + /// Returns pet inventories by status + fn get_inventory(&self) -> Box + Send> { + self.api().get_inventory(&self.context()) + } + + /// Find purchase order by ID + fn get_order_by_id(&self, order_id: i64) -> Box + Send> { + self.api().get_order_by_id(order_id, &self.context()) + } + + /// Place an order for a pet + fn place_order(&self, body: models::Order) -> Box + Send> { + self.api().place_order(body, &self.context()) + } + + /// Create user + fn create_user(&self, body: models::User) -> Box + Send> { + self.api().create_user(body, &self.context()) + } + + /// Creates list of users with given input array + fn create_users_with_array_input(&self, body: &Vec) -> Box + Send> { + self.api().create_users_with_array_input(body, &self.context()) + } + + /// Creates list of users with given input array + fn create_users_with_list_input(&self, body: &Vec) -> Box + Send> { + self.api().create_users_with_list_input(body, &self.context()) + } + + /// Delete user + fn delete_user(&self, username: String) -> Box + Send> { + self.api().delete_user(username, &self.context()) + } + + /// Get user by user name + fn get_user_by_name(&self, username: String) -> Box + Send> { + self.api().get_user_by_name(username, &self.context()) + } + + /// Logs user into the system + fn login_user(&self, username: String, password: String) -> Box + Send> { + self.api().login_user(username, password, &self.context()) + } + + /// Logs out current logged in user session + fn logout_user(&self) -> Box + Send> { + self.api().logout_user(&self.context()) + } + + /// Updated user + fn update_user(&self, username: String, body: models::User) -> Box + Send> { + self.api().update_user(username, body, &self.context()) + } + +} + +#[cfg(feature = "client")] +pub mod client; + +// Re-export Client as a top-level name +#[cfg(feature = "client")] +pub use self::client::Client; + +#[cfg(feature = "server")] +pub mod server; + +// Re-export router() as a top-level name +#[cfg(feature = "server")] +pub use self::server::router; + +pub mod models; diff --git a/samples/client/petstore/rust2/src/mimetypes.rs b/samples/client/petstore/rust2/src/mimetypes.rs new file mode 100644 index 000000000000..1f9be4ef9c51 --- /dev/null +++ b/samples/client/petstore/rust2/src/mimetypes.rs @@ -0,0 +1,125 @@ +/// mime types for requests and responses + +pub mod responses { + use hyper::mime::*; + + // The macro is called per-operation to beat the recursion limit + /// Create Mime objects for the response content types for TestSpecialTags + lazy_static! { + pub static ref TEST_SPECIAL_TAGS_SUCCESSFUL_OPERATION: Mime = mime!(Application/Json); + } + /// Create Mime objects for the response content types for GetXmlFeatures + lazy_static! { + pub static ref GET_XML_FEATURES_SUCCESS: Mime = mime!(Application/Xml); + } + /// Create Mime objects for the response content types for TestClientModel + lazy_static! { + pub static ref TEST_CLIENT_MODEL_SUCCESSFUL_OPERATION: Mime = mime!(Application/Json); + } + /// Create Mime objects for the response content types for TestClassname + lazy_static! { + pub static ref TEST_CLASSNAME_SUCCESSFUL_OPERATION: Mime = mime!(Application/Json); + } + /// Create Mime objects for the response content types for FindPetsByStatus + lazy_static! { + pub static ref FIND_PETS_BY_STATUS_SUCCESSFUL_OPERATION: Mime = mime!(Application/Xml); + } + /// Create Mime objects for the response content types for FindPetsByTags + lazy_static! { + pub static ref FIND_PETS_BY_TAGS_SUCCESSFUL_OPERATION: Mime = mime!(Application/Xml); + } + /// Create Mime objects for the response content types for GetPetById + lazy_static! { + pub static ref GET_PET_BY_ID_SUCCESSFUL_OPERATION: Mime = mime!(Application/Xml); + } + /// Create Mime objects for the response content types for UploadFile + lazy_static! { + pub static ref UPLOAD_FILE_SUCCESSFUL_OPERATION: Mime = mime!(Application/Json); + } + /// Create Mime objects for the response content types for GetInventory + lazy_static! { + pub static ref GET_INVENTORY_SUCCESSFUL_OPERATION: Mime = mime!(Application/Json); + } + /// Create Mime objects for the response content types for GetOrderById + lazy_static! { + pub static ref GET_ORDER_BY_ID_SUCCESSFUL_OPERATION: Mime = mime!(Application/Xml); + } + /// Create Mime objects for the response content types for PlaceOrder + lazy_static! { + pub static ref PLACE_ORDER_SUCCESSFUL_OPERATION: Mime = mime!(Application/Xml); + } + /// Create Mime objects for the response content types for GetUserByName + lazy_static! { + pub static ref GET_USER_BY_NAME_SUCCESSFUL_OPERATION: Mime = mime!(Application/Xml); + } + /// Create Mime objects for the response content types for LoginUser + lazy_static! { + pub static ref LOGIN_USER_SUCCESSFUL_OPERATION: Mime = mime!(Application/Xml); + } + +} + +pub mod requests { + use hyper::mime::*; + /// Create Mime objects for the request content types for TestSpecialTags + lazy_static! { + pub static ref TEST_SPECIAL_TAGS: Mime = mime!(Application/Json); + } + /// Create Mime objects for the request content types for PostXmlFeatures + lazy_static! { + pub static ref POST_XML_FEATURES: Mime = mime!(Application/Xml); + } + /// Create Mime objects for the request content types for FakeOuterBooleanSerialize + lazy_static! { + pub static ref FAKE_OUTER_BOOLEAN_SERIALIZE: Mime = mime!(Application/Json); + } + /// Create Mime objects for the request content types for FakeOuterCompositeSerialize + lazy_static! { + pub static ref FAKE_OUTER_COMPOSITE_SERIALIZE: Mime = mime!(Application/Json); + } + /// Create Mime objects for the request content types for FakeOuterNumberSerialize + lazy_static! { + pub static ref FAKE_OUTER_NUMBER_SERIALIZE: Mime = mime!(Application/Json); + } + /// Create Mime objects for the request content types for FakeOuterStringSerialize + lazy_static! { + pub static ref FAKE_OUTER_STRING_SERIALIZE: Mime = mime!(Application/Json); + } + /// Create Mime objects for the request content types for TestClientModel + lazy_static! { + pub static ref TEST_CLIENT_MODEL: Mime = mime!(Application/Json); + } + /// Create Mime objects for the request content types for TestClassname + lazy_static! { + pub static ref TEST_CLASSNAME: Mime = mime!(Application/Json); + } + /// Create Mime objects for the request content types for AddPet + lazy_static! { + pub static ref ADD_PET: Mime = mime!(Application/Json); + } + /// Create Mime objects for the request content types for UpdatePet + lazy_static! { + pub static ref UPDATE_PET: Mime = mime!(Application/Json); + } + /// Create Mime objects for the request content types for PlaceOrder + lazy_static! { + pub static ref PLACE_ORDER: Mime = mime!(Application/Json); + } + /// Create Mime objects for the request content types for CreateUser + lazy_static! { + pub static ref CREATE_USER: Mime = mime!(Application/Json); + } + /// Create Mime objects for the request content types for CreateUsersWithArrayInput + lazy_static! { + pub static ref CREATE_USERS_WITH_ARRAY_INPUT: Mime = mime!(Application/Json); + } + /// Create Mime objects for the request content types for CreateUsersWithListInput + lazy_static! { + pub static ref CREATE_USERS_WITH_LIST_INPUT: Mime = mime!(Application/Json); + } + /// Create Mime objects for the request content types for UpdateUser + lazy_static! { + pub static ref UPDATE_USER: Mime = mime!(Application/Json); + } + +} diff --git a/samples/client/petstore/rust2/src/models.rs b/samples/client/petstore/rust2/src/models.rs new file mode 100644 index 000000000000..8b5a3251c8ba --- /dev/null +++ b/samples/client/petstore/rust2/src/models.rs @@ -0,0 +1,1136 @@ +#![allow(unused_imports, unused_qualifications, unused_extern_crates)] +extern crate chrono; +extern crate uuid; + +use serde_xml_rs; +use serde::ser::Serializer; + +use std::collections::HashMap; +use models; +use swagger; + + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct AdditionalPropertiesClass { + #[serde(rename = "map_property")] + #[serde(skip_serializing_if="Option::is_none")] + pub map_property: Option>, + + #[serde(rename = "map_of_map_property")] + #[serde(skip_serializing_if="Option::is_none")] + pub map_of_map_property: Option>>, + +} + +impl AdditionalPropertiesClass { + pub fn new() -> AdditionalPropertiesClass { + AdditionalPropertiesClass { + map_property: None, + map_of_map_property: None, + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct Animal { + #[serde(rename = "className")] + pub class_name: String, + + #[serde(rename = "color")] + #[serde(skip_serializing_if="Option::is_none")] + pub color: Option, + +} + +impl Animal { + pub fn new(class_name: String, ) -> Animal { + Animal { + class_name: class_name, + color: Some("red".to_string()), + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct AnimalFarm(Vec); + +impl ::std::convert::From> for AnimalFarm { + fn from(x: Vec) -> Self { + AnimalFarm(x) + } +} + +impl ::std::convert::From for Vec { + fn from(x: AnimalFarm) -> Self { + x.0 + } +} + +impl ::std::iter::FromIterator for AnimalFarm { + fn from_iter>(u: U) -> Self { + AnimalFarm(Vec::::from_iter(u)) + } +} + +impl ::std::iter::IntoIterator for AnimalFarm { + type Item = Animal; + type IntoIter = ::std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +impl<'a> ::std::iter::IntoIterator for &'a AnimalFarm { + type Item = &'a Animal; + type IntoIter = ::std::slice::Iter<'a, Animal>; + + fn into_iter(self) -> Self::IntoIter { + (&self.0).into_iter() + } +} + +impl<'a> ::std::iter::IntoIterator for &'a mut AnimalFarm { + type Item = &'a mut Animal; + type IntoIter = ::std::slice::IterMut<'a, Animal>; + + fn into_iter(self) -> Self::IntoIter { + (&mut self.0).into_iter() + } +} + +impl ::std::ops::Deref for AnimalFarm { + type Target = Vec; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl ::std::ops::DerefMut for AnimalFarm { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct ApiResponse { + #[serde(rename = "code")] + #[serde(skip_serializing_if="Option::is_none")] + pub code: Option, + + #[serde(rename = "type")] + #[serde(skip_serializing_if="Option::is_none")] + pub _type: Option, + + #[serde(rename = "message")] + #[serde(skip_serializing_if="Option::is_none")] + pub message: Option, + +} + +impl ApiResponse { + pub fn new() -> ApiResponse { + ApiResponse { + code: None, + _type: None, + message: None, + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct ArrayOfArrayOfNumberOnly { + #[serde(rename = "ArrayArrayNumber")] + #[serde(skip_serializing_if="Option::is_none")] + pub array_array_number: Option>>, + +} + +impl ArrayOfArrayOfNumberOnly { + pub fn new() -> ArrayOfArrayOfNumberOnly { + ArrayOfArrayOfNumberOnly { + array_array_number: None, + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct ArrayOfNumberOnly { + #[serde(rename = "ArrayNumber")] + #[serde(skip_serializing_if="Option::is_none")] + pub array_number: Option>, + +} + +impl ArrayOfNumberOnly { + pub fn new() -> ArrayOfNumberOnly { + ArrayOfNumberOnly { + array_number: None, + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct ArrayTest { + #[serde(rename = "array_of_string")] + #[serde(skip_serializing_if="Option::is_none")] + pub array_of_string: Option>, + + #[serde(rename = "array_array_of_integer")] + #[serde(skip_serializing_if="Option::is_none")] + pub array_array_of_integer: Option>>, + + #[serde(rename = "array_array_of_model")] + #[serde(skip_serializing_if="Option::is_none")] + pub array_array_of_model: Option>>, + +} + +impl ArrayTest { + pub fn new() -> ArrayTest { + ArrayTest { + array_of_string: None, + array_array_of_integer: None, + array_array_of_model: None, + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct Capitalization { + #[serde(rename = "smallCamel")] + #[serde(skip_serializing_if="Option::is_none")] + pub small_camel: Option, + + #[serde(rename = "CapitalCamel")] + #[serde(skip_serializing_if="Option::is_none")] + pub capital_camel: Option, + + #[serde(rename = "small_Snake")] + #[serde(skip_serializing_if="Option::is_none")] + pub small_snake: Option, + + #[serde(rename = "Capital_Snake")] + #[serde(skip_serializing_if="Option::is_none")] + pub capital_snake: Option, + + #[serde(rename = "SCA_ETH_Flow_Points")] + #[serde(skip_serializing_if="Option::is_none")] + pub sca_eth_flow_points: Option, + + /// Name of the pet + #[serde(rename = "ATT_NAME")] + #[serde(skip_serializing_if="Option::is_none")] + pub att_name: Option, + +} + +impl Capitalization { + pub fn new() -> Capitalization { + Capitalization { + small_camel: None, + capital_camel: None, + small_snake: None, + capital_snake: None, + sca_eth_flow_points: None, + att_name: None, + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename = "Category")] +pub struct Category { + #[serde(rename = "id")] + #[serde(skip_serializing_if="Option::is_none")] + pub id: Option, + + #[serde(rename = "name")] + #[serde(skip_serializing_if="Option::is_none")] + pub name: Option, + +} + +impl Category { + pub fn new() -> Category { + Category { + id: None, + name: None, + } + } +} + +/// Model for testing model with \"_class\" property +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct ClassModel { + #[serde(rename = "_class")] + #[serde(skip_serializing_if="Option::is_none")] + pub _class: Option, + +} + +impl ClassModel { + pub fn new() -> ClassModel { + ClassModel { + _class: None, + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct Client { + #[serde(rename = "client")] + #[serde(skip_serializing_if="Option::is_none")] + pub client: Option, + +} + +impl Client { + pub fn new() -> Client { + Client { + client: None, + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct EnumArrays { + // Note: inline enums are not fully supported by swagger-codegen + #[serde(rename = "just_symbol")] + #[serde(skip_serializing_if="Option::is_none")] + pub just_symbol: Option, + + // Note: inline enums are not fully supported by swagger-codegen + #[serde(rename = "array_enum")] + #[serde(skip_serializing_if="Option::is_none")] + pub array_enum: Option>, + +} + +impl EnumArrays { + pub fn new() -> EnumArrays { + EnumArrays { + just_symbol: None, + array_enum: None, + } + } +} + +/// Enumeration of values. +/// Since this enum's variants do not hold data, we can easily define them them as `#[repr(C)]` +/// which helps with FFI. +#[allow(non_camel_case_types)] +#[repr(C)] +#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize)] +pub enum EnumClass { + #[serde(rename = "_abc")] + _ABC, + #[serde(rename = "-efg")] + _EFG, + #[serde(rename = "(xyz)")] + _XYZ_, +} + +impl ::std::fmt::Display for EnumClass { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match *self { + EnumClass::_ABC => write!(f, "{}", "_abc"), + EnumClass::_EFG => write!(f, "{}", "-efg"), + EnumClass::_XYZ_ => write!(f, "{}", "(xyz)"), + } + } +} + +impl ::std::str::FromStr for EnumClass { + type Err = (); + fn from_str(s: &str) -> Result { + match s { + "_abc" => Ok(EnumClass::_ABC), + "-efg" => Ok(EnumClass::_EFG), + "(xyz)" => Ok(EnumClass::_XYZ_), + _ => Err(()), + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct EnumTest { + // Note: inline enums are not fully supported by swagger-codegen + #[serde(rename = "enum_string")] + #[serde(skip_serializing_if="Option::is_none")] + pub enum_string: Option, + + // Note: inline enums are not fully supported by swagger-codegen + #[serde(rename = "enum_integer")] + #[serde(skip_serializing_if="Option::is_none")] + pub enum_integer: Option, + + // Note: inline enums are not fully supported by swagger-codegen + #[serde(rename = "enum_number")] + #[serde(skip_serializing_if="Option::is_none")] + pub enum_number: Option, + + #[serde(rename = "outerEnum")] + #[serde(skip_serializing_if="Option::is_none")] + pub outer_enum: Option, + +} + +impl EnumTest { + pub fn new() -> EnumTest { + EnumTest { + enum_string: None, + enum_integer: None, + enum_number: None, + outer_enum: None, + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct FormatTest { + #[serde(rename = "integer")] + #[serde(skip_serializing_if="Option::is_none")] + pub integer: Option, + + #[serde(rename = "int32")] + #[serde(skip_serializing_if="Option::is_none")] + pub int32: Option, + + #[serde(rename = "int64")] + #[serde(skip_serializing_if="Option::is_none")] + pub int64: Option, + + #[serde(rename = "number")] + pub number: f64, + + #[serde(rename = "float")] + #[serde(skip_serializing_if="Option::is_none")] + pub float: Option, + + #[serde(rename = "double")] + #[serde(skip_serializing_if="Option::is_none")] + pub double: Option, + + #[serde(rename = "string")] + #[serde(skip_serializing_if="Option::is_none")] + pub string: Option, + + #[serde(rename = "byte")] + pub byte: swagger::ByteArray, + + #[serde(rename = "binary")] + #[serde(skip_serializing_if="Option::is_none")] + pub binary: Option, + + #[serde(rename = "date")] + pub date: chrono::DateTime, + + #[serde(rename = "dateTime")] + #[serde(skip_serializing_if="Option::is_none")] + pub date_time: Option>, + + #[serde(rename = "uuid")] + #[serde(skip_serializing_if="Option::is_none")] + pub uuid: Option, + + #[serde(rename = "password")] + pub password: String, + +} + +impl FormatTest { + pub fn new(number: f64, byte: swagger::ByteArray, date: chrono::DateTime, password: String, ) -> FormatTest { + FormatTest { + integer: None, + int32: None, + int64: None, + number: number, + float: None, + double: None, + string: None, + byte: byte, + binary: None, + date: date, + date_time: None, + uuid: None, + password: password, + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct HasOnlyReadOnly { + #[serde(rename = "bar")] + #[serde(skip_serializing_if="Option::is_none")] + pub bar: Option, + + #[serde(rename = "foo")] + #[serde(skip_serializing_if="Option::is_none")] + pub foo: Option, + +} + +impl HasOnlyReadOnly { + pub fn new() -> HasOnlyReadOnly { + HasOnlyReadOnly { + bar: None, + foo: None, + } + } +} + +// Utility function for wrapping list elements when serializing xml +fn wrap_in_item(item: &Vec, serializer: S) -> Result +where + S: Serializer, +{ + serde_xml_rs::wrap_primitives(item, serializer, "item") +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct ItemList(Vec); + +impl ::std::convert::From> for ItemList { + fn from(x: Vec) -> Self { + ItemList(x) + } +} + +impl ::std::convert::From for Vec { + fn from(x: ItemList) -> Self { + x.0 + } +} + +impl ::std::iter::FromIterator for ItemList { + fn from_iter>(u: U) -> Self { + ItemList(Vec::::from_iter(u)) + } +} + +impl ::std::iter::IntoIterator for ItemList { + type Item = String; + type IntoIter = ::std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +impl<'a> ::std::iter::IntoIterator for &'a ItemList { + type Item = &'a String; + type IntoIter = ::std::slice::Iter<'a, String>; + + fn into_iter(self) -> Self::IntoIter { + (&self.0).into_iter() + } +} + +impl<'a> ::std::iter::IntoIterator for &'a mut ItemList { + type Item = &'a mut String; + type IntoIter = ::std::slice::IterMut<'a, String>; + + fn into_iter(self) -> Self::IntoIter { + (&mut self.0).into_iter() + } +} + +impl ::std::ops::Deref for ItemList { + type Target = Vec; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl ::std::ops::DerefMut for ItemList { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct List { + #[serde(rename = "123-list")] + #[serde(skip_serializing_if="Option::is_none")] + pub _123_list: Option, + +} + +impl List { + pub fn new() -> List { + List { + _123_list: None, + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct MapTest { + #[serde(rename = "map_map_of_string")] + #[serde(skip_serializing_if="Option::is_none")] + pub map_map_of_string: Option>>, + + // Note: inline enums are not fully supported by swagger-codegen + #[serde(rename = "map_of_enum_string")] + #[serde(skip_serializing_if="Option::is_none")] + pub map_of_enum_string: Option>, + +} + +impl MapTest { + pub fn new() -> MapTest { + MapTest { + map_map_of_string: None, + map_of_enum_string: None, + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct MixedPropertiesAndAdditionalPropertiesClass { + #[serde(rename = "uuid")] + #[serde(skip_serializing_if="Option::is_none")] + pub uuid: Option, + + #[serde(rename = "dateTime")] + #[serde(skip_serializing_if="Option::is_none")] + pub date_time: Option>, + + #[serde(rename = "map")] + #[serde(skip_serializing_if="Option::is_none")] + pub map: Option>, + +} + +impl MixedPropertiesAndAdditionalPropertiesClass { + pub fn new() -> MixedPropertiesAndAdditionalPropertiesClass { + MixedPropertiesAndAdditionalPropertiesClass { + uuid: None, + date_time: None, + map: None, + } + } +} + +/// Model for testing model name starting with number +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename = "Name")] +pub struct Model200Response { + #[serde(rename = "name")] + #[serde(skip_serializing_if="Option::is_none")] + pub name: Option, + + #[serde(rename = "class")] + #[serde(skip_serializing_if="Option::is_none")] + pub class: Option, + +} + +impl Model200Response { + pub fn new() -> Model200Response { + Model200Response { + name: None, + class: None, + } + } +} + +/// Model for testing reserved words +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename = "Return")] +pub struct ModelReturn { + #[serde(rename = "return")] + #[serde(skip_serializing_if="Option::is_none")] + pub _return: Option, + +} + +impl ModelReturn { + pub fn new() -> ModelReturn { + ModelReturn { + _return: None, + } + } +} + +/// Model for testing model name same as property name +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename = "Name")] +pub struct Name { + #[serde(rename = "name")] + pub name: i32, + + #[serde(rename = "snake_case")] + #[serde(skip_serializing_if="Option::is_none")] + pub snake_case: Option, + + #[serde(rename = "property")] + #[serde(skip_serializing_if="Option::is_none")] + pub property: Option, + + #[serde(rename = "123Number")] + #[serde(skip_serializing_if="Option::is_none")] + pub _123_number: Option, + +} + +impl Name { + pub fn new(name: i32, ) -> Name { + Name { + name: name, + snake_case: None, + property: None, + _123_number: None, + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct NumberOnly { + #[serde(rename = "JustNumber")] + #[serde(skip_serializing_if="Option::is_none")] + pub just_number: Option, + +} + +impl NumberOnly { + pub fn new() -> NumberOnly { + NumberOnly { + just_number: None, + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename = "Order")] +pub struct Order { + #[serde(rename = "id")] + #[serde(skip_serializing_if="Option::is_none")] + pub id: Option, + + #[serde(rename = "petId")] + #[serde(skip_serializing_if="Option::is_none")] + pub pet_id: Option, + + #[serde(rename = "quantity")] + #[serde(skip_serializing_if="Option::is_none")] + pub quantity: Option, + + #[serde(rename = "shipDate")] + #[serde(skip_serializing_if="Option::is_none")] + pub ship_date: Option>, + + /// Order Status + // Note: inline enums are not fully supported by swagger-codegen + #[serde(rename = "status")] + #[serde(skip_serializing_if="Option::is_none")] + pub status: Option, + + #[serde(rename = "complete")] + #[serde(skip_serializing_if="Option::is_none")] + pub complete: Option, + +} + +impl Order { + pub fn new() -> Order { + Order { + id: None, + pet_id: None, + quantity: None, + ship_date: None, + status: None, + complete: Some(false), + } + } +} + +#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)] + +pub struct OuterBoolean(bool); + +impl ::std::convert::From for OuterBoolean { + fn from(x: bool) -> Self { + OuterBoolean(x) + } +} + +impl ::std::convert::From for bool { + fn from(x: OuterBoolean) -> Self { + x.0 + } +} + +impl ::std::ops::Deref for OuterBoolean { + type Target = bool; + fn deref(&self) -> &bool { + &self.0 + } +} + +impl ::std::ops::DerefMut for OuterBoolean { + fn deref_mut(&mut self) -> &mut bool { + &mut self.0 + } +} + + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct OuterComposite { + #[serde(rename = "my_number")] + #[serde(skip_serializing_if="Option::is_none")] + pub my_number: Option, + + #[serde(rename = "my_string")] + #[serde(skip_serializing_if="Option::is_none")] + pub my_string: Option, + + #[serde(rename = "my_boolean")] + #[serde(skip_serializing_if="Option::is_none")] + pub my_boolean: Option, + +} + +impl OuterComposite { + pub fn new() -> OuterComposite { + OuterComposite { + my_number: None, + my_string: None, + my_boolean: None, + } + } +} + +/// Enumeration of values. +/// Since this enum's variants do not hold data, we can easily define them them as `#[repr(C)]` +/// which helps with FFI. +#[allow(non_camel_case_types)] +#[repr(C)] +#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize)] +pub enum OuterEnum { + #[serde(rename = "placed")] + PLACED, + #[serde(rename = "approved")] + APPROVED, + #[serde(rename = "delivered")] + DELIVERED, +} + +impl ::std::fmt::Display for OuterEnum { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match *self { + OuterEnum::PLACED => write!(f, "{}", "placed"), + OuterEnum::APPROVED => write!(f, "{}", "approved"), + OuterEnum::DELIVERED => write!(f, "{}", "delivered"), + } + } +} + +impl ::std::str::FromStr for OuterEnum { + type Err = (); + fn from_str(s: &str) -> Result { + match s { + "placed" => Ok(OuterEnum::PLACED), + "approved" => Ok(OuterEnum::APPROVED), + "delivered" => Ok(OuterEnum::DELIVERED), + _ => Err(()), + } + } +} + +#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)] + +pub struct OuterNumber(f64); + +impl ::std::convert::From for OuterNumber { + fn from(x: f64) -> Self { + OuterNumber(x) + } +} + +impl ::std::convert::From for f64 { + fn from(x: OuterNumber) -> Self { + x.0 + } +} + +impl ::std::ops::Deref for OuterNumber { + type Target = f64; + fn deref(&self) -> &f64 { + &self.0 + } +} + +impl ::std::ops::DerefMut for OuterNumber { + fn deref_mut(&mut self) -> &mut f64 { + &mut self.0 + } +} + + +#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)] + +pub struct OuterString(String); + +impl ::std::convert::From for OuterString { + fn from(x: String) -> Self { + OuterString(x) + } +} + +impl ::std::convert::From for String { + fn from(x: OuterString) -> Self { + x.0 + } +} + +impl ::std::ops::Deref for OuterString { + type Target = String; + fn deref(&self) -> &String { + &self.0 + } +} + +impl ::std::ops::DerefMut for OuterString { + fn deref_mut(&mut self) -> &mut String { + &mut self.0 + } +} + + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename = "Pet")] +pub struct Pet { + #[serde(rename = "id")] + #[serde(skip_serializing_if="Option::is_none")] + pub id: Option, + + #[serde(rename = "category")] + #[serde(skip_serializing_if="Option::is_none")] + pub category: Option, + + #[serde(rename = "name")] + pub name: String, + + #[serde(rename = "photoUrls")] + pub photo_urls: Vec, + + #[serde(rename = "tags")] + #[serde(skip_serializing_if="Option::is_none")] + pub tags: Option>, + + /// pet status in the store + // Note: inline enums are not fully supported by swagger-codegen + #[serde(rename = "status")] + #[serde(skip_serializing_if="Option::is_none")] + pub status: Option, + +} + +impl Pet { + pub fn new(name: String, photo_urls: Vec, ) -> Pet { + Pet { + id: None, + category: None, + name: name, + photo_urls: photo_urls, + tags: None, + status: None, + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct ReadOnlyFirst { + #[serde(rename = "bar")] + #[serde(skip_serializing_if="Option::is_none")] + pub bar: Option, + + #[serde(rename = "baz")] + #[serde(skip_serializing_if="Option::is_none")] + pub baz: Option, + +} + +impl ReadOnlyFirst { + pub fn new() -> ReadOnlyFirst { + ReadOnlyFirst { + bar: None, + baz: None, + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename = "$special[model.name]")] +pub struct SpecialModelName { + #[serde(rename = "$special[property.name]")] + #[serde(skip_serializing_if="Option::is_none")] + pub special_property_name: Option, + +} + +impl SpecialModelName { + pub fn new() -> SpecialModelName { + SpecialModelName { + special_property_name: None, + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename = "Tag")] +pub struct Tag { + #[serde(rename = "id")] + #[serde(skip_serializing_if="Option::is_none")] + pub id: Option, + + #[serde(rename = "name")] + #[serde(skip_serializing_if="Option::is_none")] + pub name: Option, + +} + +impl Tag { + pub fn new() -> Tag { + Tag { + id: None, + name: None, + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename = "User")] +pub struct User { + #[serde(rename = "id")] + #[serde(skip_serializing_if="Option::is_none")] + pub id: Option, + + #[serde(rename = "username")] + #[serde(skip_serializing_if="Option::is_none")] + pub username: Option, + + #[serde(rename = "firstName")] + #[serde(skip_serializing_if="Option::is_none")] + pub first_name: Option, + + #[serde(rename = "lastName")] + #[serde(skip_serializing_if="Option::is_none")] + pub last_name: Option, + + #[serde(rename = "email")] + #[serde(skip_serializing_if="Option::is_none")] + pub email: Option, + + #[serde(rename = "password")] + #[serde(skip_serializing_if="Option::is_none")] + pub password: Option, + + #[serde(rename = "phone")] + #[serde(skip_serializing_if="Option::is_none")] + pub phone: Option, + + /// User Status + #[serde(rename = "userStatus")] + #[serde(skip_serializing_if="Option::is_none")] + pub user_status: Option, + +} + +impl User { + pub fn new() -> User { + User { + id: None, + username: None, + first_name: None, + last_name: None, + email: None, + password: None, + phone: None, + user_status: None, + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename = "group")] +pub struct XmlObject { + #[serde(rename = "name")] + pub name: String, + + #[serde(rename = "itemList")] + #[serde(serialize_with = "wrap_in_item")] + pub item_list: models::ItemList, + +} + +impl XmlObject { + pub fn new(name: String, item_list: models::ItemList, ) -> XmlObject { + XmlObject { + name: name, + item_list: item_list, + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct Cat { + #[serde(rename = "className")] + pub class_name: String, + + #[serde(rename = "color")] + #[serde(skip_serializing_if="Option::is_none")] + pub color: Option, + + #[serde(rename = "declawed")] + #[serde(skip_serializing_if="Option::is_none")] + pub declawed: Option, + +} + +impl Cat { + pub fn new(class_name: String, ) -> Cat { + Cat { + class_name: class_name, + color: Some("red".to_string()), + declawed: None, + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct Dog { + #[serde(rename = "className")] + pub class_name: String, + + #[serde(rename = "color")] + #[serde(skip_serializing_if="Option::is_none")] + pub color: Option, + + #[serde(rename = "breed")] + #[serde(skip_serializing_if="Option::is_none")] + pub breed: Option, + +} + +impl Dog { + pub fn new(class_name: String, ) -> Dog { + Dog { + class_name: class_name, + color: Some("red".to_string()), + breed: None, + } + } +} + +//XML namespaces +pub mod namespaces { + lazy_static!{ + pub static ref XMLOBJECT: String = "http://example.com/schema.xsd".to_string(); + + } +} diff --git a/samples/client/petstore/rust2/src/server.rs b/samples/client/petstore/rust2/src/server.rs new file mode 100644 index 000000000000..a8d32981940a --- /dev/null +++ b/samples/client/petstore/rust2/src/server.rs @@ -0,0 +1,2518 @@ +#![allow(unused_extern_crates)] +extern crate serde_ignored; +extern crate iron; +extern crate router; +extern crate bodyparser; +extern crate urlencoded; +extern crate uuid; +extern crate chrono; +extern crate multipart; + +use futures::Future; +use futures::future; +use futures::{stream, Stream}; +use hyper; +use hyper::header::{Headers, ContentType}; +use self::iron::prelude::*; +use self::iron::{status, modifiers, BeforeMiddleware}; +use self::iron::url::percent_encoding::percent_decode; +use self::router::Router; +use self::urlencoded::UrlEncodedQuery; +use mimetypes; +use multipart::server::{Multipart, SaveResult}; + +use serde_json; +use serde_xml_rs; + +#[allow(unused_imports)] +use std::collections::{HashMap, BTreeMap}; +#[allow(unused_imports)] +use swagger; +use std::io::Error; + +#[allow(unused_imports)] +use std::collections::BTreeSet; + +use swagger::auth::{Authorization, AuthData, Scopes}; +use swagger::{ApiError, Context, XSpanId}; + +use {Api, + TestSpecialTagsResponse, + GetXmlFeaturesResponse, + PostXmlFeaturesResponse, + FakeOuterBooleanSerializeResponse, + FakeOuterCompositeSerializeResponse, + FakeOuterNumberSerializeResponse, + FakeOuterStringSerializeResponse, + TestClientModelResponse, + TestEndpointParametersResponse, + TestEnumParametersResponse, + TestJsonFormDataResponse, + TestClassnameResponse, + AddPetResponse, + DeletePetResponse, + FindPetsByStatusResponse, + FindPetsByTagsResponse, + GetPetByIdResponse, + UpdatePetResponse, + UpdatePetWithFormResponse, + UploadFileResponse, + DeleteOrderResponse, + GetInventoryResponse, + GetOrderByIdResponse, + PlaceOrderResponse, + CreateUserResponse, + CreateUsersWithArrayInputResponse, + CreateUsersWithListInputResponse, + DeleteUserResponse, + GetUserByNameResponse, + LoginUserResponse, + LogoutUserResponse, + UpdateUserResponse + }; +#[allow(unused_imports)] +use models; + +header! { (Warning, "Warning") => [String] } + +/// Create a new router for `Api` +pub fn router(api: T) -> Router where T: Api + Send + Sync + Clone + 'static { + let mut router = Router::new(); + add_routes(&mut router, api); + router +} + +/// Add routes for `Api` to a provided router. +/// +/// Note that these routes are added straight onto the router. This means that if the router +/// already has a route for an endpoint which clashes with those provided by this API, then the +/// old route will be lost. +/// +/// It is generally a bad idea to add routes in this way to an existing router, which may have +/// routes on it for other APIs. Distinct APIs should be behind distinct paths to encourage +/// separation of interfaces, which this function does not enforce. APIs should not overlap. +/// +/// Alternative approaches include: +/// +/// - generate an `iron::middleware::Handler` (usually a `router::Router` or +/// `iron::middleware::chain`) for each interface, and add those handlers inside an existing +/// router, mounted at different paths - so the interfaces are separated by path +/// - use a different instance of `iron::Iron` for each interface - so the interfaces are +/// separated by the address/port they listen on +/// +/// This function exists to allow legacy code, which doesn't separate its APIs properly, to make +/// use of this crate. +#[deprecated(note="APIs should not overlap - only for use in legacy code.")] +pub fn route(router: &mut Router, api: T) where T: Api + Send + Sync + Clone + 'static { + add_routes(router, api) +} + +/// Add routes for `Api` to a provided router +fn add_routes(router: &mut Router, api: T) where T: Api + Send + Sync + Clone + 'static { + + let api_clone = api.clone(); + router.patch( + "/v2/another-fake/dummy", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + + + + // 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. + + let param_body_raw = req.get::().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter body - not valid UTF-8: {}", e))))?; + let mut unused_elements = Vec::new(); + + let param_body = if let Some(param_body_raw) = param_body_raw { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_body_raw); + + let param_body: Option = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter body - doesn't match schema: {}", e))))?; + + param_body + } else { + None + }; + let param_body = param_body.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter body".to_string())))?; + + + match api.test_special_tags(param_body, context).wait() { + Ok(rsp) => match rsp { + TestSpecialTagsResponse::SuccessfulOperation(body) => { + + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(200), body_string)); + response.headers.set(ContentType(mimetypes::responses::TEST_SPECIAL_TAGS_SUCCESSFUL_OPERATION.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "TestSpecialTags"); + + let api_clone = api.clone(); + router.get( + "/v2/fake/xmlFeatures", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + + + + + match api.get_xml_features(context).wait() { + Ok(rsp) => match rsp { + GetXmlFeaturesResponse::Success(body) => { + + + let mut namespaces = BTreeMap::new(); + // An empty string is used to indicate a global namespace in xmltree. + namespaces.insert("".to_string(), models::namespaces::XMLOBJECT.clone()); + let body_string = serde_xml_rs::to_string_with_namespaces(&body, namespaces).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(200), body_string)); + response.headers.set(ContentType(mimetypes::responses::GET_XML_FEATURES_SUCCESS.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "GetXmlFeatures"); + + let api_clone = api.clone(); + router.post( + "/v2/fake/xmlFeatures", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + + + + // 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. + + let param_xml_object_raw = req.get::().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter xmlObject - not valid UTF-8: {}", e))))?; + let mut unused_elements = Vec::new(); + + let param_xml_object = if let Some(param_xml_object_raw) = param_xml_object_raw { + let deserializer = &mut serde_xml_rs::de::Deserializer::new_from_reader(param_xml_object_raw.as_bytes()); + + let param_xml_object: Option = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter xmlObject - doesn't match schema: {}", e))))?; + + param_xml_object + } else { + None + }; + let param_xml_object = param_xml_object.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter xmlObject".to_string())))?; + + + match api.post_xml_features(param_xml_object, context).wait() { + Ok(rsp) => match rsp { + PostXmlFeaturesResponse::Success => { + + + let mut response = Response::with((status::Status::from_u16(200))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "PostXmlFeatures"); + + let api_clone = api.clone(); + router.post( + "/v2/fake/outer/boolean", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + + + + // 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. + + let param_body_raw = req.get::().unwrap_or(None); + let mut unused_elements = Vec::new(); + + let param_body = if let Some(param_body_raw) = param_body_raw { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_body_raw); + + let param_body: Option = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).unwrap_or(None); + + param_body + } else { + None + };; + + + match api.fake_outer_boolean_serialize(param_body, context).wait() { + Ok(rsp) => match rsp { + FakeOuterBooleanSerializeResponse::OutputBoolean(body) => { + + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(200), body_string)); + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "FakeOuterBooleanSerialize"); + + let api_clone = api.clone(); + router.post( + "/v2/fake/outer/composite", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + + + + // 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. + + let param_body_raw = req.get::().unwrap_or(None); + let mut unused_elements = Vec::new(); + + let param_body = if let Some(param_body_raw) = param_body_raw { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_body_raw); + + let param_body: Option = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).unwrap_or(None); + + param_body + } else { + None + };; + + + match api.fake_outer_composite_serialize(param_body, context).wait() { + Ok(rsp) => match rsp { + FakeOuterCompositeSerializeResponse::OutputComposite(body) => { + + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(200), body_string)); + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "FakeOuterCompositeSerialize"); + + let api_clone = api.clone(); + router.post( + "/v2/fake/outer/number", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + + + + // 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. + + let param_body_raw = req.get::().unwrap_or(None); + let mut unused_elements = Vec::new(); + + let param_body = if let Some(param_body_raw) = param_body_raw { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_body_raw); + + let param_body: Option = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).unwrap_or(None); + + param_body + } else { + None + };; + + + match api.fake_outer_number_serialize(param_body, context).wait() { + Ok(rsp) => match rsp { + FakeOuterNumberSerializeResponse::OutputNumber(body) => { + + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(200), body_string)); + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "FakeOuterNumberSerialize"); + + let api_clone = api.clone(); + router.post( + "/v2/fake/outer/string", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + + + + // 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. + + let param_body_raw = req.get::().unwrap_or(None); + let mut unused_elements = Vec::new(); + + let param_body = if let Some(param_body_raw) = param_body_raw { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_body_raw); + + let param_body: Option = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).unwrap_or(None); + + param_body + } else { + None + };; + + + match api.fake_outer_string_serialize(param_body, context).wait() { + Ok(rsp) => match rsp { + FakeOuterStringSerializeResponse::OutputString(body) => { + + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(200), body_string)); + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "FakeOuterStringSerialize"); + + let api_clone = api.clone(); + router.patch( + "/v2/fake", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + + + + // 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. + + let param_body_raw = req.get::().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter body - not valid UTF-8: {}", e))))?; + let mut unused_elements = Vec::new(); + + let param_body = if let Some(param_body_raw) = param_body_raw { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_body_raw); + + let param_body: Option = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter body - doesn't match schema: {}", e))))?; + + param_body + } else { + None + }; + let param_body = param_body.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter body".to_string())))?; + + + match api.test_client_model(param_body, context).wait() { + Ok(rsp) => match rsp { + TestClientModelResponse::SuccessfulOperation(body) => { + + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(200), body_string)); + response.headers.set(ContentType(mimetypes::responses::TEST_CLIENT_MODEL_SUCCESSFUL_OPERATION.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "TestClientModel"); + + let api_clone = api.clone(); + router.post( + "/v2/fake", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + let authorization = context.authorization.as_ref().ok_or_else(|| { + Response::with(( + status::Forbidden, + "Unauthenticated".to_string() + )) + })?; + + + + + // Form parameters + let param_number = 3.4; + let param_double = 1.2; + let param_pattern_without_delimiter = "pattern_without_delimiter_example".to_string(); + let param_byte = swagger::ByteArray("byte_example".to_string().into_bytes()); + let param_integer = Some(56); + let param_int32 = Some(56); + let param_int64 = Some(789); + let param_float = Some(3.4); + let param_string = Some("string_example".to_string()); + let param_binary = Some(swagger::ByteArray(Vec::from("B"))); + let param_date = None; + let param_date_time = None; + let param_password = Some("password_example".to_string()); + let param_callback = Some("callback_example".to_string()); + + match api.test_endpoint_parameters(param_number, param_double, param_pattern_without_delimiter, param_byte, param_integer, param_int32, param_int64, param_float, param_string, param_binary, param_date, param_date_time, param_password, param_callback, context).wait() { + Ok(rsp) => match rsp { + TestEndpointParametersResponse::InvalidUsernameSupplied => { + + + let mut response = Response::with((status::Status::from_u16(400))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + TestEndpointParametersResponse::UserNotFound => { + + + let mut response = Response::with((status::Status::from_u16(404))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "TestEndpointParameters"); + + let api_clone = api.clone(); + router.get( + "/v2/fake", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + + + // Header parameters + header! { (RequestEnumHeaderStringArray, "enum_header_string_array") => (String)* } + let param_enum_header_string_array = req.headers.get::().map(|header| header.0.clone()); + header! { (RequestEnumHeaderString, "enum_header_string") => [String] } + let param_enum_header_string = req.headers.get::().map(|header| header.0.clone()); + + + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) + let query_params = req.get::().unwrap_or_default(); + let param_enum_query_string_array = query_params.get("enum_query_string_array") + .map(|list| list.iter().flat_map(|x| x.parse::()).collect::>()); + let param_enum_query_string = query_params.get("enum_query_string") + .and_then(|list| list.first()).and_then(|x| x.parse::().ok()); + let param_enum_query_integer = query_params.get("enum_query_integer") + .and_then(|list| list.first()).and_then(|x| x.parse::().ok()); + + // Form parameters + let param_enum_form_string_array = None; + let param_enum_form_string = Some("enum_form_string_example".to_string()); + let param_enum_query_double = Some(1.2); + + match api.test_enum_parameters(param_enum_form_string_array.as_ref(), param_enum_form_string, param_enum_header_string_array.as_ref(), param_enum_header_string, param_enum_query_string_array.as_ref(), param_enum_query_string, param_enum_query_integer, param_enum_query_double, context).wait() { + Ok(rsp) => match rsp { + TestEnumParametersResponse::InvalidRequest => { + + + let mut response = Response::with((status::Status::from_u16(400))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + TestEnumParametersResponse::NotFound => { + + + let mut response = Response::with((status::Status::from_u16(404))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "TestEnumParameters"); + + let api_clone = api.clone(); + router.get( + "/v2/fake/jsonFormData", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + + + + // Form parameters + let param_param = "param_example".to_string(); + let param_param2 = "param2_example".to_string(); + + match api.test_json_form_data(param_param, param_param2, context).wait() { + Ok(rsp) => match rsp { + TestJsonFormDataResponse::SuccessfulOperation => { + + + let mut response = Response::with((status::Status::from_u16(200))); + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "TestJsonFormData"); + + let api_clone = api.clone(); + router.patch( + "/v2/fake_classname_test", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + let authorization = context.authorization.as_ref().ok_or_else(|| { + Response::with(( + status::Forbidden, + "Unauthenticated".to_string() + )) + })?; + + + + + // 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. + + let param_body_raw = req.get::().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter body - not valid UTF-8: {}", e))))?; + let mut unused_elements = Vec::new(); + + let param_body = if let Some(param_body_raw) = param_body_raw { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_body_raw); + + let param_body: Option = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter body - doesn't match schema: {}", e))))?; + + param_body + } else { + None + }; + let param_body = param_body.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter body".to_string())))?; + + + match api.test_classname(param_body, context).wait() { + Ok(rsp) => match rsp { + TestClassnameResponse::SuccessfulOperation(body) => { + + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(200), body_string)); + response.headers.set(ContentType(mimetypes::responses::TEST_CLASSNAME_SUCCESSFUL_OPERATION.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "TestClassname"); + + let api_clone = api.clone(); + router.post( + "/v2/pet", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + let authorization = context.authorization.as_ref().ok_or_else(|| { + Response::with(( + status::Forbidden, + "Unauthenticated".to_string() + )) + })?; + + // Authorization + if let Scopes::Some(ref scopes) = authorization.scopes { + let required_scopes: BTreeSet = vec![ + "write:pets".to_string(), // modify pets in your account + "read:pets".to_string(), // read your pets + ].into_iter().collect(); + + if !required_scopes.is_subset(scopes) { + let missing_scopes = required_scopes.difference(scopes); + return Err(Response::with(( + status::Forbidden, + missing_scopes.fold( + "Insufficient authorization, missing scopes".to_string(), + |s, scope| format!("{} {}", s, scope) + ) + ))); + } + } + + + + // 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. + + let param_body_raw = req.get::().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter body - not valid UTF-8: {}", e))))?; + let mut unused_elements = Vec::new(); + + let param_body = if let Some(param_body_raw) = param_body_raw { + let deserializer = &mut serde_xml_rs::de::Deserializer::new_from_reader(param_body_raw.as_bytes()); + + let param_body: Option = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter body - doesn't match schema: {}", e))))?; + + param_body + } else { + None + }; + let param_body = param_body.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter body".to_string())))?; + + + match api.add_pet(param_body, context).wait() { + Ok(rsp) => match rsp { + AddPetResponse::InvalidInput => { + + + let mut response = Response::with((status::Status::from_u16(405))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "AddPet"); + + let api_clone = api.clone(); + router.delete( + "/v2/pet/:petId", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + let authorization = context.authorization.as_ref().ok_or_else(|| { + Response::with(( + status::Forbidden, + "Unauthenticated".to_string() + )) + })?; + + // Authorization + if let Scopes::Some(ref scopes) = authorization.scopes { + let required_scopes: BTreeSet = vec![ + "write:pets".to_string(), // modify pets in your account + "read:pets".to_string(), // read your pets + ].into_iter().collect(); + + if !required_scopes.is_subset(scopes) { + let missing_scopes = required_scopes.difference(scopes); + return Err(Response::with(( + status::Forbidden, + missing_scopes.fold( + "Insufficient authorization, missing scopes".to_string(), + |s, scope| format!("{} {}", s, scope) + ) + ))); + } + } + + + // Path parameters + let param_pet_id = { + let param = req.extensions.get::().ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("petId").ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter petId".to_string())))?; + percent_decode(param.as_bytes()).decode_utf8() + .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? + .parse().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter petId: {}", e))))? + }; + + // Header parameters + header! { (RequestApiKey, "api_key") => [String] } + let param_api_key = req.headers.get::().map(|header| header.0.clone()); + + + + match api.delete_pet(param_pet_id, param_api_key, context).wait() { + Ok(rsp) => match rsp { + DeletePetResponse::InvalidPetValue => { + + + let mut response = Response::with((status::Status::from_u16(400))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "DeletePet"); + + let api_clone = api.clone(); + router.get( + "/v2/pet/findByStatus", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + let authorization = context.authorization.as_ref().ok_or_else(|| { + Response::with(( + status::Forbidden, + "Unauthenticated".to_string() + )) + })?; + + // Authorization + if let Scopes::Some(ref scopes) = authorization.scopes { + let required_scopes: BTreeSet = vec![ + "write:pets".to_string(), // modify pets in your account + "read:pets".to_string(), // read your pets + ].into_iter().collect(); + + if !required_scopes.is_subset(scopes) { + let missing_scopes = required_scopes.difference(scopes); + return Err(Response::with(( + status::Forbidden, + missing_scopes.fold( + "Insufficient authorization, missing scopes".to_string(), + |s, scope| format!("{} {}", s, scope) + ) + ))); + } + } + + + + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) + let query_params = req.get::().unwrap_or_default(); + let param_status = query_params.get("status") + .ok_or_else(|| Response::with((status::BadRequest, "Missing required query parameter status".to_string())))? + .iter().flat_map(|x| x.parse::()).collect::>(); + + + match api.find_pets_by_status(param_status.as_ref(), context).wait() { + Ok(rsp) => match rsp { + FindPetsByStatusResponse::SuccessfulOperation(body) => { + + let body_string = serde_xml_rs::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(200), body_string)); + response.headers.set(ContentType(mimetypes::responses::FIND_PETS_BY_STATUS_SUCCESSFUL_OPERATION.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + FindPetsByStatusResponse::InvalidStatusValue => { + + + let mut response = Response::with((status::Status::from_u16(400))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "FindPetsByStatus"); + + let api_clone = api.clone(); + router.get( + "/v2/pet/findByTags", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + let authorization = context.authorization.as_ref().ok_or_else(|| { + Response::with(( + status::Forbidden, + "Unauthenticated".to_string() + )) + })?; + + // Authorization + if let Scopes::Some(ref scopes) = authorization.scopes { + let required_scopes: BTreeSet = vec![ + "write:pets".to_string(), // modify pets in your account + "read:pets".to_string(), // read your pets + ].into_iter().collect(); + + if !required_scopes.is_subset(scopes) { + let missing_scopes = required_scopes.difference(scopes); + return Err(Response::with(( + status::Forbidden, + missing_scopes.fold( + "Insufficient authorization, missing scopes".to_string(), + |s, scope| format!("{} {}", s, scope) + ) + ))); + } + } + + + + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) + let query_params = req.get::().unwrap_or_default(); + let param_tags = query_params.get("tags") + .ok_or_else(|| Response::with((status::BadRequest, "Missing required query parameter tags".to_string())))? + .iter().flat_map(|x| x.parse::()).collect::>(); + + + match api.find_pets_by_tags(param_tags.as_ref(), context).wait() { + Ok(rsp) => match rsp { + FindPetsByTagsResponse::SuccessfulOperation(body) => { + + let body_string = serde_xml_rs::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(200), body_string)); + response.headers.set(ContentType(mimetypes::responses::FIND_PETS_BY_TAGS_SUCCESSFUL_OPERATION.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + FindPetsByTagsResponse::InvalidTagValue => { + + + let mut response = Response::with((status::Status::from_u16(400))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "FindPetsByTags"); + + let api_clone = api.clone(); + router.get( + "/v2/pet/:petId", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + let authorization = context.authorization.as_ref().ok_or_else(|| { + Response::with(( + status::Forbidden, + "Unauthenticated".to_string() + )) + })?; + + + + // Path parameters + let param_pet_id = { + let param = req.extensions.get::().ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("petId").ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter petId".to_string())))?; + percent_decode(param.as_bytes()).decode_utf8() + .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? + .parse().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter petId: {}", e))))? + }; + + + + match api.get_pet_by_id(param_pet_id, context).wait() { + Ok(rsp) => match rsp { + GetPetByIdResponse::SuccessfulOperation(body) => { + + let body_string = serde_xml_rs::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(200), body_string)); + response.headers.set(ContentType(mimetypes::responses::GET_PET_BY_ID_SUCCESSFUL_OPERATION.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + GetPetByIdResponse::InvalidIDSupplied => { + + + let mut response = Response::with((status::Status::from_u16(400))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + GetPetByIdResponse::PetNotFound => { + + + let mut response = Response::with((status::Status::from_u16(404))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "GetPetById"); + + let api_clone = api.clone(); + router.put( + "/v2/pet", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + let authorization = context.authorization.as_ref().ok_or_else(|| { + Response::with(( + status::Forbidden, + "Unauthenticated".to_string() + )) + })?; + + // Authorization + if let Scopes::Some(ref scopes) = authorization.scopes { + let required_scopes: BTreeSet = vec![ + "write:pets".to_string(), // modify pets in your account + "read:pets".to_string(), // read your pets + ].into_iter().collect(); + + if !required_scopes.is_subset(scopes) { + let missing_scopes = required_scopes.difference(scopes); + return Err(Response::with(( + status::Forbidden, + missing_scopes.fold( + "Insufficient authorization, missing scopes".to_string(), + |s, scope| format!("{} {}", s, scope) + ) + ))); + } + } + + + + // 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. + + let param_body_raw = req.get::().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter body - not valid UTF-8: {}", e))))?; + let mut unused_elements = Vec::new(); + + let param_body = if let Some(param_body_raw) = param_body_raw { + let deserializer = &mut serde_xml_rs::de::Deserializer::new_from_reader(param_body_raw.as_bytes()); + + let param_body: Option = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter body - doesn't match schema: {}", e))))?; + + param_body + } else { + None + }; + let param_body = param_body.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter body".to_string())))?; + + + match api.update_pet(param_body, context).wait() { + Ok(rsp) => match rsp { + UpdatePetResponse::InvalidIDSupplied => { + + + let mut response = Response::with((status::Status::from_u16(400))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + }, + UpdatePetResponse::PetNotFound => { + + + let mut response = Response::with((status::Status::from_u16(404))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + }, + UpdatePetResponse::ValidationException => { + + + let mut response = Response::with((status::Status::from_u16(405))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "UpdatePet"); + + let api_clone = api.clone(); + router.post( + "/v2/pet/:petId", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + let authorization = context.authorization.as_ref().ok_or_else(|| { + Response::with(( + status::Forbidden, + "Unauthenticated".to_string() + )) + })?; + + // Authorization + if let Scopes::Some(ref scopes) = authorization.scopes { + let required_scopes: BTreeSet = vec![ + "write:pets".to_string(), // modify pets in your account + "read:pets".to_string(), // read your pets + ].into_iter().collect(); + + if !required_scopes.is_subset(scopes) { + let missing_scopes = required_scopes.difference(scopes); + return Err(Response::with(( + status::Forbidden, + missing_scopes.fold( + "Insufficient authorization, missing scopes".to_string(), + |s, scope| format!("{} {}", s, scope) + ) + ))); + } + } + + + // Path parameters + let param_pet_id = { + let param = req.extensions.get::().ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("petId").ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter petId".to_string())))?; + percent_decode(param.as_bytes()).decode_utf8() + .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? + .parse().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter petId: {}", e))))? + }; + + + // Form parameters + let param_name = Some("name_example".to_string()); + let param_status = Some("status_example".to_string()); + + match api.update_pet_with_form(param_pet_id, param_name, param_status, context).wait() { + Ok(rsp) => match rsp { + UpdatePetWithFormResponse::InvalidInput => { + + + let mut response = Response::with((status::Status::from_u16(405))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "UpdatePetWithForm"); + + let api_clone = api.clone(); + router.post( + "/v2/pet/:petId/uploadImage", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + let authorization = context.authorization.as_ref().ok_or_else(|| { + Response::with(( + status::Forbidden, + "Unauthenticated".to_string() + )) + })?; + + // Authorization + if let Scopes::Some(ref scopes) = authorization.scopes { + let required_scopes: BTreeSet = vec![ + "write:pets".to_string(), // modify pets in your account + "read:pets".to_string(), // read your pets + ].into_iter().collect(); + + if !required_scopes.is_subset(scopes) { + let missing_scopes = required_scopes.difference(scopes); + return Err(Response::with(( + status::Forbidden, + missing_scopes.fold( + "Insufficient authorization, missing scopes".to_string(), + |s, scope| format!("{} {}", s, scope) + ) + ))); + } + } + + + // Path parameters + let param_pet_id = { + let param = req.extensions.get::().ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("petId").ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter petId".to_string())))?; + percent_decode(param.as_bytes()).decode_utf8() + .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? + .parse().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter petId: {}", e))))? + }; + + + // Form parameters + + // Expecting a multipart form, extract and parse it now. + let mut entries = match Multipart::from_request(req) { + Ok(mut multipart) => { + + match multipart.save().temp() { + SaveResult::Full(entries) => { + Ok(entries) + }, + _ => { + Err(Response::with((status::InternalServerError, format!("Unable to process all message parts")))) + }, + } + }, + Err(e) => { + // Unable to parse as multipart + Err(Response::with((status::BadRequest, format!("Couldn't parse body as multipart")))) + } + }?; + + let param_additional_metadata = Some("additional_metadata_example".to_string()); + + + let param_file = entries.fields.remove("file"); + + let param_file = match param_file { + Some(body) => { + Ok({let bytes = body.as_bytes(); + Some( + Box::new(stream::once(Ok(bytes.to_vec()))) as Box, Error=Error> + Send> + )} + ) + } + None => {Err(Response::with((status::BadRequest, format!("Body part not found!"))))} + }?; + let param_file = Box::new(future::ok(param_file)); + + match api.upload_file(param_pet_id, param_additional_metadata, param_file, context).wait() { + Ok(rsp) => match rsp { + UploadFileResponse::SuccessfulOperation(body) => { + + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(200), body_string)); + response.headers.set(ContentType(mimetypes::responses::UPLOAD_FILE_SUCCESSFUL_OPERATION.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "UploadFile"); + + let api_clone = api.clone(); + router.delete( + "/v2/store/order/:order_id", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + + + // Path parameters + let param_order_id = { + let param = req.extensions.get::().ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("order_id").ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter order_id".to_string())))?; + percent_decode(param.as_bytes()).decode_utf8() + .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? + .parse().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter order_id: {}", e))))? + }; + + + + match api.delete_order(param_order_id, context).wait() { + Ok(rsp) => match rsp { + DeleteOrderResponse::InvalidIDSupplied => { + + + let mut response = Response::with((status::Status::from_u16(400))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + DeleteOrderResponse::OrderNotFound => { + + + let mut response = Response::with((status::Status::from_u16(404))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "DeleteOrder"); + + let api_clone = api.clone(); + router.get( + "/v2/store/inventory", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + let authorization = context.authorization.as_ref().ok_or_else(|| { + Response::with(( + status::Forbidden, + "Unauthenticated".to_string() + )) + })?; + + + + + + match api.get_inventory(context).wait() { + Ok(rsp) => match rsp { + GetInventoryResponse::SuccessfulOperation(body) => { + + let body_string = serde_json::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(200), body_string)); + response.headers.set(ContentType(mimetypes::responses::GET_INVENTORY_SUCCESSFUL_OPERATION.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "GetInventory"); + + let api_clone = api.clone(); + router.get( + "/v2/store/order/:order_id", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + + + // Path parameters + let param_order_id = { + let param = req.extensions.get::().ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("order_id").ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter order_id".to_string())))?; + percent_decode(param.as_bytes()).decode_utf8() + .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? + .parse().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter order_id: {}", e))))? + }; + + + + match api.get_order_by_id(param_order_id, context).wait() { + Ok(rsp) => match rsp { + GetOrderByIdResponse::SuccessfulOperation(body) => { + + let body_string = serde_xml_rs::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(200), body_string)); + response.headers.set(ContentType(mimetypes::responses::GET_ORDER_BY_ID_SUCCESSFUL_OPERATION.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + GetOrderByIdResponse::InvalidIDSupplied => { + + + let mut response = Response::with((status::Status::from_u16(400))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + GetOrderByIdResponse::OrderNotFound => { + + + let mut response = Response::with((status::Status::from_u16(404))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "GetOrderById"); + + let api_clone = api.clone(); + router.post( + "/v2/store/order", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + + + + // 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. + + let param_body_raw = req.get::().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter body - not valid UTF-8: {}", e))))?; + let mut unused_elements = Vec::new(); + + let param_body = if let Some(param_body_raw) = param_body_raw { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_body_raw); + + let param_body: Option = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter body - doesn't match schema: {}", e))))?; + + param_body + } else { + None + }; + let param_body = param_body.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter body".to_string())))?; + + + match api.place_order(param_body, context).wait() { + Ok(rsp) => match rsp { + PlaceOrderResponse::SuccessfulOperation(body) => { + + let body_string = serde_xml_rs::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(200), body_string)); + response.headers.set(ContentType(mimetypes::responses::PLACE_ORDER_SUCCESSFUL_OPERATION.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + }, + PlaceOrderResponse::InvalidOrder => { + + + let mut response = Response::with((status::Status::from_u16(400))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "PlaceOrder"); + + let api_clone = api.clone(); + router.post( + "/v2/user", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + + + + // 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. + + let param_body_raw = req.get::().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter body - not valid UTF-8: {}", e))))?; + let mut unused_elements = Vec::new(); + + let param_body = if let Some(param_body_raw) = param_body_raw { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_body_raw); + + let param_body: Option = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter body - doesn't match schema: {}", e))))?; + + param_body + } else { + None + }; + let param_body = param_body.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter body".to_string())))?; + + + match api.create_user(param_body, context).wait() { + Ok(rsp) => match rsp { + CreateUserResponse::SuccessfulOperation => { + + + let mut response = Response::with((status::Status::from_u16(0))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "CreateUser"); + + let api_clone = api.clone(); + router.post( + "/v2/user/createWithArray", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + + + + // 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. + + let param_body_raw = req.get::().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter body - not valid UTF-8: {}", e))))?; + let mut unused_elements = Vec::new(); + + let param_body = if let Some(param_body_raw) = param_body_raw { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_body_raw); + + let param_body: Option> = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter body - doesn't match schema: {}", e))))?; + + param_body + } else { + None + }; + let param_body = param_body.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter body".to_string())))?; + + + match api.create_users_with_array_input(param_body.as_ref(), context).wait() { + Ok(rsp) => match rsp { + CreateUsersWithArrayInputResponse::SuccessfulOperation => { + + + let mut response = Response::with((status::Status::from_u16(0))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "CreateUsersWithArrayInput"); + + let api_clone = api.clone(); + router.post( + "/v2/user/createWithList", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + + + + // 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. + + let param_body_raw = req.get::().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter body - not valid UTF-8: {}", e))))?; + let mut unused_elements = Vec::new(); + + let param_body = if let Some(param_body_raw) = param_body_raw { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_body_raw); + + let param_body: Option> = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter body - doesn't match schema: {}", e))))?; + + param_body + } else { + None + }; + let param_body = param_body.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter body".to_string())))?; + + + match api.create_users_with_list_input(param_body.as_ref(), context).wait() { + Ok(rsp) => match rsp { + CreateUsersWithListInputResponse::SuccessfulOperation => { + + + let mut response = Response::with((status::Status::from_u16(0))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "CreateUsersWithListInput"); + + let api_clone = api.clone(); + router.delete( + "/v2/user/:username", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + + + // Path parameters + let param_username = { + let param = req.extensions.get::().ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("username").ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter username".to_string())))?; + percent_decode(param.as_bytes()).decode_utf8() + .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? + .parse().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter username: {}", e))))? + }; + + + + match api.delete_user(param_username, context).wait() { + Ok(rsp) => match rsp { + DeleteUserResponse::InvalidUsernameSupplied => { + + + let mut response = Response::with((status::Status::from_u16(400))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + DeleteUserResponse::UserNotFound => { + + + let mut response = Response::with((status::Status::from_u16(404))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "DeleteUser"); + + let api_clone = api.clone(); + router.get( + "/v2/user/:username", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + + + // Path parameters + let param_username = { + let param = req.extensions.get::().ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("username").ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter username".to_string())))?; + percent_decode(param.as_bytes()).decode_utf8() + .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? + .parse().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter username: {}", e))))? + }; + + + + match api.get_user_by_name(param_username, context).wait() { + Ok(rsp) => match rsp { + GetUserByNameResponse::SuccessfulOperation(body) => { + + let body_string = serde_xml_rs::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(200), body_string)); + response.headers.set(ContentType(mimetypes::responses::GET_USER_BY_NAME_SUCCESSFUL_OPERATION.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + GetUserByNameResponse::InvalidUsernameSupplied => { + + + let mut response = Response::with((status::Status::from_u16(400))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + GetUserByNameResponse::UserNotFound => { + + + let mut response = Response::with((status::Status::from_u16(404))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "GetUserByName"); + + let api_clone = api.clone(); + router.get( + "/v2/user/login", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + + + + // Query parameters (note that non-required or collection query parameters will ignore garbage values, rather than causing a 400 response) + let query_params = req.get::().unwrap_or_default(); + let param_username = query_params.get("username") + .ok_or_else(|| Response::with((status::BadRequest, "Missing required query parameter username".to_string())))? + .first().ok_or_else(|| Response::with((status::BadRequest, "Required query parameter username was empty".to_string())))? + .parse::().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse query parameter username - doesn't match schema: {}", e))))?; + let param_password = query_params.get("password") + .ok_or_else(|| Response::with((status::BadRequest, "Missing required query parameter password".to_string())))? + .first().ok_or_else(|| Response::with((status::BadRequest, "Required query parameter password was empty".to_string())))? + .parse::().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse query parameter password - doesn't match schema: {}", e))))?; + + + match api.login_user(param_username, param_password, context).wait() { + Ok(rsp) => match rsp { + LoginUserResponse::SuccessfulOperation{ body, x_rate_limit, x_expires_after } => { + + let body_string = serde_xml_rs::to_string(&body).expect("impossible to fail to serialize"); + + let mut response = Response::with((status::Status::from_u16(200), body_string)); header! { (ResponseXRateLimit, "X-Rate-Limit") => [i32] } + response.headers.set(ResponseXRateLimit(x_rate_limit)); + header! { (ResponseXExpiresAfter, "X-Expires-After") => [chrono::DateTime] } + response.headers.set(ResponseXExpiresAfter(x_expires_after)); + + response.headers.set(ContentType(mimetypes::responses::LOGIN_USER_SUCCESSFUL_OPERATION.clone())); + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + LoginUserResponse::InvalidUsername => { + + + let mut response = Response::with((status::Status::from_u16(400))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "LoginUser"); + + let api_clone = api.clone(); + router.get( + "/v2/user/logout", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + + + + + match api.logout_user(context).wait() { + Ok(rsp) => match rsp { + LogoutUserResponse::SuccessfulOperation => { + + + let mut response = Response::with((status::Status::from_u16(0))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "LogoutUser"); + + let api_clone = api.clone(); + router.put( + "/v2/user/:username", + move |req: &mut Request| { + let mut context = Context::default(); + + // Helper function to provide a code block to use `?` in (to be replaced by the `catch` block when it exists). + fn handle_request(req: &mut Request, api: &T, context: &mut Context) -> Result where T: Api { + + context.x_span_id = Some(req.headers.get::().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string())); + context.auth_data = req.extensions.remove::(); + context.authorization = req.extensions.remove::(); + + + + // Path parameters + let param_username = { + let param = req.extensions.get::().ok_or_else(|| Response::with((status::InternalServerError, "An internal error occurred".to_string())))? + .find("username").ok_or_else(|| Response::with((status::BadRequest, "Missing path parameter username".to_string())))?; + percent_decode(param.as_bytes()).decode_utf8() + .map_err(|_| Response::with((status::BadRequest, format!("Couldn't percent-decode path parameter as UTF-8: {}", param))))? + .parse().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse path parameter username: {}", e))))? + }; + + + // 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. + + let param_body_raw = req.get::().map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter body - not valid UTF-8: {}", e))))?; + let mut unused_elements = Vec::new(); + + let param_body = if let Some(param_body_raw) = param_body_raw { + let deserializer = &mut serde_json::Deserializer::from_str(¶m_body_raw); + + let param_body: Option = serde_ignored::deserialize(deserializer, |path| { + warn!("Ignoring unknown field in body: {}", path); + unused_elements.push(path.to_string()); + }).map_err(|e| Response::with((status::BadRequest, format!("Couldn't parse body parameter body - doesn't match schema: {}", e))))?; + + param_body + } else { + None + }; + let param_body = param_body.ok_or_else(|| Response::with((status::BadRequest, "Missing required body parameter body".to_string())))?; + + + match api.update_user(param_username, param_body, context).wait() { + Ok(rsp) => match rsp { + UpdateUserResponse::InvalidUserSupplied => { + + + let mut response = Response::with((status::Status::from_u16(400))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + }, + UpdateUserResponse::UserNotFound => { + + + let mut response = Response::with((status::Status::from_u16(404))); + + + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + if !unused_elements.is_empty() { + response.headers.set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements))); + } + Ok(response) + }, + }, + Err(_) => { + // Application code returned an error. This should not happen, as the implementation should + // return a valid response. + Err(Response::with((status::InternalServerError, "An internal error occurred".to_string()))) + } + } + } + + handle_request(req, &api_clone, &mut context).or_else(|mut response| { + context.x_span_id.as_ref().map(|header| response.headers.set(XSpanId(header.clone()))); + Ok(response) + }) + }, + "UpdateUser"); + +} + +/// Middleware to extract authentication data from request +pub struct ExtractAuthData; + +impl BeforeMiddleware for ExtractAuthData { + fn before(&self, req: &mut Request) -> IronResult<()> { + { + header! { (ApiKey1, "api_key") => [String] } + if let Some(header) = req.headers.get::() { + req.extensions.insert::(AuthData::ApiKey(header.0.clone())); + return Ok(()); + } + } + { + let header = match req.get_ref::() { + Ok(query) => query.get("api_key_query").map(|v| v[0].clone()), + _ => None + }; + if let Some(key) = header { + req.extensions.insert::(AuthData::ApiKey(key)); + return Ok(()); + } + } + { + use hyper::header::{Authorization, Basic, Bearer}; + use std::ops::Deref; + if let Some(basic) = req.headers.get::>() { + req.extensions.insert::(AuthData::Basic(basic.deref().clone())); + return Ok(()); + } + } + { + use hyper::header::{Authorization, Basic, Bearer}; + use std::ops::Deref; + if let Some(bearer) = req.headers.get::>() { + req.extensions.insert::(AuthData::Bearer(bearer.deref().clone())); + return Ok(()); + } + } + + Ok(()) + } +}