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(()) + } +}