diff --git a/README.md b/README.md
index a8d0c4e1cfe4..5f231380b4d8 100644
--- a/README.md
+++ b/README.md
@@ -779,6 +779,7 @@ Here is a list of template creators:
* Bash: @bkryza
* C: @PowerOfCreation @zhemant [:heart:](https://www.patreon.com/zhemant)
* C++ REST: @Danielku15
+ * C++ UE4: @Kahncode
* C# (.NET 2.0): @who
* C# (.NET Standard 1.3 ): @Gronsak
* C# (.NET 4.5 refactored): @jimschubert [:heart:](https://www.patreon.com/jimschubert)
diff --git a/bin/cpp-ue4-petstore.sh b/bin/cpp-ue4-petstore.sh
new file mode 100755
index 000000000000..9eeab274c870
--- /dev/null
+++ b/bin/cpp-ue4-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/openapi-generator-cli/target/openapi-generator-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/openapi-generator/src/main/resources/cpp-ue4 -i modules/openapi-generator/src/test/resources/2_0/petstore.yaml -g cpp-ue4 -o samples/client/petstore/cpp-ue4"
+
+java $JAVA_OPTS -jar $executable $ags
diff --git a/bin/windows/cpp-ue4-petstore.bat b/bin/windows/cpp-ue4-petstore.bat
new file mode 100644
index 000000000000..726c92dc1ac4
--- /dev/null
+++ b/bin/windows/cpp-ue4-petstore.bat
@@ -0,0 +1,10 @@
+set executable=.\modules\openapi-generator-cli\target\openapi-generator-cli.jar
+
+If Not Exist %executable% (
+ mvn clean package
+)
+
+REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M
+set ags=generate -i modules\openapi-generator\src\test\resources\2_0\petstore.yaml -g cpp-ue4 -o samples\client\petstore\cpp-ue4
+
+java %JAVA_OPTS% -jar %executable% %ags%
diff --git a/docs/generators.md b/docs/generators.md
index 50a944ebb366..3d0bb08663a5 100644
--- a/docs/generators.md
+++ b/docs/generators.md
@@ -15,6 +15,7 @@ The following generators are available:
* [cpp-qt5-client](generators/cpp-qt5-client.md)
* [cpp-restsdk](generators/cpp-restsdk.md)
* [cpp-tizen](generators/cpp-tizen.md)
+* [cpp-ue4 (beta)](generators/cpp-ue4.md)
* [csharp](generators/csharp.md)
* [csharp-dotnet2 (deprecated)](generators/csharp-dotnet2.md)
* [csharp-netcore](generators/csharp-netcore.md)
diff --git a/docs/generators/cpp-ue4.md b/docs/generators/cpp-ue4.md
new file mode 100644
index 000000000000..eb00fa4a5ceb
--- /dev/null
+++ b/docs/generators/cpp-ue4.md
@@ -0,0 +1,248 @@
+---
+title: Config Options for cpp-ue4
+sidebar_label: cpp-ue4
+---
+
+| Option | Description | Values | Default |
+| ------ | ----------- | ------ | ------- |
+|allowUnicodeIdentifiers|boolean, toggles whether unicode identifiers are allowed in names or not, default is false| |false|
+|cppNamespace|C++ namespace (convention: name::space::for::api).| |OpenAPI|
+|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true|
+|legacyDiscriminatorBehavior|This flag is used by OpenAPITools codegen to influence the processing of the discriminator attribute in OpenAPI documents. This flag has no impact if the OAS document does not use the discriminator attribute. The default value of this flag is set in each language-specific code generator (e.g. Python, Java, go...)using the method toModelName. Note to developers supporting a language generator in OpenAPITools; to fully support the discriminator attribute as defined in the OAS specification 3.x, language generators should set this flag to true by default; however this requires updating the mustache templates to generate a language-specific discriminator lookup function that iterates over {{#mappedModels}} and does not iterate over {{children}}, {{#anyOf}}, or {{#oneOf}}.|
- **true**
- The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.
- **false**
- The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.
|true|
+|optionalProjectFile|Generate Build.cs| |true|
+|prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false|
+|reservedWordPrefix|Prefix to prepend to reserved words in order to avoid conflicts| |r_|
+|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true|
+|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true|
+|unrealModuleName|Name of the generated unreal module (optional)| |OpenAPI|
+|variableNameFirstCharacterUppercase|Make first character of variable name uppercase (eg. value -> Value)| |true|
+
+## IMPORT MAPPING
+
+| Type/Alias | Imports |
+| ---------- | ------- |
+|HttpFileInput|#include "OpenAPIHelpers.h"|
+
+
+## INSTANTIATION TYPES
+
+| Type/Alias | Instantiated By |
+| ---------- | --------------- |
+
+
+## LANGUAGE PRIMITIVES
+
+
+- FDateTime
+- FGuid
+- FString
+- TArray
+- TArray<uint8>
+- TMap
+- TSharedPtr<FJsonObject>
+- bool
+- double
+- float
+- int32
+- int64
+
+
+## RESERVED WORDS
+
+
+- alignas
+- alignof
+- and
+- and_eq
+- asm
+- auto
+- bitand
+- bitor
+- bool
+- break
+- case
+- catch
+- char
+- char16_t
+- char32_t
+- class
+- compl
+- concept
+- const
+- const_cast
+- constexpr
+- continue
+- decltype
+- default
+- delete
+- do
+- double
+- dynamic_cast
+- else
+- enum
+- explicit
+- export
+- extern
+- false
+- float
+- for
+- friend
+- goto
+- if
+- inline
+- int
+- linux
+- long
+- mutable
+- namespace
+- new
+- noexcept
+- not
+- not_eq
+- nullptr
+- operator
+- or
+- or_eq
+- private
+- protected
+- public
+- register
+- reinterpret_cast
+- requires
+- return
+- short
+- signed
+- sizeof
+- static
+- static_assert
+- static_cast
+- struct
+- switch
+- template
+- this
+- thread_local
+- throw
+- true
+- try
+- typedef
+- typeid
+- typename
+- union
+- unsigned
+- using
+- virtual
+- void
+- volatile
+- wchar_t
+- while
+- xor
+- xor_eq
+
+
+## FEATURE SET
+
+
+### Client Modification Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|BasePath|✗|ToolingExtension
+|Authorizations|✗|ToolingExtension
+|UserAgent|✗|ToolingExtension
+
+### Data Type Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|Custom|✗|OAS2,OAS3
+|Int32|✓|OAS2,OAS3
+|Int64|✓|OAS2,OAS3
+|Float|✓|OAS2,OAS3
+|Double|✓|OAS2,OAS3
+|Decimal|✓|ToolingExtension
+|String|✓|OAS2,OAS3
+|Byte|✓|OAS2,OAS3
+|Binary|✓|OAS2,OAS3
+|Boolean|✓|OAS2,OAS3
+|Date|✓|OAS2,OAS3
+|DateTime|✓|OAS2,OAS3
+|Password|✓|OAS2,OAS3
+|File|✓|OAS2
+|Array|✓|OAS2,OAS3
+|Maps|✓|ToolingExtension
+|CollectionFormat|✓|OAS2
+|CollectionFormatMulti|✓|OAS2
+|Enum|✓|OAS2,OAS3
+|ArrayOfEnum|✓|ToolingExtension
+|ArrayOfModel|✓|ToolingExtension
+|ArrayOfCollectionOfPrimitives|✓|ToolingExtension
+|ArrayOfCollectionOfModel|✓|ToolingExtension
+|ArrayOfCollectionOfEnum|✓|ToolingExtension
+|MapOfEnum|✓|ToolingExtension
+|MapOfModel|✓|ToolingExtension
+|MapOfCollectionOfPrimitives|✓|ToolingExtension
+|MapOfCollectionOfModel|✓|ToolingExtension
+|MapOfCollectionOfEnum|✓|ToolingExtension
+
+### Documentation Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|Readme|✗|ToolingExtension
+|Model|✓|ToolingExtension
+|Api|✓|ToolingExtension
+
+### Global Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|Host|✓|OAS2,OAS3
+|BasePath|✓|OAS2,OAS3
+|Info|✓|OAS2,OAS3
+|Schemes|✗|OAS2,OAS3
+|PartialSchemes|✓|OAS2,OAS3
+|Consumes|✓|OAS2
+|Produces|✓|OAS2
+|ExternalDocumentation|✓|OAS2,OAS3
+|Examples|✓|OAS2,OAS3
+|XMLStructureDefinitions|✗|OAS2,OAS3
+|MultiServer|✗|OAS3
+|ParameterizedServer|✗|OAS3
+|ParameterStyling|✗|OAS3
+|Callbacks|✓|OAS3
+|LinkObjects|✗|OAS3
+
+### Parameter Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|Path|✓|OAS2,OAS3
+|Query|✓|OAS2,OAS3
+|Header|✓|OAS2,OAS3
+|Body|✓|OAS2
+|FormUnencoded|✓|OAS2
+|FormMultipart|✓|OAS2
+|Cookie|✓|OAS3
+
+### Schema Support Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|Simple|✓|OAS2,OAS3
+|Composite|✓|OAS2,OAS3
+|Polymorphism|✓|OAS2,OAS3
+|Union|✗|OAS3
+
+### Security Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|BasicAuth|✓|OAS2,OAS3
+|ApiKey|✓|OAS2,OAS3
+|OpenIDConnect|✗|OAS3
+|BearerToken|✓|OAS3
+|OAuth2_Implicit|✓|OAS2,OAS3
+|OAuth2_Password|✓|OAS2,OAS3
+|OAuth2_ClientCredentials|✓|OAS2,OAS3
+|OAuth2_AuthorizationCode|✓|OAS2,OAS3
+
+### Wire Format Feature
+| Name | Supported | Defined By |
+| ---- | --------- | ---------- |
+|JSON|✓|OAS2,OAS3
+|XML|✓|OAS2,OAS3
+|PROTOBUF|✗|ToolingExtension
+|Custom|✗|OAS2,OAS3
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppUE4ClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppUE4ClientCodegen.java
new file mode 100644
index 000000000000..88d9c309ecd1
--- /dev/null
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppUE4ClientCodegen.java
@@ -0,0 +1,544 @@
+/*
+ * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.openapitools.codegen.languages;
+
+import io.swagger.v3.oas.models.media.ArraySchema;
+import io.swagger.v3.oas.models.media.Schema;
+import org.openapitools.codegen.CodegenConstants;
+import org.openapitools.codegen.CodegenType;
+import org.openapitools.codegen.SupportingFile;
+import org.openapitools.codegen.meta.GeneratorMetadata;
+import org.openapitools.codegen.meta.Stability;
+import org.openapitools.codegen.utils.ModelUtils;
+
+import java.io.File;
+import java.util.*;
+
+import static org.openapitools.codegen.utils.StringUtils.camelize;
+
+public class CppUE4ClientCodegen extends AbstractCppCodegen {
+ public static final String CPP_NAMESPACE = "cppNamespace";
+ public static final String CPP_NAMESPACE_DESC = "C++ namespace (convention: name::space::for::api).";
+ public static final String UNREAL_MODULE_NAME = "unrealModuleName";
+ public static final String UNREAL_MODULE_NAME_DESC = "Name of the generated unreal module (optional)";
+ public static final String OPTIONAL_PROJECT_FILE_DESC = "Generate Build.cs";
+
+ protected String unrealModuleName = "OpenAPI";
+ // Will be treated as pointer
+ protected Set pointerClasses = new HashSet();
+ // source folder where to write the files
+ protected String privateFolder = "Private";
+ protected String publicFolder = "Public";
+ protected String apiVersion = "1.0.0";
+ protected Map namespaces = new HashMap();
+ // Will be included using the <> syntax, not used in Unreal's coding convention
+ protected Set systemIncludes = new HashSet();
+ protected String cppNamespace = unrealModuleName;
+ protected boolean optionalProjectFileFlag = true;
+
+ public CppUE4ClientCodegen() {
+ super();
+
+ generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
+ .stability(Stability.BETA)
+ .build();
+
+ // set the output folder here
+ outputFolder = "generated-code/cpp-ue4";
+
+ // set modelNamePrefix as default for cpp-ue4
+ if ("".equals(modelNamePrefix)) {
+ modelNamePrefix = unrealModuleName;
+ }
+
+ /*
+ * 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.put(
+ "model-header.mustache",
+ ".h");
+
+ modelTemplateFiles.put(
+ "model-source.mustache",
+ ".cpp");
+
+ /*
+ * 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.put(
+ "api-header.mustache", // the template to use
+ ".h"); // the extension for each file to write
+
+ apiTemplateFiles.put(
+ "api-source.mustache", // the template to use
+ ".cpp"); // the extension for each file to write
+
+ apiTemplateFiles.put(
+ "api-operations-header.mustache", // the template to use
+ ".h"); // the extension for each file to write
+
+ apiTemplateFiles.put(
+ "api-operations-source.mustache", // the template to use
+ ".cpp"); // the extension for each file to write
+
+ /*
+ * 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 = "cpp-ue4";
+
+ // CLI options
+ addOption(CPP_NAMESPACE, CPP_NAMESPACE_DESC, this.cppNamespace);
+ addOption(UNREAL_MODULE_NAME, UNREAL_MODULE_NAME_DESC, this.unrealModuleName);
+ addSwitch(CodegenConstants.OPTIONAL_PROJECT_FILE, OPTIONAL_PROJECT_FILE_DESC, this.optionalProjectFileFlag);
+
+ /*
+ * 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("modelNamePrefix", modelNamePrefix);
+ additionalProperties().put("modelPackage", modelPackage);
+ additionalProperties().put("apiPackage", apiPackage);
+ additionalProperties().put("dllapi", unrealModuleName.toUpperCase(Locale.ROOT) + "_API");
+ additionalProperties().put("unrealModuleName", unrealModuleName);
+
+ // Write defaults namespace in properties so that it can be accessible in templates.
+ // At this point command line has not been parsed so if value is given
+ // in command line it will superseed this content
+ additionalProperties.put("cppNamespace", cppNamespace);
+ additionalProperties.put("unrealModuleName", unrealModuleName);
+
+ /*
+ * Language Specific Primitives. These types will not trigger imports by
+ * the client generator
+ */
+ languageSpecificPrimitives = new HashSet(
+ Arrays.asList(
+ "bool",
+ "int32",
+ "int64",
+ "float",
+ "double",
+ "FString",
+ "FDateTime",
+ "FGuid",
+ "TArray",
+ "TArray", // For byte arrays
+ "TMap",
+ "TSharedPtr")
+ );
+
+ supportingFiles.add(new SupportingFile("model-base-header.mustache", publicFolder, modelNamePrefix + "BaseModel.h"));
+ supportingFiles.add(new SupportingFile("model-base-source.mustache", privateFolder, modelNamePrefix + "BaseModel.cpp"));
+ supportingFiles.add(new SupportingFile("helpers-header.mustache", publicFolder, modelNamePrefix + "Helpers.h"));
+ supportingFiles.add(new SupportingFile("helpers-source.mustache", privateFolder, modelNamePrefix + "Helpers.cpp"));
+ if (optionalProjectFileFlag) {
+ supportingFiles.add(new SupportingFile("Build.cs.mustache", unrealModuleName + ".Build.cs"));
+ supportingFiles.add(new SupportingFile("module-header.mustache", privateFolder, unrealModuleName + "Module.h"));
+ supportingFiles.add(new SupportingFile("module-source.mustache", privateFolder, unrealModuleName + "Module.cpp"));
+ }
+
+ super.typeMapping = new HashMap();
+
+ // Maps C++ types during call to getSchemaType, see DefaultCodegen.getSchemaType and not the types/formats
+ // defined in openapi specification "array" is also used explicitly in the generator for containers
+ typeMapping.clear();
+ typeMapping.put("integer", "int32");
+ typeMapping.put("long", "int64");
+ typeMapping.put("float", "float");
+ typeMapping.put("number", "double");
+ typeMapping.put("double", "double");
+ typeMapping.put("string", "FString");
+ typeMapping.put("byte", "uint8");
+ typeMapping.put("binary", "TArray");
+ typeMapping.put("ByteArray", "TArray");
+ typeMapping.put("password", "FString");
+ typeMapping.put("boolean", "bool");
+ typeMapping.put("date", "FDateTime");
+ typeMapping.put("Date", "FDateTime");
+ typeMapping.put("date-time", "FDateTime");
+ typeMapping.put("DateTime", "FDateTime");
+ typeMapping.put("array", "TArray");
+ typeMapping.put("list", "TArray");
+ typeMapping.put("map", "TMap");
+ typeMapping.put("object", "TSharedPtr");
+ typeMapping.put("Object", "TSharedPtr");
+ typeMapping.put("file", "HttpFileInput");
+ typeMapping.put("UUID", "FGuid");
+
+ importMapping = new HashMap();
+ importMapping.put("HttpFileInput", "#include \"" + modelNamePrefix + "Helpers.h\"");
+
+ namespaces = new HashMap();
+ }
+
+ @Override
+ public void processOpts() {
+ super.processOpts();
+
+ if (additionalProperties.containsKey("cppNamespace")) {
+ cppNamespace = (String) additionalProperties.get("cppNamespace");
+ }
+
+ additionalProperties.put("cppNamespaceDeclarations", cppNamespace.split("\\::"));
+
+ boolean updateSupportingFiles = false;
+ if (additionalProperties.containsKey("unrealModuleName")) {
+ unrealModuleName = (String) additionalProperties.get("unrealModuleName");
+ additionalProperties().put("dllapi", unrealModuleName.toUpperCase(Locale.ROOT) + "_API");
+ modelNamePrefix = unrealModuleName;
+ updateSupportingFiles = true;
+ }
+
+ if (additionalProperties.containsKey("modelNamePrefix")) {
+ modelNamePrefix = (String) additionalProperties.get("modelNamePrefix");
+ updateSupportingFiles = true;
+ }
+
+ if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_PROJECT_FILE)) {
+ setOptionalProjectFileFlag(convertPropertyToBooleanAndWriteBack(CodegenConstants.OPTIONAL_PROJECT_FILE));
+ } else {
+ additionalProperties.put(CodegenConstants.OPTIONAL_PROJECT_FILE, optionalProjectFileFlag);
+ }
+
+ if (updateSupportingFiles) {
+ supportingFiles.clear();
+
+ supportingFiles.add(new SupportingFile("model-base-header.mustache", publicFolder, modelNamePrefix + "BaseModel.h"));
+ supportingFiles.add(new SupportingFile("model-base-source.mustache", privateFolder, modelNamePrefix + "BaseModel.cpp"));
+ supportingFiles.add(new SupportingFile("helpers-header.mustache", publicFolder, modelNamePrefix + "Helpers.h"));
+ supportingFiles.add(new SupportingFile("helpers-source.mustache", privateFolder, modelNamePrefix + "Helpers.cpp"));
+ if (optionalProjectFileFlag) {
+ supportingFiles.add(new SupportingFile("Build.cs.mustache", unrealModuleName + ".Build.cs"));
+ supportingFiles.add(new SupportingFile("module-header.mustache", privateFolder, unrealModuleName + "Module.h"));
+ supportingFiles.add(new SupportingFile("module-source.mustache", privateFolder, unrealModuleName + "Module.cpp"));
+ }
+
+ importMapping.put("HttpFileInput", "#include \"" + modelNamePrefix + "Helpers.h\"");
+ }
+ }
+
+ public void setOptionalProjectFileFlag(boolean flag) {
+ this.optionalProjectFileFlag = flag;
+ }
+
+ /**
+ * Configures the type of generator.
+ *
+ * @return the CodegenType for this generator
+ * @see org.openapitools.codegen.CodegenType
+ */
+ @Override
+ public CodegenType getTag() {
+ return CodegenType.CLIENT;
+ }
+
+ /**
+ * 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 "cpp-ue4";
+ }
+
+ /**
+ * 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 Unreal Engine 4 C++ Module (beta).";
+ }
+
+ @Override
+ public String toModelImport(String name) {
+ if (namespaces.containsKey(name)) {
+ return "using " + namespaces.get(name) + ";";
+ } else if (systemIncludes.contains(name)) {
+ return "#include <" + name + ">";
+ }
+
+ String folder = modelPackage().replace("::", File.separator);
+ if (!folder.isEmpty())
+ folder += File.separator;
+
+ return "#include \"" + folder + name + ".h\"";
+ }
+
+ @Override
+ protected boolean needToImport(String type) {
+ boolean shouldImport = super.needToImport(type);
+ if (shouldImport)
+ return !languageSpecificPrimitives.contains(type);
+ else
+ return false;
+ }
+
+ /**
+ * 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 reserved words
+ *
+ * @return the escaped term
+ */
+ @Override
+ public String escapeReservedWord(String name) {
+ if (this.reservedWordsMappings().containsKey(name)) {
+ return this.reservedWordsMappings().get(name);
+ }
+ return "_" + name;
+ }
+
+ /**
+ * Location to write model files. You can use the modelPackage() as defined when the class is
+ * instantiated
+ */
+ @Override
+ public String modelFileFolder() {
+ return outputFolder + File.separator + modelPackage().replace("::", File.separator);
+ }
+
+ /**
+ * 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.separator);
+ }
+
+ /*
+ @Override
+ public String modelFilename(String templateName, String tag) {
+ String suffix = modelTemplateFiles().get(templateName);
+ String folder = privateFolder;
+ if (suffix == ".h") {
+ folder = publicFolder;
+ }
+
+ return modelFileFolder() + File.separator + folder + File.separator + toModelFilename(tag) + suffix;
+ }
+ */
+
+ @Override
+ public String toModelFilename(String name) {
+ name = sanitizeName(name);
+ return modelNamePrefix + camelize(name);
+ }
+
+ @Override
+ public String apiFilename(String templateName, String tag) {
+ String suffix = apiTemplateFiles().get(templateName);
+ String folder = privateFolder;
+ if (".h".equals(suffix)) {
+ folder = publicFolder;
+ }
+
+ if (templateName.startsWith("api-operations")) {
+ return apiFileFolder() + File.separator + folder + File.separator + toApiFilename(tag) + "Operations" + suffix;
+ } else {
+ return apiFileFolder() + File.separator + folder + File.separator + toApiFilename(tag) + suffix;
+ }
+ }
+
+ @Override
+ public String toApiFilename(String name) {
+ name = sanitizeName(name);
+ return modelNamePrefix + camelize(name) + "Api";
+ }
+
+ /**
+ * Optional - type declaration. This is a String which is used by the templates to instantiate your
+ * types. There is typically special handling for different property types
+ *
+ * @return a string value used as the `dataType` field for model templates, `returnType` for api templates
+ */
+ @Override
+ public String getTypeDeclaration(Schema p) {
+ String openAPIType = getSchemaType(p);
+
+ if (ModelUtils.isArraySchema(p)) {
+ ArraySchema ap = (ArraySchema) p;
+ String inner = getSchemaType(ap.getItems());
+ return getSchemaType(p) + "<" + getTypeDeclaration(inner) + ">";
+ } else if (ModelUtils.isMapSchema(p)) {
+ String inner = getSchemaType(ModelUtils.getAdditionalProperties(p));
+ return getSchemaType(p) + "";
+ }
+
+ if (pointerClasses.contains(openAPIType)) {
+ return openAPIType + "*";
+ } else if (languageSpecificPrimitives.contains(openAPIType)) {
+ return toModelName(openAPIType);
+ } else {
+ return openAPIType;
+ }
+ }
+
+
+ @Override
+ public String toDefaultValue(Schema p) {
+ if (ModelUtils.isStringSchema(p)) {
+ if (p.getDefault() != null) {
+ return "TEXT(\"" + p.getDefault().toString() + "\")";
+ } else {
+ return null;
+ }
+ } else if (ModelUtils.isBooleanSchema(p)) {
+ if (p.getDefault() != null) {
+ return p.getDefault().toString();
+ } else {
+ return "false";
+ }
+ } else if (ModelUtils.isDateSchema(p)) {
+ return "FDateTime(0)";
+ } else if (ModelUtils.isDateTimeSchema(p)) {
+ return "FDateTime(0)";
+ } else if (ModelUtils.isDoubleSchema(p)) {
+ if (p.getDefault() != null) {
+ return p.getDefault().toString();
+ } else {
+ return "0.0";
+ }
+ } else if (ModelUtils.isFloatSchema(p)) {
+ if (p.getDefault() != null) {
+ return p.getDefault().toString();
+ } else {
+ return "0.0f";
+ }
+ } else if (ModelUtils.isIntegerSchema(p)) {
+ if (p.getDefault() != null) {
+ return p.getDefault().toString();
+ } else {
+ return "0";
+ }
+ } else if (ModelUtils.isLongSchema(p)) {
+ if (p.getDefault() != null) {
+ return p.getDefault().toString();
+ } else {
+ return "0";
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Optional - OpenAPI type conversion. This is used to map OpenAPI types in a `Property` into
+ * either language specific types via `typeMapping` or into complex models if there is not a mapping.
+ *
+ * @return a string value of the type or complex model for this property
+ * @see io.swagger.v3.oas.models.media.Schema
+ */
+ @Override
+ public String getSchemaType(Schema p) {
+ String openAPIType = super.getSchemaType(p);
+ String type = null;
+ if (typeMapping.containsKey(openAPIType)) {
+ type = typeMapping.get(openAPIType);
+ if (languageSpecificPrimitives.contains(type)) {
+ return toModelName(type);
+ }
+ if (pointerClasses.contains(type)) {
+ return type;
+ }
+ } else {
+ type = openAPIType;
+ }
+ return toModelName(type);
+ }
+
+ @Override
+ public String toModelName(String type) {
+ if (typeMapping.keySet().contains(type) ||
+ typeMapping.values().contains(type) ||
+ importMapping.values().contains(type) ||
+ defaultIncludes.contains(type) ||
+ languageSpecificPrimitives.contains(type)) {
+ return type;
+ } else {
+ return modelNamePrefix + camelize(sanitizeName(type), false);
+ }
+ }
+
+ @Override
+ public String toVarName(String name) {
+ // sanitize name
+ name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
+
+ // if it's all uppper case, convert to lower case
+ if (name.matches("^[A-Z_]*$")) {
+ name = name.toLowerCase(Locale.ROOT);
+ }
+
+ // for reserved word or word starting with number, append _
+ if (isReservedWord(name) || name.matches("^\\d.*")) {
+ name = escapeReservedWord(name);
+ }
+
+ //Unreal variable names are CamelCase
+ return camelize(name, false);
+ }
+
+ @Override
+ public String toEnumVarName(String name, String datatype) {
+ return toVarName(name);
+ }
+
+ @Override
+ public String toParamName(String name) {
+ return toVarName(name);
+ }
+
+ @Override
+ public String toApiName(String type) {
+ return modelNamePrefix + camelize(type, false) + "Api";
+ }
+
+ @Override
+ public String escapeQuotationMark(String input) {
+ // remove " to avoid code injection
+ return input.replace("\"", "");
+ }
+
+ @Override
+ public String escapeUnsafeCharacters(String input) {
+ return input.replace("*/", "*_/").replace("/*", "/_*");
+ }
+
+ public String toBooleanGetter(String name) {
+ return "Is" + getterAndSetterCapitalize(name);
+ }
+
+ public String toGetter(String name) {
+ return "Get" + getterAndSetterCapitalize(name);
+ }
+
+ public String toSetter(String name) {
+ return "Set" + getterAndSetterCapitalize(name);
+ }
+}
diff --git a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig
index 13bb4e918500..cc86e5dc9d09 100644
--- a/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig
+++ b/modules/openapi-generator/src/main/resources/META-INF/services/org.openapitools.codegen.CodegenConfig
@@ -16,6 +16,7 @@ org.openapitools.codegen.languages.CppPistacheServerCodegen
org.openapitools.codegen.languages.CppRestbedServerCodegen
org.openapitools.codegen.languages.CppRestSdkClientCodegen
org.openapitools.codegen.languages.CppTizenClientCodegen
+org.openapitools.codegen.languages.CppUE4ClientCodegen
org.openapitools.codegen.languages.CSharpClientCodegen
org.openapitools.codegen.languages.CSharpNetCoreClientCodegen
org.openapitools.codegen.languages.CSharpDotNet2ClientCodegen
@@ -124,4 +125,4 @@ org.openapitools.codegen.languages.TypeScriptInversifyClientCodegen
org.openapitools.codegen.languages.TypeScriptJqueryClientCodegen
org.openapitools.codegen.languages.TypeScriptNodeClientCodegen
org.openapitools.codegen.languages.TypeScriptReduxQueryClientCodegen
-org.openapitools.codegen.languages.TypeScriptRxjsClientCodegen
+org.openapitools.codegen.languages.TypeScriptRxjsClientCodegen
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/cpp-ue4/Build.cs.mustache b/modules/openapi-generator/src/main/resources/cpp-ue4/Build.cs.mustache
new file mode 100644
index 000000000000..a6fe9bd84ec8
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/cpp-ue4/Build.cs.mustache
@@ -0,0 +1,19 @@
+{{>licenseInfo}}
+using System;
+using System.IO;
+using UnrealBuildTool;
+
+public class {{unrealModuleName}} : ModuleRules
+{
+ public {{unrealModuleName}}(ReadOnlyTargetRules Target) : base(Target)
+ {
+ PublicDependencyModuleNames.AddRange(
+ new string[]
+ {
+ "Core",
+ "Http",
+ "Json",
+ }
+ );
+ }
+}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/cpp-ue4/api-header.mustache b/modules/openapi-generator/src/main/resources/cpp-ue4/api-header.mustache
new file mode 100644
index 000000000000..6629cf47cb11
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/cpp-ue4/api-header.mustache
@@ -0,0 +1,42 @@
+{{>licenseInfo}}
+#pragma once
+
+#include "CoreMinimal.h"
+#include "{{modelNamePrefix}}BaseModel.h"
+
+{{#cppNamespaceDeclarations}}
+namespace {{this}}
+{
+{{/cppNamespaceDeclarations}}
+
+class {{dllapi}} {{classname}}
+{
+public:
+ {{classname}}();
+ ~{{classname}}();
+
+ void SetURL(const FString& Url);
+ void AddHeaderParam(const FString& Key, const FString& Value);
+ void ClearHeaderParams();
+
+ {{#operations}}{{#operation}}class {{operationIdCamelCase}}Request;
+ class {{operationIdCamelCase}}Response;
+ {{/operation}}{{/operations}}
+ {{#operations}}{{#operation}}DECLARE_DELEGATE_OneParam(F{{operationIdCamelCase}}Delegate, const {{operationIdCamelCase}}Response&);
+ {{/operation}}{{/operations}}
+ {{#operations}}{{#operation}}{{#description}}/* {{{description}}} */
+ {{/description}}bool {{operationIdCamelCase}}(const {{operationIdCamelCase}}Request& Request, const F{{operationIdCamelCase}}Delegate& Delegate = F{{operationIdCamelCase}}Delegate()) const;
+ {{/operation}}{{/operations}}
+private:
+ {{#operations}}{{#operation}}void On{{operationIdCamelCase}}Response(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, F{{operationIdCamelCase}}Delegate Delegate) const;
+ {{/operation}}{{/operations}}
+ bool IsValid() const;
+ void HandleResponse(FHttpResponsePtr HttpResponse, bool bSucceeded, Response& InOutResponse) const;
+
+ FString Url;
+ TMap AdditionalHeaderParams;
+};
+
+{{#cppNamespaceDeclarations}}
+}
+{{/cppNamespaceDeclarations}}
diff --git a/modules/openapi-generator/src/main/resources/cpp-ue4/api-operations-header.mustache b/modules/openapi-generator/src/main/resources/cpp-ue4/api-operations-header.mustache
new file mode 100644
index 000000000000..1486ef60e2cb
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/cpp-ue4/api-operations-header.mustache
@@ -0,0 +1,64 @@
+{{>licenseInfo}}
+#pragma once
+
+#include "{{modelNamePrefix}}BaseModel.h"
+#include "{{classname}}.h"
+
+{{#imports}}{{{import}}}
+{{/imports}}
+
+{{#cppNamespaceDeclarations}}
+namespace {{this}}
+{
+{{/cppNamespaceDeclarations}}
+
+{{#operations}}
+{{#operation}}
+/* {{summary}}
+{{#notes}} *
+ * {{notes}}{{/notes}}
+*/
+class {{dllapi}} {{classname}}::{{operationIdCamelCase}}Request : public Request
+{
+public:
+ virtual ~{{operationIdCamelCase}}Request() {}
+ void SetupHttpRequest(const TSharedRef& HttpRequest) const final;
+ FString ComputePath() const final;
+
+ {{#allParams}}
+ {{#isEnum}}
+ {{#allowableValues}}
+ enum class {{{enumName}}}
+ {
+ {{#enumVars}}
+ {{name}},
+ {{/enumVars}}
+ };
+ {{/allowableValues}}
+ {{#description}}/* {{{description}}} */
+ {{/description}}{{^required}}TOptional<{{/required}}{{{datatypeWithEnum}}}{{^required}}>{{/required}} {{paramName}}{{#required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{/required}};
+ {{/isEnum}}
+ {{^isEnum}}
+ {{#description}}/* {{{description}}} */
+ {{/description}}{{^required}}TOptional<{{/required}}{{{dataType}}}{{^required}}>{{/required}} {{paramName}}{{#required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{/required}};
+ {{/isEnum}}
+ {{/allParams}}
+};
+
+class {{dllapi}} {{classname}}::{{operationIdCamelCase}}Response : public Response
+{
+public:
+ virtual ~{{operationIdCamelCase}}Response() {}
+ {{#responses.0}}
+ void SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode) final;
+ {{/responses.0}}
+ bool FromJson(const TSharedPtr& JsonObject) final;
+
+ {{#returnType}}{{{returnType}}} Content;{{/returnType}}
+};
+
+{{/operation}}
+{{/operations}}
+{{#cppNamespaceDeclarations}}
+}
+{{/cppNamespaceDeclarations}}
diff --git a/modules/openapi-generator/src/main/resources/cpp-ue4/api-operations-source.mustache b/modules/openapi-generator/src/main/resources/cpp-ue4/api-operations-source.mustache
new file mode 100644
index 000000000000..894e76bc7b7b
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/cpp-ue4/api-operations-source.mustache
@@ -0,0 +1,286 @@
+{{>licenseInfo}}
+#include "{{classname}}Operations.h"
+
+#include "{{unrealModuleName}}Module.h"
+#include "{{modelNamePrefix}}Helpers.h"
+
+#include "Dom/JsonObject.h"
+#include "Templates/SharedPointer.h"
+#include "HttpModule.h"
+#include "PlatformHttp.h"
+
+{{#cppNamespaceDeclarations}}
+namespace {{this}}
+{
+{{/cppNamespaceDeclarations}}
+{{#operations}}{{#operation}}
+{{#allParams}}
+{{#isEnum}}
+inline FString ToString(const {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}}& Value)
+{
+ {{#allowableValues}}
+ switch (Value)
+ {
+ {{#enumVars}}
+ case {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}}::{{name}}:
+ return TEXT({{{value}}});
+ {{/enumVars}}
+ }
+ {{/allowableValues}}
+
+ UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Invalid {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}} Value (%d)"), (int)Value);
+ return TEXT("");
+}
+
+inline FStringFormatArg ToStringFormatArg(const {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}}& Value)
+{
+ return FStringFormatArg(ToString(Value));
+}
+
+inline void WriteJsonValue(JsonWriter& Writer, const {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}}& Value)
+{
+ WriteJsonValue(Writer, ToString(Value));
+}
+
+inline bool TryGetJsonValue(const TSharedPtr& JsonValue, {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}}& Value)
+{
+ {{#allowableValues}}
+ FString TmpValue;
+ if (JsonValue->TryGetString(TmpValue))
+ {
+ static TMap StringToEnum = { {{#enumVars}}
+ { TEXT({{{value}}}), {{classname}}::{{operationIdCamelCase}}Request::{{{enumName}}}::{{name}} },{{/enumVars}} };
+
+ const auto Found = StringToEnum.Find(TmpValue);
+ if(Found)
+ {
+ Value = *Found;
+ return true;
+ }
+ }
+ {{/allowableValues}}
+ return false;
+}
+
+{{/isEnum}}
+{{/allParams}}
+FString {{classname}}::{{operationIdCamelCase}}Request::ComputePath() const
+{
+ {{^pathParams.0}}
+ FString Path(TEXT("{{{path}}}"));
+ {{/pathParams.0}}
+ {{#pathParams.0}}
+ TMap PathParams = { {{#pathParams}}
+ { TEXT("{{baseName}}"), ToStringFormatArg({{paramName}}) }{{#hasMore}},{{/hasMore}}{{/pathParams}} };
+
+ FString Path = FString::Format(TEXT("{{{path}}}"), PathParams);
+
+ {{/pathParams.0}}
+ {{#queryParams.0}}
+ TArray QueryParams;
+ {{#queryParams}}
+ {{#required}}
+ {{^collectionFormat}}
+ QueryParams.Add(FString(TEXT("{{baseName}}=")) + ToUrlString({{paramName}}));
+ {{/collectionFormat}}
+ {{#collectionFormat}}
+ QueryParams.Add(FString(TEXT("{{baseName}}=")) + CollectionToUrlString_{{collectionFormat}}({{paramName}}, TEXT("{{baseName}}")));
+ {{/collectionFormat}}
+ {{/required}}
+ {{^required}}
+ {{^collectionFormat}}
+ if({{paramName}}.IsSet())
+ {
+ QueryParams.Add(FString(TEXT("{{baseName}}=")) + ToUrlString({{paramName}}.GetValue()));
+ }
+ {{/collectionFormat}}
+ {{#collectionFormat}}
+ if({{paramName}}.IsSet())
+ {
+ QueryParams.Add(FString(TEXT("{{baseName}}=")) + CollectionToUrlString_{{collectionFormat}}({{paramName}}.GetValue(), TEXT("{{baseName}}")));
+ }
+ {{/collectionFormat}}
+ {{/required}}
+ {{/queryParams}}
+ Path += TCHAR('?');
+ Path += FString::Join(QueryParams, TEXT("&"));
+
+ {{/queryParams.0}}
+ return Path;
+}
+
+void {{classname}}::{{operationIdCamelCase}}Request::SetupHttpRequest(const TSharedRef& HttpRequest) const
+{
+ static const TArray Consumes = { {{#consumes}}TEXT("{{{mediaType}}}"){{#hasMore}}, {{/hasMore}}{{/consumes}} };
+ //static const TArray Produces = { {{#produces}}TEXT("{{{mediaType}}}"){{#hasMore}}, {{/hasMore}}{{/produces}} };
+
+ HttpRequest->SetVerb(TEXT("{{httpMethod}}"));
+ {{#headerParams.0}}
+
+ // Header parameters
+ {{#headerParams}}
+ {{#required}}
+ HttpRequest->SetHeader(TEXT("{{baseName}}"), {{paramName}});
+ {{/required}}
+ {{^required}}
+ if ({{paramName}}.IsSet())
+ {
+ HttpRequest->SetHeader(TEXT("{{baseName}}"), {{paramName}}.GetValue());
+ }
+ {{/required}}
+ {{/headerParams}}
+ {{/headerParams.0}}
+
+ // Default to Json Body request
+ if (Consumes.Num() == 0 || Consumes.Contains(TEXT("application/json")))
+ {
+ {{#bodyParams.0}}
+ // Body parameters
+ FString JsonBody;
+ JsonWriter Writer = TJsonWriterFactory<>::Create(&JsonBody);
+
+ Writer->WriteObjectStart();
+ {{#bodyParams}}
+ {{#required}}
+ Writer->WriteIdentifierPrefix(TEXT("{{baseName}}")); WriteJsonValue(Writer, {{paramName}});
+ {{/required}}
+ {{^required}}
+ if ({{paramName}}.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("{{baseName}}")); WriteJsonValue(Writer, {{paramName}}.GetValue());
+ }
+ {{/required}}
+ {{/bodyParams}}
+ Writer->WriteObjectEnd();
+ Writer->Close();
+
+ HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json; charset=utf-8"));
+ HttpRequest->SetContentAsString(JsonBody);
+ {{/bodyParams.0}}
+ {{#formParams.0}}
+ {{#formParams}}
+ UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Form parameter ({{baseName}}) was ignored, cannot be used in JsonBody"));
+ {{/formParams}}
+ {{/formParams.0}}
+ }
+ else if (Consumes.Contains(TEXT("multipart/form-data")))
+ {
+ {{#formParams.0}}
+ HttpMultipartFormData FormData;
+ {{#formParams}}
+ {{#isContainer}}
+ UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Form parameter ({{baseName}}) was ignored, Collections are not supported in multipart form"));
+ {{/isContainer}}
+ {{^isContainer}}
+ {{#required}}
+ {{#isFile}}
+ FormData.AddFilePart(TEXT("{{baseName}}"), {{paramName}});
+ {{/isFile}}
+ {{#isBinary}}
+ FormData.AddBinaryPart(TEXT("{{baseName}}"), {{paramName}});
+ {{/isBinary}}
+ {{#isBinary}}
+ {{^isFile}}
+ FormData.AddStringPart(TEXT("{{baseName}}"), *ToUrlString({{paramName}}));
+ {{/isFile}}
+ {{/isBinary}}
+ {{/required}}
+ {{^required}}
+ if({{paramName}}.IsSet())
+ {
+ {{#isFile}}
+ FormData.AddFilePart(TEXT("{{baseName}}"), {{paramName}}.GetValue());
+ {{/isFile}}
+ {{#isBinary}}
+ FormData.AddBinaryPart(TEXT("{{baseName}}"), {{paramName}}.GetValue());
+ {{/isBinary}}
+ {{^isBinary}}
+ {{^isFile}}
+ FormData.AddStringPart(TEXT("{{baseName}}"), *ToUrlString({{paramName}}.GetValue()));
+ {{/isFile}}
+ {{/isBinary}}
+ }
+ {{/required}}
+ {{/isContainer}}
+ {{/formParams}}
+
+ FormData.SetupHttpRequest(HttpRequest);
+ {{/formParams.0}}
+ {{#bodyParams.0}}
+ {{#bodyParams}}
+ UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Body parameter ({{baseName}}) was ignored, not supported in multipart form"));
+ {{/bodyParams}}
+ {{/bodyParams.0}}
+ }
+ else if (Consumes.Contains(TEXT("application/x-www-form-urlencoded")))
+ {
+ {{#formParams.0}}
+ TArray FormParams;
+ {{#formParams}}
+ {{#isContainer}}
+ UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Form parameter ({{baseName}}) was ignored, Collections are not supported in urlencoded requests"));
+ {{/isContainer}}
+ {{#isFile}}
+ UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Form parameter ({{baseName}}) was ignored, Files are not supported in urlencoded requests"));
+ {{/isFile}}
+ {{^isFile}}
+ {{^isContainer}}
+ {{#required}}
+ FormParams.Add(FString(TEXT("{{baseName}}=")) + ToUrlString({{paramName}}));
+ {{/required}}
+ {{^required}}
+ if({{paramName}}.IsSet())
+ {
+ FormParams.Add(FString(TEXT("{{baseName}}=")) + ToUrlString({{paramName}}.GetValue()));
+ }
+ {{/required}}
+ {{/isContainer}}
+ {{/isFile}}
+ {{/formParams}}
+
+ HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/x-www-form-urlencoded; charset=utf-8"));
+ HttpRequest->SetContentAsString(FString::Join(FormParams, TEXT("&")));
+ {{/formParams.0}}
+ {{#bodyParams.0}}
+ {{#bodyParams}}
+ UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Body parameter ({{baseName}}) was ignored, not supported in urlencoded requests"));
+ {{/bodyParams}}
+ {{/bodyParams.0}}
+ }
+ else
+ {
+ UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Request ContentType not supported (%s)"), *FString::Join(Consumes, TEXT(",")));
+ }
+}
+
+{{#responses.0}}
+void {{classname}}::{{operationIdCamelCase}}Response::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
+{
+ Response::SetHttpResponseCode(InHttpResponseCode);
+ switch ((int)InHttpResponseCode)
+ {
+ {{#responses}}
+ case {{code}}:
+ {{#isDefault}}
+ default:
+ {{/isDefault}}
+ SetResponseString(TEXT("{{message}}"));
+ break;
+ {{/responses}}
+ }
+}
+{{/responses.0}}
+
+bool {{classname}}::{{operationIdCamelCase}}Response::FromJson(const TSharedPtr& JsonValue)
+{
+ {{#returnType}}
+ return TryGetJsonValue(JsonValue, Content);
+ {{/returnType}}
+ {{^returnType}}
+ return true;
+ {{/returnType}}
+}
+{{/operation}}{{/operations}}
+{{#cppNamespaceDeclarations}}
+}
+{{/cppNamespaceDeclarations}}
diff --git a/modules/openapi-generator/src/main/resources/cpp-ue4/api-source.mustache b/modules/openapi-generator/src/main/resources/cpp-ue4/api-source.mustache
new file mode 100644
index 000000000000..c1ca56649e5d
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/cpp-ue4/api-source.mustache
@@ -0,0 +1,120 @@
+{{>licenseInfo}}
+#include "{{classname}}.h"
+
+#include "{{classname}}Operations.h"
+#include "{{unrealModuleName}}Module.h"
+
+#include "HttpModule.h"
+#include "Serialization/JsonSerializer.h"
+
+{{#cppNamespaceDeclarations}}
+namespace {{this}}
+{
+{{/cppNamespaceDeclarations}}
+
+{{classname}}::{{classname}}()
+: Url(TEXT("{{basePath}}"))
+{
+}
+
+{{classname}}::~{{classname}}() {}
+
+void {{classname}}::SetURL(const FString& InUrl)
+{
+ Url = InUrl;
+}
+
+void {{classname}}::AddHeaderParam(const FString& Key, const FString& Value)
+{
+ AdditionalHeaderParams.Add(Key, Value);
+}
+
+void {{classname}}::ClearHeaderParams()
+{
+ AdditionalHeaderParams.Reset();
+}
+
+bool {{classname}}::IsValid() const
+{
+ if (Url.IsEmpty())
+ {
+ UE_LOG(Log{{unrealModuleName}}, Error, TEXT("{{classname}}: Endpoint Url is not set, request cannot be performed"));
+ return false;
+ }
+
+ return true;
+}
+
+void {{classname}}::HandleResponse(FHttpResponsePtr HttpResponse, bool bSucceeded, Response& InOutResponse) const
+{
+ InOutResponse.SetHttpResponse(HttpResponse);
+ InOutResponse.SetSuccessful(bSucceeded);
+
+ if (bSucceeded && HttpResponse.IsValid())
+ {
+ InOutResponse.SetHttpResponseCode((EHttpResponseCodes::Type)HttpResponse->GetResponseCode());
+ FString ContentType = HttpResponse->GetContentType();
+ FString Content;
+
+ if (ContentType == TEXT("application/json"))
+ {
+ Content = HttpResponse->GetContentAsString();
+
+ TSharedPtr JsonValue;
+ auto Reader = TJsonReaderFactory<>::Create(Content);
+
+ if (FJsonSerializer::Deserialize(Reader, JsonValue) && JsonValue.IsValid())
+ {
+ if (InOutResponse.FromJson(JsonValue))
+ return; // Successfully parsed
+ }
+ }
+ else if(ContentType == TEXT("text/plain"))
+ {
+ Content = HttpResponse->GetContentAsString();
+ InOutResponse.SetResponseString(Content);
+ return; // Successfully parsed
+ }
+
+ // Report the parse error but do not mark the request as unsuccessful. Data could be partial or malformed, but the request succeeded.
+ UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Failed to deserialize Http response content (type:%s):\n%s"), *ContentType , *Content);
+ return;
+ }
+
+ // By default, assume we failed to establish connection
+ InOutResponse.SetHttpResponseCode(EHttpResponseCodes::RequestTimeout);
+}
+
+{{#operations}}
+{{#operation}}
+bool {{classname}}::{{operationIdCamelCase}}(const {{operationIdCamelCase}}Request& Request, const F{{operationIdCamelCase}}Delegate& Delegate /*= F{{operationIdCamelCase}}Delegate()*/) const
+{
+ if (!IsValid())
+ return false;
+
+ TSharedRef HttpRequest = FHttpModule::Get().CreateRequest();
+ HttpRequest->SetURL(*(Url + Request.ComputePath()));
+
+ for(const auto& It : AdditionalHeaderParams)
+ {
+ HttpRequest->SetHeader(It.Key, It.Value);
+ }
+
+ Request.SetupHttpRequest(HttpRequest);
+
+ HttpRequest->OnProcessRequestComplete().BindRaw(this, &{{classname}}::On{{operationIdCamelCase}}Response, Delegate);
+ return HttpRequest->ProcessRequest();
+}
+
+void {{classname}}::On{{operationIdCamelCase}}Response(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, F{{operationIdCamelCase}}Delegate Delegate) const
+{
+ {{operationIdCamelCase}}Response Response;
+ HandleResponse(HttpResponse, bSucceeded, Response);
+ Delegate.ExecuteIfBound(Response);
+}
+
+{{/operation}}
+{{/operations}}
+{{#cppNamespaceDeclarations}}
+}
+{{/cppNamespaceDeclarations}}
diff --git a/modules/openapi-generator/src/main/resources/cpp-ue4/helpers-header.mustache b/modules/openapi-generator/src/main/resources/cpp-ue4/helpers-header.mustache
new file mode 100644
index 000000000000..adbff0c0e889
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/cpp-ue4/helpers-header.mustache
@@ -0,0 +1,405 @@
+{{>licenseInfo}}
+#pragma once
+
+#include "{{modelNamePrefix}}BaseModel.h"
+
+#include "Serialization/JsonSerializer.h"
+#include "Dom/JsonObject.h"
+#include "Misc/Base64.h"
+
+class IHttpRequest;
+
+{{#cppNamespaceDeclarations}}
+namespace {{this}}
+{
+{{/cppNamespaceDeclarations}}
+
+typedef TSharedRef> JsonWriter;
+
+//////////////////////////////////////////////////////////////////////////
+
+class {{dllapi}} HttpFileInput
+{
+public:
+ HttpFileInput(const TCHAR* InFilePath);
+ HttpFileInput(const FString& InFilePath);
+
+ // This will automatically set the content type if not already set
+ void SetFilePath(const TCHAR* InFilePath);
+ void SetFilePath(const FString& InFilePath);
+
+ // Optional if it can be deduced from the FilePath
+ void SetContentType(const TCHAR* ContentType);
+
+ HttpFileInput& operator=(const HttpFileInput& Other) = default;
+ HttpFileInput& operator=(const FString& InFilePath) { SetFilePath(*InFilePath); return*this; }
+ HttpFileInput& operator=(const TCHAR* InFilePath) { SetFilePath(InFilePath); return*this; }
+
+ const FString& GetFilePath() const { return FilePath; }
+ const FString& GetContentType() const { return ContentType; }
+
+ // Returns the filename with extension
+ FString GetFilename() const;
+
+private:
+ FString FilePath;
+ FString ContentType;
+};
+
+//////////////////////////////////////////////////////////////////////////
+
+class HttpMultipartFormData
+{
+public:
+ void SetBoundary(const TCHAR* InBoundary);
+ void SetupHttpRequest(const TSharedRef& HttpRequest);
+
+ void AddStringPart(const TCHAR* Name, const TCHAR* Data);
+ void AddJsonPart(const TCHAR* Name, const FString& JsonString);
+ void AddBinaryPart(const TCHAR* Name, const TArray& ByteArray);
+ void AddFilePart(const TCHAR* Name, const HttpFileInput& File);
+
+private:
+ void AppendString(const TCHAR* Str);
+ const FString& GetBoundary() const;
+
+ mutable FString Boundary;
+ TArray FormData;
+
+ static const TCHAR* Delimiter;
+ static const TCHAR* Newline;
+};
+
+//////////////////////////////////////////////////////////////////////////
+
+// Decodes Base64Url encoded strings, see https://en.wikipedia.org/wiki/Base64#Variants_summary_table
+template
+bool Base64UrlDecode(const FString& Base64String, T& Value)
+{
+ FString TmpCopy(Base64String);
+ TmpCopy.ReplaceInline(TEXT("-"), TEXT("+"));
+ TmpCopy.ReplaceInline(TEXT("_"), TEXT("/"));
+
+ return FBase64::Decode(TmpCopy, Value);
+}
+
+// Encodes strings in Base64Url, see https://en.wikipedia.org/wiki/Base64#Variants_summary_table
+template
+FString Base64UrlEncode(const T& Value)
+{
+ FString Base64String = FBase64::Encode(Value);
+ Base64String.ReplaceInline(TEXT("+"), TEXT("-"));
+ Base64String.ReplaceInline(TEXT("/"), TEXT("_"));
+ return Base64String;
+}
+
+template
+inline FStringFormatArg ToStringFormatArg(const T& Value)
+{
+ return FStringFormatArg(Value);
+}
+
+inline FStringFormatArg ToStringFormatArg(const FDateTime& Value)
+{
+ return FStringFormatArg(Value.ToIso8601());
+}
+
+inline FStringFormatArg ToStringFormatArg(const TArray& Value)
+{
+ return FStringFormatArg(Base64UrlEncode(Value));
+}
+
+template::value, int>::type = 0>
+inline FString ToString(const T& Value)
+{
+ return FString::Format(TEXT("{0}"), { ToStringFormatArg(Value) });
+}
+
+inline FString ToString(const FString& Value)
+{
+ return Value;
+}
+
+inline FString ToString(const TArray& Value)
+{
+ return Base64UrlEncode(Value);
+}
+
+inline FString ToString(const Model& Value)
+{
+ FString String;
+ JsonWriter Writer = TJsonWriterFactory<>::Create(&String);
+ Value.WriteJson(Writer);
+ Writer->Close();
+ return String;
+}
+
+template
+inline FString ToUrlString(const T& Value)
+{
+ return FPlatformHttp::UrlEncode(ToString(Value));
+}
+
+template
+inline FString CollectionToUrlString(const TArray& Collection, const TCHAR* Separator)
+{
+ FString Output;
+ if(Collection.Num() == 0)
+ return Output;
+
+ Output += ToUrlString(Collection[0]);
+ for(int i = 1; i < Collection.Num(); i++)
+ {
+ Output += FString::Format(TEXT("{0}{1}"), { Separator, *ToUrlString(Collection[i]) });
+ }
+ return Output;
+}
+
+template
+inline FString CollectionToUrlString_csv(const TArray& Collection, const TCHAR* BaseName)
+{
+ return CollectionToUrlString(Collection, TEXT(","));
+}
+
+template
+inline FString CollectionToUrlString_ssv(const TArray& Collection, const TCHAR* BaseName)
+{
+ return CollectionToUrlString(Collection, TEXT(" "));
+}
+
+template
+inline FString CollectionToUrlString_tsv(const TArray& Collection, const TCHAR* BaseName)
+{
+ return CollectionToUrlString(Collection, TEXT("\t"));
+}
+
+template
+inline FString CollectionToUrlString_pipes(const TArray& Collection, const TCHAR* BaseName)
+{
+ return CollectionToUrlString(Collection, TEXT("|"));
+}
+
+template
+inline FString CollectionToUrlString_multi(const TArray& Collection, const TCHAR* BaseName)
+{
+ FString Output;
+ if(Collection.Num() == 0)
+ return Output;
+
+ Output += FString::Format(TEXT("{0}={1}"), { FStringFormatArg(BaseName), ToUrlString(Collection[0]) });
+ for(int i = 1; i < Collection.Num(); i++)
+ {
+ Output += FString::Format(TEXT("&{0}={1}"), { FStringFormatArg(BaseName), ToUrlString(Collection[i]) });
+ }
+ return Output;
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+template::value, int>::type = 0>
+inline void WriteJsonValue(JsonWriter& Writer, const T& Value)
+{
+ Writer->WriteValue(Value);
+}
+
+inline void WriteJsonValue(JsonWriter& Writer, const FDateTime& Value)
+{
+ Writer->WriteValue(Value.ToIso8601());
+}
+
+inline void WriteJsonValue(JsonWriter& Writer, const Model& Value)
+{
+ Value.WriteJson(Writer);
+}
+
+template
+inline void WriteJsonValue(JsonWriter& Writer, const TArray& Value)
+{
+ Writer->WriteArrayStart();
+ for (const auto& Element : Value)
+ {
+ WriteJsonValue(Writer, Element);
+ }
+ Writer->WriteArrayEnd();
+}
+
+template
+inline void WriteJsonValue(JsonWriter& Writer, const TMap& Value)
+{
+ Writer->WriteObjectStart();
+ for (const auto& It : Value)
+ {
+ Writer->WriteIdentifierPrefix(It.Key);
+ WriteJsonValue(Writer, It.Value);
+ }
+ Writer->WriteObjectEnd();
+}
+
+inline void WriteJsonValue(JsonWriter& Writer, const TSharedPtr& Value)
+{
+ if (Value.IsValid())
+ {
+ FJsonSerializer::Serialize(Value.ToSharedRef(), Writer, false);
+ }
+ else
+ {
+ Writer->WriteObjectStart();
+ Writer->WriteObjectEnd();
+ }
+}
+
+inline void WriteJsonValue(JsonWriter& Writer, const TArray& Value)
+{
+ Writer->WriteValue(ToString(Value));
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+template
+inline bool TryGetJsonValue(const TSharedPtr& JsonObject, const FString& Key, T& Value)
+{
+ const TSharedPtr JsonValue = JsonObject->TryGetField(Key);
+ if (JsonValue.IsValid() && !JsonValue->IsNull())
+ {
+ return TryGetJsonValue(JsonValue, Value);
+ }
+ return false;
+}
+
+template
+inline bool TryGetJsonValue(const TSharedPtr& JsonObject, const FString& Key, TOptional& OptionalValue)
+{
+ if(JsonObject->HasField(Key))
+ {
+ T Value;
+ if (TryGetJsonValue(JsonObject, Key, Value))
+ {
+ OptionalValue = Value;
+ return true;
+ }
+ else
+ return false;
+ }
+ return true; // Absence of optional value is not a parsing error
+}
+
+inline bool TryGetJsonValue(const TSharedPtr& JsonValue, FString& Value)
+{
+ FString TmpValue;
+ if (JsonValue->TryGetString(TmpValue))
+ {
+ Value = TmpValue;
+ return true;
+ }
+ else
+ return false;
+}
+
+inline bool TryGetJsonValue(const TSharedPtr& JsonValue, FDateTime& Value)
+{
+ FString TmpValue;
+ if (JsonValue->TryGetString(TmpValue))
+ return FDateTime::Parse(TmpValue, Value);
+ else
+ return false;
+}
+
+inline bool TryGetJsonValue(const TSharedPtr& JsonValue, bool& Value)
+{
+ bool TmpValue;
+ if (JsonValue->TryGetBool(TmpValue))
+ {
+ Value = TmpValue;
+ return true;
+ }
+ else
+ return false;
+}
+
+template::value, int>::type = 0>
+inline bool TryGetJsonValue(const TSharedPtr& JsonValue, T& Value)
+{
+ T TmpValue;
+ if (JsonValue->TryGetNumber(TmpValue))
+ {
+ Value = TmpValue;
+ return true;
+ }
+ else
+ return false;
+}
+
+inline bool TryGetJsonValue(const TSharedPtr& JsonValue, Model& Value)
+{
+ const TSharedPtr* Object;
+ if (JsonValue->TryGetObject(Object))
+ return Value.FromJson(*Object);
+ else
+ return false;
+}
+
+template
+inline bool TryGetJsonValue(const TSharedPtr& JsonValue, TArray& ArrayValue)
+{
+ const TArray>* JsonArray;
+ if (JsonValue->TryGetArray(JsonArray))
+ {
+ bool ParseSuccess = true;
+ const int32 Count = JsonArray->Num();
+ ArrayValue.Reset(Count);
+ for (int i = 0; i < Count; i++)
+ {
+ T TmpValue;
+ ParseSuccess &= TryGetJsonValue((*JsonArray)[i], TmpValue);
+ ArrayValue.Emplace(MoveTemp(TmpValue));
+ }
+ return ParseSuccess;
+ }
+ return false;
+}
+
+template
+inline bool TryGetJsonValue(const TSharedPtr& JsonValue, TMap& MapValue)
+{
+ const TSharedPtr* Object;
+ if (JsonValue->TryGetObject(Object))
+ {
+ MapValue.Reset();
+ bool ParseSuccess = true;
+ for (const auto& It : (*Object)->Values)
+ {
+ T TmpValue;
+ ParseSuccess &= TryGetJsonValue(It.Value, TmpValue);
+ MapValue.Emplace(It.Key, MoveTemp(TmpValue));
+ }
+ return ParseSuccess;
+ }
+ return false;
+}
+
+inline bool TryGetJsonValue(const TSharedPtr& JsonValue, TSharedPtr& JsonObjectValue)
+{
+ const TSharedPtr* Object;
+ if (JsonValue->TryGetObject(Object))
+ {
+ JsonObjectValue = *Object;
+ return true;
+ }
+ return false;
+}
+
+inline bool TryGetJsonValue(const TSharedPtr& JsonValue, TArray& Value)
+{
+ FString TmpValue;
+ if (JsonValue->TryGetString(TmpValue))
+ {
+ Base64UrlDecode(TmpValue, Value);
+ return true;
+ }
+ else
+ return false;
+}
+
+{{#cppNamespaceDeclarations}}
+}
+{{/cppNamespaceDeclarations}}
diff --git a/modules/openapi-generator/src/main/resources/cpp-ue4/helpers-source.mustache b/modules/openapi-generator/src/main/resources/cpp-ue4/helpers-source.mustache
new file mode 100644
index 000000000000..1ae8bad54c68
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/cpp-ue4/helpers-source.mustache
@@ -0,0 +1,187 @@
+{{>licenseInfo}}
+#include "{{modelNamePrefix}}Helpers.h"
+
+#include "{{unrealModuleName}}Module.h"
+
+#include "Interfaces/IHttpRequest.h"
+#include "PlatformHttp.h"
+#include "Misc/FileHelper.h"
+
+{{#cppNamespaceDeclarations}}
+namespace {{this}}
+{
+{{/cppNamespaceDeclarations}}
+
+HttpFileInput::HttpFileInput(const TCHAR* InFilePath)
+{
+ SetFilePath(InFilePath);
+}
+
+HttpFileInput::HttpFileInput(const FString& InFilePath)
+{
+ SetFilePath(InFilePath);
+}
+
+void HttpFileInput::SetFilePath(const TCHAR* InFilePath)
+{
+ FilePath = InFilePath;
+ if(ContentType.IsEmpty())
+ {
+ ContentType = FPlatformHttp::GetMimeType(InFilePath);
+ }
+}
+
+void HttpFileInput::SetFilePath(const FString& InFilePath)
+{
+ SetFilePath(*InFilePath);
+}
+
+void HttpFileInput::SetContentType(const TCHAR* InContentType)
+{
+ ContentType = InContentType;
+}
+
+FString HttpFileInput::GetFilename() const
+{
+ return FPaths::GetCleanFilename(FilePath);
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+const TCHAR* HttpMultipartFormData::Delimiter = TEXT("--");
+const TCHAR* HttpMultipartFormData::Newline = TEXT("\r\n");
+
+void HttpMultipartFormData::SetBoundary(const TCHAR* InBoundary)
+{
+ checkf(Boundary.IsEmpty(), TEXT("Boundary must be set before usage"));
+ Boundary = InBoundary;
+}
+
+const FString& HttpMultipartFormData::GetBoundary() const
+{
+ if (Boundary.IsEmpty())
+ {
+ // Generate a random boundary with enough entropy, should avoid occurences of the boundary in the data.
+ // Since the boundary is generated at every request, in case of failure, retries should succeed.
+ Boundary = FGuid::NewGuid().ToString(EGuidFormats::Short);
+ }
+
+ return Boundary;
+}
+
+void HttpMultipartFormData::SetupHttpRequest(const TSharedRef& HttpRequest)
+{
+ if(HttpRequest->GetVerb() != TEXT("POST"))
+ {
+ UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Expected POST verb when using multipart form data"));
+ }
+
+ // Append final boundary
+ AppendString(Delimiter);
+ AppendString(*GetBoundary());
+ AppendString(Delimiter);
+
+ HttpRequest->SetHeader("Content-Type", FString::Printf(TEXT("multipart/form-data; boundary=%s"), *GetBoundary()));
+ HttpRequest->SetContent(FormData);
+}
+
+void HttpMultipartFormData::AddStringPart(const TCHAR* Name, const TCHAR* Data)
+{
+ // Add boundary
+ AppendString(Delimiter);
+ AppendString(*GetBoundary());
+ AppendString(Newline);
+
+ // Add header
+ AppendString(*FString::Printf(TEXT("Content-Disposition: form-data; name = \"%s\""), Name));
+ AppendString(Newline);
+ AppendString(*FString::Printf(TEXT("Content-Type: text/plain; charset=utf-8")));
+ AppendString(Newline);
+
+ // Add header to body splitter
+ AppendString(Newline);
+
+ // Add Data
+ AppendString(Data);
+ AppendString(Newline);
+}
+
+void HttpMultipartFormData::AddJsonPart(const TCHAR* Name, const FString& JsonString)
+{
+ // Add boundary
+ AppendString(Delimiter);
+ AppendString(*GetBoundary());
+ AppendString(Newline);
+
+ // Add header
+ AppendString(*FString::Printf(TEXT("Content-Disposition: form-data; name=\"%s\""), Name));
+ AppendString(Newline);
+ AppendString(*FString::Printf(TEXT("Content-Type: application/json; charset=utf-8")));
+ AppendString(Newline);
+
+ // Add header to body splitter
+ AppendString(Newline);
+
+ // Add Data
+ AppendString(*JsonString);
+ AppendString(Newline);
+}
+
+void HttpMultipartFormData::AddBinaryPart(const TCHAR* Name, const TArray& ByteArray)
+{
+ // Add boundary
+ AppendString(Delimiter);
+ AppendString(*GetBoundary());
+ AppendString(Newline);
+
+ // Add header
+ AppendString(*FString::Printf(TEXT("Content-Disposition: form-data; name=\"%s\""), Name));
+ AppendString(Newline);
+ AppendString(*FString::Printf(TEXT("Content-Type: application/octet-stream")));
+ AppendString(Newline);
+
+ // Add header to body splitter
+ AppendString(Newline);
+
+ // Add Data
+ FormData.Append(ByteArray);
+ AppendString(Newline);
+}
+
+void HttpMultipartFormData::AddFilePart(const TCHAR* Name, const HttpFileInput& File)
+{
+ TArray FileContents;
+ if (!FFileHelper::LoadFileToArray(FileContents, *File.GetFilePath()))
+ {
+ UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Failed to load file (%s)"), *File.GetFilePath());
+ return;
+ }
+
+ // Add boundary
+ AppendString(Delimiter);
+ AppendString(*GetBoundary());
+ AppendString(Newline);
+
+ // Add header
+ AppendString(*FString::Printf(TEXT("Content-Disposition: form-data; name=\"%s\"; filename=\"%s\""), Name, *File.GetFilename()));
+ AppendString(Newline);
+ AppendString(*FString::Printf(TEXT("Content-Type: %s"), *File.GetContentType()));
+ AppendString(Newline);
+
+ // Add header to body splitter
+ AppendString(Newline);
+
+ // Add Data
+ FormData.Append(FileContents);
+ AppendString(Newline);
+}
+
+void HttpMultipartFormData::AppendString(const TCHAR* Str)
+{
+ FTCHARToUTF8 utf8Str(Str);
+ FormData.Append((uint8*)utf8Str.Get(), utf8Str.Length());
+}
+
+{{#cppNamespaceDeclarations}}
+}
+{{/cppNamespaceDeclarations}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/cpp-ue4/licenseInfo.mustache b/modules/openapi-generator/src/main/resources/cpp-ue4/licenseInfo.mustache
new file mode 100644
index 000000000000..147bb985790b
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/cpp-ue4/licenseInfo.mustache
@@ -0,0 +1,11 @@
+/**
+ * {{{appName}}}
+ * {{{appDescription}}}
+ *
+ * {{#version}}OpenAPI spec version: {{{version}}}{{/version}}
+ * {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}}
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator
+ * https://github.com/OpenAPITools/openapi-generator
+ * Do not edit the class manually.
+ */
diff --git a/modules/openapi-generator/src/main/resources/cpp-ue4/model-base-header.mustache b/modules/openapi-generator/src/main/resources/cpp-ue4/model-base-header.mustache
new file mode 100644
index 000000000000..67280bde9890
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/cpp-ue4/model-base-header.mustache
@@ -0,0 +1,59 @@
+{{>licenseInfo}}
+#pragma once
+
+#include "Interfaces/IHttpRequest.h"
+#include "Interfaces/IHttpResponse.h"
+#include "Serialization/JsonWriter.h"
+#include "Dom/JsonObject.h"
+
+{{#cppNamespaceDeclarations}}
+namespace {{this}}
+{
+{{/cppNamespaceDeclarations}}
+
+typedef TSharedRef> JsonWriter;
+
+class {{dllapi}} Model
+{
+public:
+ virtual ~Model() {}
+ virtual void WriteJson(JsonWriter& Writer) const = 0;
+ virtual bool FromJson(const TSharedPtr& JsonObject) = 0;
+};
+
+class {{dllapi}} Request
+{
+public:
+ virtual ~Request() {}
+ virtual void SetupHttpRequest(const TSharedRef& HttpRequest) const = 0;
+ virtual FString ComputePath() const = 0;
+};
+
+class {{dllapi}} Response
+{
+public:
+ virtual ~Response() {}
+ virtual bool FromJson(const TSharedPtr& JsonObject) = 0;
+
+ void SetSuccessful(bool InSuccessful) { Successful = InSuccessful; }
+ bool IsSuccessful() const { return Successful; }
+
+ virtual void SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode);
+ EHttpResponseCodes::Type GetHttpResponseCode() const { return ResponseCode; }
+
+ void SetResponseString(const FString& InResponseString) { ResponseString = InResponseString; }
+ const FString& GetResponseString() const { return ResponseString; }
+
+ void SetHttpResponse(const FHttpResponsePtr& InHttpResponse) { HttpResponse = InHttpResponse; }
+ const FHttpResponsePtr& GetHttpResponse() const { return HttpResponse; }
+
+private:
+ bool Successful;
+ EHttpResponseCodes::Type ResponseCode;
+ FString ResponseString;
+ FHttpResponsePtr HttpResponse;
+};
+
+{{#cppNamespaceDeclarations}}
+}
+{{/cppNamespaceDeclarations}}
diff --git a/modules/openapi-generator/src/main/resources/cpp-ue4/model-base-source.mustache b/modules/openapi-generator/src/main/resources/cpp-ue4/model-base-source.mustache
new file mode 100644
index 000000000000..12decd77211d
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/cpp-ue4/model-base-source.mustache
@@ -0,0 +1,21 @@
+{{>licenseInfo}}
+#include "{{modelNamePrefix}}BaseModel.h"
+
+{{#cppNamespaceDeclarations}}
+namespace {{this}}
+{
+{{/cppNamespaceDeclarations}}
+
+void Response::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
+{
+ ResponseCode = InHttpResponseCode;
+ SetSuccessful(EHttpResponseCodes::IsOk(InHttpResponseCode));
+ if(InHttpResponseCode == EHttpResponseCodes::RequestTimeout)
+ {
+ SetResponseString(TEXT("Request Timeout"));
+ }
+}
+
+{{#cppNamespaceDeclarations}}
+}
+{{/cppNamespaceDeclarations}}
\ No newline at end of file
diff --git a/modules/openapi-generator/src/main/resources/cpp-ue4/model-header.mustache b/modules/openapi-generator/src/main/resources/cpp-ue4/model-header.mustache
new file mode 100644
index 000000000000..6af8c720f0e8
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/cpp-ue4/model-header.mustache
@@ -0,0 +1,51 @@
+{{>licenseInfo}}
+#pragma once
+
+#include "{{modelNamePrefix}}BaseModel.h"
+{{#imports}}{{{import}}}
+{{/imports}}
+
+{{#cppNamespaceDeclarations}}
+namespace {{this}}
+{
+{{/cppNamespaceDeclarations}}
+{{#models}}
+{{#model}}
+
+/*
+ * {{classname}}
+ *
+ * {{description}}
+ */
+class {{dllapi}} {{classname}} : public Model
+{
+public:
+ virtual ~{{classname}}() {}
+ bool FromJson(const TSharedPtr& JsonObject) final;
+ void WriteJson(JsonWriter& Writer) const final;
+
+ {{#vars}}
+ {{#isEnum}}
+ {{#allowableValues}}
+ enum class {{{enumName}}}
+ {
+ {{#enumVars}}
+ {{name}},
+ {{/enumVars}}
+ };
+ {{/allowableValues}}
+ {{#description}}/* {{{description}}} */
+ {{/description}}{{^required}}TOptional<{{/required}}{{{datatypeWithEnum}}}{{^required}}>{{/required}} {{name}}{{#required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{/required}};
+ {{/isEnum}}
+ {{^isEnum}}
+ {{#description}}/* {{{description}}} */
+ {{/description}}{{^required}}TOptional<{{/required}}{{{datatype}}}{{^required}}>{{/required}} {{name}}{{#required}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{/required}};
+ {{/isEnum}}
+ {{/vars}}
+};
+
+{{/model}}
+{{/models}}
+{{#cppNamespaceDeclarations}}
+}
+{{/cppNamespaceDeclarations}}
diff --git a/modules/openapi-generator/src/main/resources/cpp-ue4/model-source.mustache b/modules/openapi-generator/src/main/resources/cpp-ue4/model-source.mustache
new file mode 100644
index 000000000000..4850fb9859ce
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/cpp-ue4/model-source.mustache
@@ -0,0 +1,98 @@
+{{>licenseInfo}}
+#include "{{classname}}.h"
+
+#include "{{unrealModuleName}}Module.h"
+#include "{{modelNamePrefix}}Helpers.h"
+
+#include "Templates/SharedPointer.h"
+
+{{#cppNamespaceDeclarations}}
+namespace {{this}}
+{
+{{/cppNamespaceDeclarations}}
+{{#models}}{{#model}}
+{{#hasEnums}}
+{{#vars}}
+{{#isEnum}}
+inline FString ToString(const {{classname}}::{{{enumName}}}& Value)
+{
+ {{#allowableValues}}
+ switch (Value)
+ {
+ {{#enumVars}}
+ case {{classname}}::{{{enumName}}}::{{name}}:
+ return TEXT({{{value}}});
+ {{/enumVars}}
+ }
+ {{/allowableValues}}
+
+ UE_LOG(Log{{unrealModuleName}}, Error, TEXT("Invalid {{classname}}::{{{enumName}}} Value (%d)"), (int)Value);
+ return TEXT("");
+}
+
+inline FStringFormatArg ToStringFormatArg(const {{classname}}::{{{enumName}}}& Value)
+{
+ return FStringFormatArg(ToString(Value));
+}
+
+inline void WriteJsonValue(JsonWriter& Writer, const {{classname}}::{{{enumName}}}& Value)
+{
+ WriteJsonValue(Writer, ToString(Value));
+}
+
+inline bool TryGetJsonValue(const TSharedPtr& JsonValue, {{classname}}::{{{enumName}}}& Value)
+{
+ FString TmpValue;
+ if (JsonValue->TryGetString(TmpValue))
+ {
+ static TMap StringToEnum = { {{#enumVars}}
+ { TEXT({{{value}}}), {{classname}}::{{{enumName}}}::{{name}} },{{/enumVars}} };
+
+ const auto Found = StringToEnum.Find(TmpValue);
+ if(Found)
+ {
+ Value = *Found;
+ return true;
+ }
+ }
+ return false;
+}
+
+{{/isEnum}}
+{{/vars}}
+{{/hasEnums}}
+void {{classname}}::WriteJson(JsonWriter& Writer) const
+{
+ {{#parent}}
+ #error inheritance not handled right now
+ {{/parent}}
+ Writer->WriteObjectStart();
+ {{#vars}}
+ {{#required}}
+ Writer->WriteIdentifierPrefix(TEXT("{{baseName}}")); WriteJsonValue(Writer, {{name}});
+ {{/required}}
+ {{^required}}
+ if ({{name}}.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("{{baseName}}")); WriteJsonValue(Writer, {{name}}.GetValue());
+ }
+ {{/required}}
+ {{/vars}}
+ Writer->WriteObjectEnd();
+}
+
+bool {{classname}}::FromJson(const TSharedPtr& JsonObject)
+{
+ bool ParseSuccess = true;
+
+ {{#vars}}
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("{{baseName}}"), {{name}});
+ {{/vars}}
+
+ return ParseSuccess;
+}
+{{/model}}
+{{/models}}
+{{#cppNamespaceDeclarations}}
+}
+{{/cppNamespaceDeclarations}}
diff --git a/modules/openapi-generator/src/main/resources/cpp-ue4/module-header.mustache b/modules/openapi-generator/src/main/resources/cpp-ue4/module-header.mustache
new file mode 100644
index 000000000000..f27de891f9ff
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/cpp-ue4/module-header.mustache
@@ -0,0 +1,15 @@
+{{>licenseInfo}}
+#pragma once
+
+#include "Modules/ModuleInterface.h"
+#include "Modules/ModuleManager.h"
+#include "Logging/LogMacros.h"
+
+DECLARE_LOG_CATEGORY_EXTERN(Log{{unrealModuleName}}, Log, All);
+
+class {{dllapi}} {{unrealModuleName}}Module : public IModuleInterface
+{
+public:
+ void StartupModule() final;
+ void ShutdownModule() final;
+};
diff --git a/modules/openapi-generator/src/main/resources/cpp-ue4/module-source.mustache b/modules/openapi-generator/src/main/resources/cpp-ue4/module-source.mustache
new file mode 100644
index 000000000000..676633ea0d9f
--- /dev/null
+++ b/modules/openapi-generator/src/main/resources/cpp-ue4/module-source.mustache
@@ -0,0 +1,14 @@
+{{>licenseInfo}}
+#include "{{unrealModuleName}}Module.h"
+
+IMPLEMENT_MODULE({{unrealModuleName}}Module, {{unrealModuleName}});
+DEFINE_LOG_CATEGORY(Log{{unrealModuleName}});
+
+void {{unrealModuleName}}Module::StartupModule()
+{
+}
+
+void {{unrealModuleName}}Module::ShutdownModule()
+{
+}
+
diff --git a/samples/client/petstore/cpp-ue4/.openapi-generator-ignore b/samples/client/petstore/cpp-ue4/.openapi-generator-ignore
new file mode 100644
index 000000000000..7484ee590a38
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/.openapi-generator-ignore
@@ -0,0 +1,23 @@
+# OpenAPI Generator Ignore
+# Generated by openapi-generator https://github.com/openapitools/openapi-generator
+
+# 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 OpenAPI Generator 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/cpp-ue4/.openapi-generator/VERSION b/samples/client/petstore/cpp-ue4/.openapi-generator/VERSION
new file mode 100644
index 000000000000..d99e7162d01f
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/.openapi-generator/VERSION
@@ -0,0 +1 @@
+5.0.0-SNAPSHOT
\ No newline at end of file
diff --git a/samples/client/petstore/cpp-ue4/OpenAPI.Build.cs b/samples/client/petstore/cpp-ue4/OpenAPI.Build.cs
new file mode 100644
index 000000000000..48294bae4e42
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/OpenAPI.Build.cs
@@ -0,0 +1,30 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator
+ * https://github.com/OpenAPITools/openapi-generator
+ * Do not edit the class manually.
+ */
+
+using System;
+using System.IO;
+using UnrealBuildTool;
+
+public class OpenAPI : ModuleRules
+{
+ public OpenAPI(ReadOnlyTargetRules Target) : base(Target)
+ {
+ PublicDependencyModuleNames.AddRange(
+ new string[]
+ {
+ "Core",
+ "Http",
+ "Json",
+ }
+ );
+ }
+}
\ No newline at end of file
diff --git a/samples/client/petstore/cpp-ue4/OpenAPIApiResponse.cpp b/samples/client/petstore/cpp-ue4/OpenAPIApiResponse.cpp
new file mode 100644
index 000000000000..542540959896
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/OpenAPIApiResponse.cpp
@@ -0,0 +1,51 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator
+ * https://github.com/OpenAPITools/openapi-generator
+ * Do not edit the class manually.
+ */
+
+#include "OpenAPIApiResponse.h"
+
+#include "OpenAPIModule.h"
+#include "OpenAPIHelpers.h"
+
+#include "Templates/SharedPointer.h"
+
+namespace OpenAPI
+{
+
+void OpenAPIApiResponse::WriteJson(JsonWriter& Writer) const
+{
+ Writer->WriteObjectStart();
+ if (Code.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("code")); WriteJsonValue(Writer, Code.GetValue());
+ }
+ if (Type.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("type")); WriteJsonValue(Writer, Type.GetValue());
+ }
+ if (Message.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("message")); WriteJsonValue(Writer, Message.GetValue());
+ }
+ Writer->WriteObjectEnd();
+}
+
+bool OpenAPIApiResponse::FromJson(const TSharedPtr& JsonObject)
+{
+ bool ParseSuccess = true;
+
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("code"), Code);
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("type"), Type);
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("message"), Message);
+
+ return ParseSuccess;
+}
+}
diff --git a/samples/client/petstore/cpp-ue4/OpenAPIApiResponse.h b/samples/client/petstore/cpp-ue4/OpenAPIApiResponse.h
new file mode 100644
index 000000000000..9eca3a5e273d
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/OpenAPIApiResponse.h
@@ -0,0 +1,37 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator
+ * https://github.com/OpenAPITools/openapi-generator
+ * Do not edit the class manually.
+ */
+
+#pragma once
+
+#include "OpenAPIBaseModel.h"
+
+namespace OpenAPI
+{
+
+/*
+ * OpenAPIApiResponse
+ *
+ * Describes the result of uploading an image resource
+ */
+class OPENAPI_API OpenAPIApiResponse : public Model
+{
+public:
+ virtual ~OpenAPIApiResponse() {}
+ bool FromJson(const TSharedPtr& JsonObject) final;
+ void WriteJson(JsonWriter& Writer) const final;
+
+ TOptional Code;
+ TOptional Type;
+ TOptional Message;
+};
+
+}
diff --git a/samples/client/petstore/cpp-ue4/OpenAPICategory.cpp b/samples/client/petstore/cpp-ue4/OpenAPICategory.cpp
new file mode 100644
index 000000000000..2f3b816d3c97
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/OpenAPICategory.cpp
@@ -0,0 +1,46 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator
+ * https://github.com/OpenAPITools/openapi-generator
+ * Do not edit the class manually.
+ */
+
+#include "OpenAPICategory.h"
+
+#include "OpenAPIModule.h"
+#include "OpenAPIHelpers.h"
+
+#include "Templates/SharedPointer.h"
+
+namespace OpenAPI
+{
+
+void OpenAPICategory::WriteJson(JsonWriter& Writer) const
+{
+ Writer->WriteObjectStart();
+ if (Id.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("id")); WriteJsonValue(Writer, Id.GetValue());
+ }
+ if (Name.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("name")); WriteJsonValue(Writer, Name.GetValue());
+ }
+ Writer->WriteObjectEnd();
+}
+
+bool OpenAPICategory::FromJson(const TSharedPtr& JsonObject)
+{
+ bool ParseSuccess = true;
+
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("id"), Id);
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("name"), Name);
+
+ return ParseSuccess;
+}
+}
diff --git a/samples/client/petstore/cpp-ue4/OpenAPICategory.h b/samples/client/petstore/cpp-ue4/OpenAPICategory.h
new file mode 100644
index 000000000000..b375f23e71ae
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/OpenAPICategory.h
@@ -0,0 +1,36 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator
+ * https://github.com/OpenAPITools/openapi-generator
+ * Do not edit the class manually.
+ */
+
+#pragma once
+
+#include "OpenAPIBaseModel.h"
+
+namespace OpenAPI
+{
+
+/*
+ * OpenAPICategory
+ *
+ * A category for a pet
+ */
+class OPENAPI_API OpenAPICategory : public Model
+{
+public:
+ virtual ~OpenAPICategory() {}
+ bool FromJson(const TSharedPtr& JsonObject) final;
+ void WriteJson(JsonWriter& Writer) const final;
+
+ TOptional Id;
+ TOptional Name;
+};
+
+}
diff --git a/samples/client/petstore/cpp-ue4/OpenAPIOrder.cpp b/samples/client/petstore/cpp-ue4/OpenAPIOrder.cpp
new file mode 100644
index 000000000000..cd8e524b0496
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/OpenAPIOrder.cpp
@@ -0,0 +1,109 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator
+ * https://github.com/OpenAPITools/openapi-generator
+ * Do not edit the class manually.
+ */
+
+#include "OpenAPIOrder.h"
+
+#include "OpenAPIModule.h"
+#include "OpenAPIHelpers.h"
+
+#include "Templates/SharedPointer.h"
+
+namespace OpenAPI
+{
+
+inline FString ToString(const OpenAPIOrder::StatusEnum& Value)
+{
+ switch (Value)
+ {
+ case OpenAPIOrder::StatusEnum::Placed:
+ return TEXT("placed");
+ case OpenAPIOrder::StatusEnum::Approved:
+ return TEXT("approved");
+ case OpenAPIOrder::StatusEnum::Delivered:
+ return TEXT("delivered");
+ }
+
+ UE_LOG(LogOpenAPI, Error, TEXT("Invalid OpenAPIOrder::StatusEnum Value (%d)"), (int)Value);
+ return TEXT("");
+}
+
+inline FStringFormatArg ToStringFormatArg(const OpenAPIOrder::StatusEnum& Value)
+{
+ return FStringFormatArg(ToString(Value));
+}
+
+inline void WriteJsonValue(JsonWriter& Writer, const OpenAPIOrder::StatusEnum& Value)
+{
+ WriteJsonValue(Writer, ToString(Value));
+}
+
+inline bool TryGetJsonValue(const TSharedPtr& JsonValue, OpenAPIOrder::StatusEnum& Value)
+{
+ FString TmpValue;
+ if (JsonValue->TryGetString(TmpValue))
+ {
+ static TMap StringToEnum = { };
+
+ const auto Found = StringToEnum.Find(TmpValue);
+ if(Found)
+ {
+ Value = *Found;
+ return true;
+ }
+ }
+ return false;
+}
+
+void OpenAPIOrder::WriteJson(JsonWriter& Writer) const
+{
+ Writer->WriteObjectStart();
+ if (Id.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("id")); WriteJsonValue(Writer, Id.GetValue());
+ }
+ if (PetId.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("petId")); WriteJsonValue(Writer, PetId.GetValue());
+ }
+ if (Quantity.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("quantity")); WriteJsonValue(Writer, Quantity.GetValue());
+ }
+ if (ShipDate.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("shipDate")); WriteJsonValue(Writer, ShipDate.GetValue());
+ }
+ if (Status.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("status")); WriteJsonValue(Writer, Status.GetValue());
+ }
+ if (Complete.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("complete")); WriteJsonValue(Writer, Complete.GetValue());
+ }
+ Writer->WriteObjectEnd();
+}
+
+bool OpenAPIOrder::FromJson(const TSharedPtr& JsonObject)
+{
+ bool ParseSuccess = true;
+
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("id"), Id);
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("petId"), PetId);
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("quantity"), Quantity);
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("shipDate"), ShipDate);
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("status"), Status);
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("complete"), Complete);
+
+ return ParseSuccess;
+}
+}
diff --git a/samples/client/petstore/cpp-ue4/OpenAPIOrder.h b/samples/client/petstore/cpp-ue4/OpenAPIOrder.h
new file mode 100644
index 000000000000..e3207190e295
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/OpenAPIOrder.h
@@ -0,0 +1,47 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator
+ * https://github.com/OpenAPITools/openapi-generator
+ * Do not edit the class manually.
+ */
+
+#pragma once
+
+#include "OpenAPIBaseModel.h"
+
+namespace OpenAPI
+{
+
+/*
+ * OpenAPIOrder
+ *
+ * An order for a pets from the pet store
+ */
+class OPENAPI_API OpenAPIOrder : public Model
+{
+public:
+ virtual ~OpenAPIOrder() {}
+ bool FromJson(const TSharedPtr& JsonObject) final;
+ void WriteJson(JsonWriter& Writer) const final;
+
+ TOptional Id;
+ TOptional PetId;
+ TOptional Quantity;
+ TOptional ShipDate;
+ enum class StatusEnum
+ {
+ Placed,
+ Approved,
+ Delivered,
+ };
+ /* Order Status */
+ TOptional Status;
+ TOptional Complete;
+};
+
+}
diff --git a/samples/client/petstore/cpp-ue4/OpenAPIPet.cpp b/samples/client/petstore/cpp-ue4/OpenAPIPet.cpp
new file mode 100644
index 000000000000..d1d1a690d6c5
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/OpenAPIPet.cpp
@@ -0,0 +1,103 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator
+ * https://github.com/OpenAPITools/openapi-generator
+ * Do not edit the class manually.
+ */
+
+#include "OpenAPIPet.h"
+
+#include "OpenAPIModule.h"
+#include "OpenAPIHelpers.h"
+
+#include "Templates/SharedPointer.h"
+
+namespace OpenAPI
+{
+
+inline FString ToString(const OpenAPIPet::StatusEnum& Value)
+{
+ switch (Value)
+ {
+ case OpenAPIPet::StatusEnum::Available:
+ return TEXT("available");
+ case OpenAPIPet::StatusEnum::Pending:
+ return TEXT("pending");
+ case OpenAPIPet::StatusEnum::Sold:
+ return TEXT("sold");
+ }
+
+ UE_LOG(LogOpenAPI, Error, TEXT("Invalid OpenAPIPet::StatusEnum Value (%d)"), (int)Value);
+ return TEXT("");
+}
+
+inline FStringFormatArg ToStringFormatArg(const OpenAPIPet::StatusEnum& Value)
+{
+ return FStringFormatArg(ToString(Value));
+}
+
+inline void WriteJsonValue(JsonWriter& Writer, const OpenAPIPet::StatusEnum& Value)
+{
+ WriteJsonValue(Writer, ToString(Value));
+}
+
+inline bool TryGetJsonValue(const TSharedPtr& JsonValue, OpenAPIPet::StatusEnum& Value)
+{
+ FString TmpValue;
+ if (JsonValue->TryGetString(TmpValue))
+ {
+ static TMap StringToEnum = { };
+
+ const auto Found = StringToEnum.Find(TmpValue);
+ if(Found)
+ {
+ Value = *Found;
+ return true;
+ }
+ }
+ return false;
+}
+
+void OpenAPIPet::WriteJson(JsonWriter& Writer) const
+{
+ Writer->WriteObjectStart();
+ if (Id.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("id")); WriteJsonValue(Writer, Id.GetValue());
+ }
+ if (Category.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("category")); WriteJsonValue(Writer, Category.GetValue());
+ }
+ Writer->WriteIdentifierPrefix(TEXT("name")); WriteJsonValue(Writer, Name);
+ Writer->WriteIdentifierPrefix(TEXT("photoUrls")); WriteJsonValue(Writer, PhotoUrls);
+ if (Tags.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("tags")); WriteJsonValue(Writer, Tags.GetValue());
+ }
+ if (Status.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("status")); WriteJsonValue(Writer, Status.GetValue());
+ }
+ Writer->WriteObjectEnd();
+}
+
+bool OpenAPIPet::FromJson(const TSharedPtr& JsonObject)
+{
+ bool ParseSuccess = true;
+
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("id"), Id);
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("category"), Category);
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("name"), Name);
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("photoUrls"), PhotoUrls);
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("tags"), Tags);
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("status"), Status);
+
+ return ParseSuccess;
+}
+}
diff --git a/samples/client/petstore/cpp-ue4/OpenAPIPet.h b/samples/client/petstore/cpp-ue4/OpenAPIPet.h
new file mode 100644
index 000000000000..3a90d2b0c6b1
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/OpenAPIPet.h
@@ -0,0 +1,49 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator
+ * https://github.com/OpenAPITools/openapi-generator
+ * Do not edit the class manually.
+ */
+
+#pragma once
+
+#include "OpenAPIBaseModel.h"
+#include "OpenAPICategory.h"
+#include "OpenAPITag.h"
+
+namespace OpenAPI
+{
+
+/*
+ * OpenAPIPet
+ *
+ * A pet for sale in the pet store
+ */
+class OPENAPI_API OpenAPIPet : public Model
+{
+public:
+ virtual ~OpenAPIPet() {}
+ bool FromJson(const TSharedPtr& JsonObject) final;
+ void WriteJson(JsonWriter& Writer) const final;
+
+ TOptional Id;
+ TOptional Category;
+ FString Name;
+ TArray> PhotoUrls;
+ TOptional>> Tags;
+ enum class StatusEnum
+ {
+ Available,
+ Pending,
+ Sold,
+ };
+ /* pet status in the store */
+ TOptional Status;
+};
+
+}
diff --git a/samples/client/petstore/cpp-ue4/OpenAPITag.cpp b/samples/client/petstore/cpp-ue4/OpenAPITag.cpp
new file mode 100644
index 000000000000..4f399573c7e3
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/OpenAPITag.cpp
@@ -0,0 +1,46 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator
+ * https://github.com/OpenAPITools/openapi-generator
+ * Do not edit the class manually.
+ */
+
+#include "OpenAPITag.h"
+
+#include "OpenAPIModule.h"
+#include "OpenAPIHelpers.h"
+
+#include "Templates/SharedPointer.h"
+
+namespace OpenAPI
+{
+
+void OpenAPITag::WriteJson(JsonWriter& Writer) const
+{
+ Writer->WriteObjectStart();
+ if (Id.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("id")); WriteJsonValue(Writer, Id.GetValue());
+ }
+ if (Name.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("name")); WriteJsonValue(Writer, Name.GetValue());
+ }
+ Writer->WriteObjectEnd();
+}
+
+bool OpenAPITag::FromJson(const TSharedPtr& JsonObject)
+{
+ bool ParseSuccess = true;
+
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("id"), Id);
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("name"), Name);
+
+ return ParseSuccess;
+}
+}
diff --git a/samples/client/petstore/cpp-ue4/OpenAPITag.h b/samples/client/petstore/cpp-ue4/OpenAPITag.h
new file mode 100644
index 000000000000..72bc6d130da7
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/OpenAPITag.h
@@ -0,0 +1,36 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator
+ * https://github.com/OpenAPITools/openapi-generator
+ * Do not edit the class manually.
+ */
+
+#pragma once
+
+#include "OpenAPIBaseModel.h"
+
+namespace OpenAPI
+{
+
+/*
+ * OpenAPITag
+ *
+ * A tag for a pet
+ */
+class OPENAPI_API OpenAPITag : public Model
+{
+public:
+ virtual ~OpenAPITag() {}
+ bool FromJson(const TSharedPtr& JsonObject) final;
+ void WriteJson(JsonWriter& Writer) const final;
+
+ TOptional Id;
+ TOptional Name;
+};
+
+}
diff --git a/samples/client/petstore/cpp-ue4/OpenAPIUser.cpp b/samples/client/petstore/cpp-ue4/OpenAPIUser.cpp
new file mode 100644
index 000000000000..bb0fe0292bf4
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/OpenAPIUser.cpp
@@ -0,0 +1,76 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator
+ * https://github.com/OpenAPITools/openapi-generator
+ * Do not edit the class manually.
+ */
+
+#include "OpenAPIUser.h"
+
+#include "OpenAPIModule.h"
+#include "OpenAPIHelpers.h"
+
+#include "Templates/SharedPointer.h"
+
+namespace OpenAPI
+{
+
+void OpenAPIUser::WriteJson(JsonWriter& Writer) const
+{
+ Writer->WriteObjectStart();
+ if (Id.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("id")); WriteJsonValue(Writer, Id.GetValue());
+ }
+ if (Username.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("username")); WriteJsonValue(Writer, Username.GetValue());
+ }
+ if (FirstName.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("firstName")); WriteJsonValue(Writer, FirstName.GetValue());
+ }
+ if (LastName.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("lastName")); WriteJsonValue(Writer, LastName.GetValue());
+ }
+ if (Email.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("email")); WriteJsonValue(Writer, Email.GetValue());
+ }
+ if (Password.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("password")); WriteJsonValue(Writer, Password.GetValue());
+ }
+ if (Phone.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("phone")); WriteJsonValue(Writer, Phone.GetValue());
+ }
+ if (UserStatus.IsSet())
+ {
+ Writer->WriteIdentifierPrefix(TEXT("userStatus")); WriteJsonValue(Writer, UserStatus.GetValue());
+ }
+ Writer->WriteObjectEnd();
+}
+
+bool OpenAPIUser::FromJson(const TSharedPtr& JsonObject)
+{
+ bool ParseSuccess = true;
+
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("id"), Id);
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("username"), Username);
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("firstName"), FirstName);
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("lastName"), LastName);
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("email"), Email);
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("password"), Password);
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("phone"), Phone);
+ ParseSuccess &= TryGetJsonValue(JsonObject, TEXT("userStatus"), UserStatus);
+
+ return ParseSuccess;
+}
+}
diff --git a/samples/client/petstore/cpp-ue4/OpenAPIUser.h b/samples/client/petstore/cpp-ue4/OpenAPIUser.h
new file mode 100644
index 000000000000..55494d8ec0bd
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/OpenAPIUser.h
@@ -0,0 +1,43 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator
+ * https://github.com/OpenAPITools/openapi-generator
+ * Do not edit the class manually.
+ */
+
+#pragma once
+
+#include "OpenAPIBaseModel.h"
+
+namespace OpenAPI
+{
+
+/*
+ * OpenAPIUser
+ *
+ * A User who is purchasing from the pet store
+ */
+class OPENAPI_API OpenAPIUser : public Model
+{
+public:
+ virtual ~OpenAPIUser() {}
+ bool FromJson(const TSharedPtr& JsonObject) final;
+ void WriteJson(JsonWriter& Writer) const final;
+
+ TOptional Id;
+ TOptional Username;
+ TOptional FirstName;
+ TOptional LastName;
+ TOptional Email;
+ TOptional Password;
+ TOptional Phone;
+ /* User Status */
+ TOptional UserStatus;
+};
+
+}
diff --git a/samples/client/petstore/cpp-ue4/Private/OpenAPIBaseModel.cpp b/samples/client/petstore/cpp-ue4/Private/OpenAPIBaseModel.cpp
new file mode 100644
index 000000000000..b8b5bd778a76
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/Private/OpenAPIBaseModel.cpp
@@ -0,0 +1,28 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator
+ * https://github.com/OpenAPITools/openapi-generator
+ * Do not edit the class manually.
+ */
+
+#include "OpenAPIBaseModel.h"
+
+namespace OpenAPI
+{
+
+void Response::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
+{
+ ResponseCode = InHttpResponseCode;
+ SetSuccessful(EHttpResponseCodes::IsOk(InHttpResponseCode));
+ if(InHttpResponseCode == EHttpResponseCodes::RequestTimeout)
+ {
+ SetResponseString(TEXT("Request Timeout"));
+ }
+}
+
+}
diff --git a/samples/client/petstore/cpp-ue4/Private/OpenAPIHelpers.cpp b/samples/client/petstore/cpp-ue4/Private/OpenAPIHelpers.cpp
new file mode 100644
index 000000000000..0a3be0adee22
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/Private/OpenAPIHelpers.cpp
@@ -0,0 +1,194 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator
+ * https://github.com/OpenAPITools/openapi-generator
+ * Do not edit the class manually.
+ */
+
+#include "OpenAPIHelpers.h"
+
+#include "OpenAPIModule.h"
+
+#include "Interfaces/IHttpRequest.h"
+#include "PlatformHttp.h"
+#include "Misc/FileHelper.h"
+
+namespace OpenAPI
+{
+
+HttpFileInput::HttpFileInput(const TCHAR* InFilePath)
+{
+ SetFilePath(InFilePath);
+}
+
+HttpFileInput::HttpFileInput(const FString& InFilePath)
+{
+ SetFilePath(InFilePath);
+}
+
+void HttpFileInput::SetFilePath(const TCHAR* InFilePath)
+{
+ FilePath = InFilePath;
+ if(ContentType.IsEmpty())
+ {
+ ContentType = FPlatformHttp::GetMimeType(InFilePath);
+ }
+}
+
+void HttpFileInput::SetFilePath(const FString& InFilePath)
+{
+ SetFilePath(*InFilePath);
+}
+
+void HttpFileInput::SetContentType(const TCHAR* InContentType)
+{
+ ContentType = InContentType;
+}
+
+FString HttpFileInput::GetFilename() const
+{
+ return FPaths::GetCleanFilename(FilePath);
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+const TCHAR* HttpMultipartFormData::Delimiter = TEXT("--");
+const TCHAR* HttpMultipartFormData::Newline = TEXT("\r\n");
+
+void HttpMultipartFormData::SetBoundary(const TCHAR* InBoundary)
+{
+ checkf(Boundary.IsEmpty(), TEXT("Boundary must be set before usage"));
+ Boundary = InBoundary;
+}
+
+const FString& HttpMultipartFormData::GetBoundary() const
+{
+ if (Boundary.IsEmpty())
+ {
+ // Generate a random boundary with enough entropy, should avoid occurences of the boundary in the data.
+ // Since the boundary is generated at every request, in case of failure, retries should succeed.
+ Boundary = FGuid::NewGuid().ToString(EGuidFormats::Short);
+ }
+
+ return Boundary;
+}
+
+void HttpMultipartFormData::SetupHttpRequest(const TSharedRef& HttpRequest)
+{
+ if(HttpRequest->GetVerb() != TEXT("POST"))
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Expected POST verb when using multipart form data"));
+ }
+
+ // Append final boundary
+ AppendString(Delimiter);
+ AppendString(*GetBoundary());
+ AppendString(Delimiter);
+
+ HttpRequest->SetHeader("Content-Type", FString::Printf(TEXT("multipart/form-data; boundary=%s"), *GetBoundary()));
+ HttpRequest->SetContent(FormData);
+}
+
+void HttpMultipartFormData::AddStringPart(const TCHAR* Name, const TCHAR* Data)
+{
+ // Add boundary
+ AppendString(Delimiter);
+ AppendString(*GetBoundary());
+ AppendString(Newline);
+
+ // Add header
+ AppendString(*FString::Printf(TEXT("Content-Disposition: form-data; name = \"%s\""), Name));
+ AppendString(Newline);
+ AppendString(*FString::Printf(TEXT("Content-Type: text/plain; charset=utf-8")));
+ AppendString(Newline);
+
+ // Add header to body splitter
+ AppendString(Newline);
+
+ // Add Data
+ AppendString(Data);
+ AppendString(Newline);
+}
+
+void HttpMultipartFormData::AddJsonPart(const TCHAR* Name, const FString& JsonString)
+{
+ // Add boundary
+ AppendString(Delimiter);
+ AppendString(*GetBoundary());
+ AppendString(Newline);
+
+ // Add header
+ AppendString(*FString::Printf(TEXT("Content-Disposition: form-data; name=\"%s\""), Name));
+ AppendString(Newline);
+ AppendString(*FString::Printf(TEXT("Content-Type: application/json; charset=utf-8")));
+ AppendString(Newline);
+
+ // Add header to body splitter
+ AppendString(Newline);
+
+ // Add Data
+ AppendString(*JsonString);
+ AppendString(Newline);
+}
+
+void HttpMultipartFormData::AddBinaryPart(const TCHAR* Name, const TArray& ByteArray)
+{
+ // Add boundary
+ AppendString(Delimiter);
+ AppendString(*GetBoundary());
+ AppendString(Newline);
+
+ // Add header
+ AppendString(*FString::Printf(TEXT("Content-Disposition: form-data; name=\"%s\""), Name));
+ AppendString(Newline);
+ AppendString(*FString::Printf(TEXT("Content-Type: application/octet-stream")));
+ AppendString(Newline);
+
+ // Add header to body splitter
+ AppendString(Newline);
+
+ // Add Data
+ FormData.Append(ByteArray);
+ AppendString(Newline);
+}
+
+void HttpMultipartFormData::AddFilePart(const TCHAR* Name, const HttpFileInput& File)
+{
+ TArray FileContents;
+ if (!FFileHelper::LoadFileToArray(FileContents, *File.GetFilePath()))
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Failed to load file (%s)"), *File.GetFilePath());
+ return;
+ }
+
+ // Add boundary
+ AppendString(Delimiter);
+ AppendString(*GetBoundary());
+ AppendString(Newline);
+
+ // Add header
+ AppendString(*FString::Printf(TEXT("Content-Disposition: form-data; name=\"%s\"; filename=\"%s\""), Name, *File.GetFilename()));
+ AppendString(Newline);
+ AppendString(*FString::Printf(TEXT("Content-Type: %s"), *File.GetContentType()));
+ AppendString(Newline);
+
+ // Add header to body splitter
+ AppendString(Newline);
+
+ // Add Data
+ FormData.Append(FileContents);
+ AppendString(Newline);
+}
+
+void HttpMultipartFormData::AppendString(const TCHAR* Str)
+{
+ FTCHARToUTF8 utf8Str(Str);
+ FormData.Append((uint8*)utf8Str.Get(), utf8Str.Length());
+}
+
+}
diff --git a/samples/client/petstore/cpp-ue4/Private/OpenAPIModule.cpp b/samples/client/petstore/cpp-ue4/Private/OpenAPIModule.cpp
new file mode 100644
index 000000000000..cdadfc281f4a
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/Private/OpenAPIModule.cpp
@@ -0,0 +1,25 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator
+ * https://github.com/OpenAPITools/openapi-generator
+ * Do not edit the class manually.
+ */
+
+#include "OpenAPIModule.h"
+
+IMPLEMENT_MODULE(OpenAPIModule, OpenAPI);
+DEFINE_LOG_CATEGORY(LogOpenAPI);
+
+void OpenAPIModule::StartupModule()
+{
+}
+
+void OpenAPIModule::ShutdownModule()
+{
+}
+
diff --git a/samples/client/petstore/cpp-ue4/Private/OpenAPIModule.h b/samples/client/petstore/cpp-ue4/Private/OpenAPIModule.h
new file mode 100644
index 000000000000..5dc6eeff6eb6
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/Private/OpenAPIModule.h
@@ -0,0 +1,26 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator
+ * https://github.com/OpenAPITools/openapi-generator
+ * Do not edit the class manually.
+ */
+
+#pragma once
+
+#include "Modules/ModuleInterface.h"
+#include "Modules/ModuleManager.h"
+#include "Logging/LogMacros.h"
+
+DECLARE_LOG_CATEGORY_EXTERN(LogOpenAPI, Log, All);
+
+class OPENAPI_API OpenAPIModule : public IModuleInterface
+{
+public:
+ void StartupModule() final;
+ void ShutdownModule() final;
+};
diff --git a/samples/client/petstore/cpp-ue4/Private/OpenAPIPetApi.cpp b/samples/client/petstore/cpp-ue4/Private/OpenAPIPetApi.cpp
new file mode 100644
index 000000000000..a0a0cdd962e7
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/Private/OpenAPIPetApi.cpp
@@ -0,0 +1,305 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator
+ * https://github.com/OpenAPITools/openapi-generator
+ * Do not edit the class manually.
+ */
+
+#include "OpenAPIPetApi.h"
+
+#include "OpenAPIPetApiOperations.h"
+#include "OpenAPIModule.h"
+
+#include "HttpModule.h"
+#include "Serialization/JsonSerializer.h"
+
+namespace OpenAPI
+{
+
+OpenAPIPetApi::OpenAPIPetApi()
+: Url(TEXT("http://petstore.swagger.io/v2"))
+{
+}
+
+OpenAPIPetApi::~OpenAPIPetApi() {}
+
+void OpenAPIPetApi::SetURL(const FString& InUrl)
+{
+ Url = InUrl;
+}
+
+void OpenAPIPetApi::AddHeaderParam(const FString& Key, const FString& Value)
+{
+ AdditionalHeaderParams.Add(Key, Value);
+}
+
+void OpenAPIPetApi::ClearHeaderParams()
+{
+ AdditionalHeaderParams.Reset();
+}
+
+bool OpenAPIPetApi::IsValid() const
+{
+ if (Url.IsEmpty())
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("OpenAPIPetApi: Endpoint Url is not set, request cannot be performed"));
+ return false;
+ }
+
+ return true;
+}
+
+void OpenAPIPetApi::HandleResponse(FHttpResponsePtr HttpResponse, bool bSucceeded, Response& InOutResponse) const
+{
+ InOutResponse.SetHttpResponse(HttpResponse);
+ InOutResponse.SetSuccessful(bSucceeded);
+
+ if (bSucceeded && HttpResponse.IsValid())
+ {
+ InOutResponse.SetHttpResponseCode((EHttpResponseCodes::Type)HttpResponse->GetResponseCode());
+ FString ContentType = HttpResponse->GetContentType();
+ FString Content;
+
+ if (ContentType == TEXT("application/json"))
+ {
+ Content = HttpResponse->GetContentAsString();
+
+ TSharedPtr JsonValue;
+ auto Reader = TJsonReaderFactory<>::Create(Content);
+
+ if (FJsonSerializer::Deserialize(Reader, JsonValue) && JsonValue.IsValid())
+ {
+ if (InOutResponse.FromJson(JsonValue))
+ return; // Successfully parsed
+ }
+ }
+ else if(ContentType == TEXT("text/plain"))
+ {
+ Content = HttpResponse->GetContentAsString();
+ InOutResponse.SetResponseString(Content);
+ return; // Successfully parsed
+ }
+
+ // Report the parse error but do not mark the request as unsuccessful. Data could be partial or malformed, but the request succeeded.
+ UE_LOG(LogOpenAPI, Error, TEXT("Failed to deserialize Http response content (type:%s):\n%s"), *ContentType , *Content);
+ return;
+ }
+
+ // By default, assume we failed to establish connection
+ InOutResponse.SetHttpResponseCode(EHttpResponseCodes::RequestTimeout);
+}
+
+bool OpenAPIPetApi::AddPet(const AddPetRequest& Request, const FAddPetDelegate& Delegate /*= FAddPetDelegate()*/) const
+{
+ if (!IsValid())
+ return false;
+
+ TSharedRef HttpRequest = FHttpModule::Get().CreateRequest();
+ HttpRequest->SetURL(*(Url + Request.ComputePath()));
+
+ for(const auto& It : AdditionalHeaderParams)
+ {
+ HttpRequest->SetHeader(It.Key, It.Value);
+ }
+
+ Request.SetupHttpRequest(HttpRequest);
+
+ HttpRequest->OnProcessRequestComplete().BindRaw(this, &OpenAPIPetApi::OnAddPetResponse, Delegate);
+ return HttpRequest->ProcessRequest();
+}
+
+void OpenAPIPetApi::OnAddPetResponse(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, FAddPetDelegate Delegate) const
+{
+ AddPetResponse Response;
+ HandleResponse(HttpResponse, bSucceeded, Response);
+ Delegate.ExecuteIfBound(Response);
+}
+
+bool OpenAPIPetApi::DeletePet(const DeletePetRequest& Request, const FDeletePetDelegate& Delegate /*= FDeletePetDelegate()*/) const
+{
+ if (!IsValid())
+ return false;
+
+ TSharedRef HttpRequest = FHttpModule::Get().CreateRequest();
+ HttpRequest->SetURL(*(Url + Request.ComputePath()));
+
+ for(const auto& It : AdditionalHeaderParams)
+ {
+ HttpRequest->SetHeader(It.Key, It.Value);
+ }
+
+ Request.SetupHttpRequest(HttpRequest);
+
+ HttpRequest->OnProcessRequestComplete().BindRaw(this, &OpenAPIPetApi::OnDeletePetResponse, Delegate);
+ return HttpRequest->ProcessRequest();
+}
+
+void OpenAPIPetApi::OnDeletePetResponse(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, FDeletePetDelegate Delegate) const
+{
+ DeletePetResponse Response;
+ HandleResponse(HttpResponse, bSucceeded, Response);
+ Delegate.ExecuteIfBound(Response);
+}
+
+bool OpenAPIPetApi::FindPetsByStatus(const FindPetsByStatusRequest& Request, const FFindPetsByStatusDelegate& Delegate /*= FFindPetsByStatusDelegate()*/) const
+{
+ if (!IsValid())
+ return false;
+
+ TSharedRef HttpRequest = FHttpModule::Get().CreateRequest();
+ HttpRequest->SetURL(*(Url + Request.ComputePath()));
+
+ for(const auto& It : AdditionalHeaderParams)
+ {
+ HttpRequest->SetHeader(It.Key, It.Value);
+ }
+
+ Request.SetupHttpRequest(HttpRequest);
+
+ HttpRequest->OnProcessRequestComplete().BindRaw(this, &OpenAPIPetApi::OnFindPetsByStatusResponse, Delegate);
+ return HttpRequest->ProcessRequest();
+}
+
+void OpenAPIPetApi::OnFindPetsByStatusResponse(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, FFindPetsByStatusDelegate Delegate) const
+{
+ FindPetsByStatusResponse Response;
+ HandleResponse(HttpResponse, bSucceeded, Response);
+ Delegate.ExecuteIfBound(Response);
+}
+
+bool OpenAPIPetApi::FindPetsByTags(const FindPetsByTagsRequest& Request, const FFindPetsByTagsDelegate& Delegate /*= FFindPetsByTagsDelegate()*/) const
+{
+ if (!IsValid())
+ return false;
+
+ TSharedRef HttpRequest = FHttpModule::Get().CreateRequest();
+ HttpRequest->SetURL(*(Url + Request.ComputePath()));
+
+ for(const auto& It : AdditionalHeaderParams)
+ {
+ HttpRequest->SetHeader(It.Key, It.Value);
+ }
+
+ Request.SetupHttpRequest(HttpRequest);
+
+ HttpRequest->OnProcessRequestComplete().BindRaw(this, &OpenAPIPetApi::OnFindPetsByTagsResponse, Delegate);
+ return HttpRequest->ProcessRequest();
+}
+
+void OpenAPIPetApi::OnFindPetsByTagsResponse(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, FFindPetsByTagsDelegate Delegate) const
+{
+ FindPetsByTagsResponse Response;
+ HandleResponse(HttpResponse, bSucceeded, Response);
+ Delegate.ExecuteIfBound(Response);
+}
+
+bool OpenAPIPetApi::GetPetById(const GetPetByIdRequest& Request, const FGetPetByIdDelegate& Delegate /*= FGetPetByIdDelegate()*/) const
+{
+ if (!IsValid())
+ return false;
+
+ TSharedRef HttpRequest = FHttpModule::Get().CreateRequest();
+ HttpRequest->SetURL(*(Url + Request.ComputePath()));
+
+ for(const auto& It : AdditionalHeaderParams)
+ {
+ HttpRequest->SetHeader(It.Key, It.Value);
+ }
+
+ Request.SetupHttpRequest(HttpRequest);
+
+ HttpRequest->OnProcessRequestComplete().BindRaw(this, &OpenAPIPetApi::OnGetPetByIdResponse, Delegate);
+ return HttpRequest->ProcessRequest();
+}
+
+void OpenAPIPetApi::OnGetPetByIdResponse(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, FGetPetByIdDelegate Delegate) const
+{
+ GetPetByIdResponse Response;
+ HandleResponse(HttpResponse, bSucceeded, Response);
+ Delegate.ExecuteIfBound(Response);
+}
+
+bool OpenAPIPetApi::UpdatePet(const UpdatePetRequest& Request, const FUpdatePetDelegate& Delegate /*= FUpdatePetDelegate()*/) const
+{
+ if (!IsValid())
+ return false;
+
+ TSharedRef HttpRequest = FHttpModule::Get().CreateRequest();
+ HttpRequest->SetURL(*(Url + Request.ComputePath()));
+
+ for(const auto& It : AdditionalHeaderParams)
+ {
+ HttpRequest->SetHeader(It.Key, It.Value);
+ }
+
+ Request.SetupHttpRequest(HttpRequest);
+
+ HttpRequest->OnProcessRequestComplete().BindRaw(this, &OpenAPIPetApi::OnUpdatePetResponse, Delegate);
+ return HttpRequest->ProcessRequest();
+}
+
+void OpenAPIPetApi::OnUpdatePetResponse(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, FUpdatePetDelegate Delegate) const
+{
+ UpdatePetResponse Response;
+ HandleResponse(HttpResponse, bSucceeded, Response);
+ Delegate.ExecuteIfBound(Response);
+}
+
+bool OpenAPIPetApi::UpdatePetWithForm(const UpdatePetWithFormRequest& Request, const FUpdatePetWithFormDelegate& Delegate /*= FUpdatePetWithFormDelegate()*/) const
+{
+ if (!IsValid())
+ return false;
+
+ TSharedRef HttpRequest = FHttpModule::Get().CreateRequest();
+ HttpRequest->SetURL(*(Url + Request.ComputePath()));
+
+ for(const auto& It : AdditionalHeaderParams)
+ {
+ HttpRequest->SetHeader(It.Key, It.Value);
+ }
+
+ Request.SetupHttpRequest(HttpRequest);
+
+ HttpRequest->OnProcessRequestComplete().BindRaw(this, &OpenAPIPetApi::OnUpdatePetWithFormResponse, Delegate);
+ return HttpRequest->ProcessRequest();
+}
+
+void OpenAPIPetApi::OnUpdatePetWithFormResponse(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, FUpdatePetWithFormDelegate Delegate) const
+{
+ UpdatePetWithFormResponse Response;
+ HandleResponse(HttpResponse, bSucceeded, Response);
+ Delegate.ExecuteIfBound(Response);
+}
+
+bool OpenAPIPetApi::UploadFile(const UploadFileRequest& Request, const FUploadFileDelegate& Delegate /*= FUploadFileDelegate()*/) const
+{
+ if (!IsValid())
+ return false;
+
+ TSharedRef HttpRequest = FHttpModule::Get().CreateRequest();
+ HttpRequest->SetURL(*(Url + Request.ComputePath()));
+
+ for(const auto& It : AdditionalHeaderParams)
+ {
+ HttpRequest->SetHeader(It.Key, It.Value);
+ }
+
+ Request.SetupHttpRequest(HttpRequest);
+
+ HttpRequest->OnProcessRequestComplete().BindRaw(this, &OpenAPIPetApi::OnUploadFileResponse, Delegate);
+ return HttpRequest->ProcessRequest();
+}
+
+void OpenAPIPetApi::OnUploadFileResponse(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, FUploadFileDelegate Delegate) const
+{
+ UploadFileResponse Response;
+ HandleResponse(HttpResponse, bSucceeded, Response);
+ Delegate.ExecuteIfBound(Response);
+}
+
+}
diff --git a/samples/client/petstore/cpp-ue4/Private/OpenAPIPetApiOperations.cpp b/samples/client/petstore/cpp-ue4/Private/OpenAPIPetApiOperations.cpp
new file mode 100644
index 000000000000..8ca1ec220fd5
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/Private/OpenAPIPetApiOperations.cpp
@@ -0,0 +1,560 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator
+ * https://github.com/OpenAPITools/openapi-generator
+ * Do not edit the class manually.
+ */
+
+#include "OpenAPIPetApiOperations.h"
+
+#include "OpenAPIModule.h"
+#include "OpenAPIHelpers.h"
+
+#include "Dom/JsonObject.h"
+#include "Templates/SharedPointer.h"
+#include "HttpModule.h"
+#include "PlatformHttp.h"
+
+namespace OpenAPI
+{
+
+FString OpenAPIPetApi::AddPetRequest::ComputePath() const
+{
+ FString Path(TEXT("/pet"));
+ return Path;
+}
+
+void OpenAPIPetApi::AddPetRequest::SetupHttpRequest(const TSharedRef& HttpRequest) const
+{
+ static const TArray Consumes = { TEXT("application/json"), TEXT("application/xml") };
+ //static const TArray Produces = { };
+
+ HttpRequest->SetVerb(TEXT("POST"));
+
+ // Default to Json Body request
+ if (Consumes.Num() == 0 || Consumes.Contains(TEXT("application/json")))
+ {
+ // Body parameters
+ FString JsonBody;
+ JsonWriter Writer = TJsonWriterFactory<>::Create(&JsonBody);
+
+ Writer->WriteObjectStart();
+ Writer->WriteIdentifierPrefix(TEXT("body")); WriteJsonValue(Writer, Body);
+ Writer->WriteObjectEnd();
+ Writer->Close();
+
+ HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json; charset=utf-8"));
+ HttpRequest->SetContentAsString(JsonBody);
+ }
+ else if (Consumes.Contains(TEXT("multipart/form-data")))
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Body parameter (body) was ignored, not supported in multipart form"));
+ }
+ else if (Consumes.Contains(TEXT("application/x-www-form-urlencoded")))
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Body parameter (body) was ignored, not supported in urlencoded requests"));
+ }
+ else
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Request ContentType not supported (%s)"), *FString::Join(Consumes, TEXT(",")));
+ }
+}
+
+void OpenAPIPetApi::AddPetResponse::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
+{
+ Response::SetHttpResponseCode(InHttpResponseCode);
+ switch ((int)InHttpResponseCode)
+ {
+ case 405:
+ SetResponseString(TEXT("Invalid input"));
+ break;
+ }
+}
+
+bool OpenAPIPetApi::AddPetResponse::FromJson(const TSharedPtr& JsonValue)
+{
+ return true;
+}
+
+FString OpenAPIPetApi::DeletePetRequest::ComputePath() const
+{
+ TMap PathParams = {
+ { TEXT("petId"), ToStringFormatArg(PetId) } };
+
+ FString Path = FString::Format(TEXT("/pet/{petId}"), PathParams);
+
+ return Path;
+}
+
+void OpenAPIPetApi::DeletePetRequest::SetupHttpRequest(const TSharedRef& HttpRequest) const
+{
+ static const TArray Consumes = { };
+ //static const TArray Produces = { };
+
+ HttpRequest->SetVerb(TEXT("DELETE"));
+
+ // Header parameters
+ if (ApiKey.IsSet())
+ {
+ HttpRequest->SetHeader(TEXT("api_key"), ApiKey.GetValue());
+ }
+
+ // Default to Json Body request
+ if (Consumes.Num() == 0 || Consumes.Contains(TEXT("application/json")))
+ {
+ }
+ else if (Consumes.Contains(TEXT("multipart/form-data")))
+ {
+ }
+ else if (Consumes.Contains(TEXT("application/x-www-form-urlencoded")))
+ {
+ }
+ else
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Request ContentType not supported (%s)"), *FString::Join(Consumes, TEXT(",")));
+ }
+}
+
+void OpenAPIPetApi::DeletePetResponse::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
+{
+ Response::SetHttpResponseCode(InHttpResponseCode);
+ switch ((int)InHttpResponseCode)
+ {
+ case 400:
+ SetResponseString(TEXT("Invalid pet value"));
+ break;
+ }
+}
+
+bool OpenAPIPetApi::DeletePetResponse::FromJson(const TSharedPtr& JsonValue)
+{
+ return true;
+}
+
+inline FString ToString(const OpenAPIPetApi::FindPetsByStatusRequest::StatusEnum& Value)
+{
+ switch (Value)
+ {
+ case OpenAPIPetApi::FindPetsByStatusRequest::StatusEnum::Available:
+ return TEXT("available");
+ case OpenAPIPetApi::FindPetsByStatusRequest::StatusEnum::Pending:
+ return TEXT("pending");
+ case OpenAPIPetApi::FindPetsByStatusRequest::StatusEnum::Sold:
+ return TEXT("sold");
+ }
+
+ UE_LOG(LogOpenAPI, Error, TEXT("Invalid OpenAPIPetApi::FindPetsByStatusRequest::StatusEnum Value (%d)"), (int)Value);
+ return TEXT("");
+}
+
+inline FStringFormatArg ToStringFormatArg(const OpenAPIPetApi::FindPetsByStatusRequest::StatusEnum& Value)
+{
+ return FStringFormatArg(ToString(Value));
+}
+
+inline void WriteJsonValue(JsonWriter& Writer, const OpenAPIPetApi::FindPetsByStatusRequest::StatusEnum& Value)
+{
+ WriteJsonValue(Writer, ToString(Value));
+}
+
+inline bool TryGetJsonValue(const TSharedPtr& JsonValue, OpenAPIPetApi::FindPetsByStatusRequest::StatusEnum& Value)
+{
+ FString TmpValue;
+ if (JsonValue->TryGetString(TmpValue))
+ {
+ static TMap StringToEnum = {
+ { TEXT("available"), OpenAPIPetApi::FindPetsByStatusRequest::StatusEnum::Available },
+ { TEXT("pending"), OpenAPIPetApi::FindPetsByStatusRequest::StatusEnum::Pending },
+ { TEXT("sold"), OpenAPIPetApi::FindPetsByStatusRequest::StatusEnum::Sold }, };
+
+ const auto Found = StringToEnum.Find(TmpValue);
+ if(Found)
+ {
+ Value = *Found;
+ return true;
+ }
+ }
+ return false;
+}
+
+FString OpenAPIPetApi::FindPetsByStatusRequest::ComputePath() const
+{
+ FString Path(TEXT("/pet/findByStatus"));
+ TArray QueryParams;
+ QueryParams.Add(FString(TEXT("status=")) + CollectionToUrlString_csv(Status, TEXT("status")));
+ Path += TCHAR('?');
+ Path += FString::Join(QueryParams, TEXT("&"));
+
+ return Path;
+}
+
+void OpenAPIPetApi::FindPetsByStatusRequest::SetupHttpRequest(const TSharedRef& HttpRequest) const
+{
+ static const TArray Consumes = { };
+ //static const TArray Produces = { TEXT("application/xml"), TEXT("application/json") };
+
+ HttpRequest->SetVerb(TEXT("GET"));
+
+ // Default to Json Body request
+ if (Consumes.Num() == 0 || Consumes.Contains(TEXT("application/json")))
+ {
+ }
+ else if (Consumes.Contains(TEXT("multipart/form-data")))
+ {
+ }
+ else if (Consumes.Contains(TEXT("application/x-www-form-urlencoded")))
+ {
+ }
+ else
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Request ContentType not supported (%s)"), *FString::Join(Consumes, TEXT(",")));
+ }
+}
+
+void OpenAPIPetApi::FindPetsByStatusResponse::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
+{
+ Response::SetHttpResponseCode(InHttpResponseCode);
+ switch ((int)InHttpResponseCode)
+ {
+ case 200:
+ default:
+ SetResponseString(TEXT("successful operation"));
+ break;
+ case 400:
+ SetResponseString(TEXT("Invalid status value"));
+ break;
+ }
+}
+
+bool OpenAPIPetApi::FindPetsByStatusResponse::FromJson(const TSharedPtr& JsonValue)
+{
+ return TryGetJsonValue(JsonValue, Content);
+}
+
+FString OpenAPIPetApi::FindPetsByTagsRequest::ComputePath() const
+{
+ FString Path(TEXT("/pet/findByTags"));
+ TArray QueryParams;
+ QueryParams.Add(FString(TEXT("tags=")) + CollectionToUrlString_csv(Tags, TEXT("tags")));
+ Path += TCHAR('?');
+ Path += FString::Join(QueryParams, TEXT("&"));
+
+ return Path;
+}
+
+void OpenAPIPetApi::FindPetsByTagsRequest::SetupHttpRequest(const TSharedRef& HttpRequest) const
+{
+ static const TArray Consumes = { };
+ //static const TArray Produces = { TEXT("application/xml"), TEXT("application/json") };
+
+ HttpRequest->SetVerb(TEXT("GET"));
+
+ // Default to Json Body request
+ if (Consumes.Num() == 0 || Consumes.Contains(TEXT("application/json")))
+ {
+ }
+ else if (Consumes.Contains(TEXT("multipart/form-data")))
+ {
+ }
+ else if (Consumes.Contains(TEXT("application/x-www-form-urlencoded")))
+ {
+ }
+ else
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Request ContentType not supported (%s)"), *FString::Join(Consumes, TEXT(",")));
+ }
+}
+
+void OpenAPIPetApi::FindPetsByTagsResponse::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
+{
+ Response::SetHttpResponseCode(InHttpResponseCode);
+ switch ((int)InHttpResponseCode)
+ {
+ case 200:
+ default:
+ SetResponseString(TEXT("successful operation"));
+ break;
+ case 400:
+ SetResponseString(TEXT("Invalid tag value"));
+ break;
+ }
+}
+
+bool OpenAPIPetApi::FindPetsByTagsResponse::FromJson(const TSharedPtr& JsonValue)
+{
+ return TryGetJsonValue(JsonValue, Content);
+}
+
+FString OpenAPIPetApi::GetPetByIdRequest::ComputePath() const
+{
+ TMap PathParams = {
+ { TEXT("petId"), ToStringFormatArg(PetId) } };
+
+ FString Path = FString::Format(TEXT("/pet/{petId}"), PathParams);
+
+ return Path;
+}
+
+void OpenAPIPetApi::GetPetByIdRequest::SetupHttpRequest(const TSharedRef& HttpRequest) const
+{
+ static const TArray Consumes = { };
+ //static const TArray Produces = { TEXT("application/xml"), TEXT("application/json") };
+
+ HttpRequest->SetVerb(TEXT("GET"));
+
+ // Default to Json Body request
+ if (Consumes.Num() == 0 || Consumes.Contains(TEXT("application/json")))
+ {
+ }
+ else if (Consumes.Contains(TEXT("multipart/form-data")))
+ {
+ }
+ else if (Consumes.Contains(TEXT("application/x-www-form-urlencoded")))
+ {
+ }
+ else
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Request ContentType not supported (%s)"), *FString::Join(Consumes, TEXT(",")));
+ }
+}
+
+void OpenAPIPetApi::GetPetByIdResponse::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
+{
+ Response::SetHttpResponseCode(InHttpResponseCode);
+ switch ((int)InHttpResponseCode)
+ {
+ case 200:
+ default:
+ SetResponseString(TEXT("successful operation"));
+ break;
+ case 400:
+ SetResponseString(TEXT("Invalid ID supplied"));
+ break;
+ case 404:
+ SetResponseString(TEXT("Pet not found"));
+ break;
+ }
+}
+
+bool OpenAPIPetApi::GetPetByIdResponse::FromJson(const TSharedPtr& JsonValue)
+{
+ return TryGetJsonValue(JsonValue, Content);
+}
+
+FString OpenAPIPetApi::UpdatePetRequest::ComputePath() const
+{
+ FString Path(TEXT("/pet"));
+ return Path;
+}
+
+void OpenAPIPetApi::UpdatePetRequest::SetupHttpRequest(const TSharedRef& HttpRequest) const
+{
+ static const TArray Consumes = { TEXT("application/json"), TEXT("application/xml") };
+ //static const TArray Produces = { };
+
+ HttpRequest->SetVerb(TEXT("PUT"));
+
+ // Default to Json Body request
+ if (Consumes.Num() == 0 || Consumes.Contains(TEXT("application/json")))
+ {
+ // Body parameters
+ FString JsonBody;
+ JsonWriter Writer = TJsonWriterFactory<>::Create(&JsonBody);
+
+ Writer->WriteObjectStart();
+ Writer->WriteIdentifierPrefix(TEXT("body")); WriteJsonValue(Writer, Body);
+ Writer->WriteObjectEnd();
+ Writer->Close();
+
+ HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json; charset=utf-8"));
+ HttpRequest->SetContentAsString(JsonBody);
+ }
+ else if (Consumes.Contains(TEXT("multipart/form-data")))
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Body parameter (body) was ignored, not supported in multipart form"));
+ }
+ else if (Consumes.Contains(TEXT("application/x-www-form-urlencoded")))
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Body parameter (body) was ignored, not supported in urlencoded requests"));
+ }
+ else
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Request ContentType not supported (%s)"), *FString::Join(Consumes, TEXT(",")));
+ }
+}
+
+void OpenAPIPetApi::UpdatePetResponse::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
+{
+ Response::SetHttpResponseCode(InHttpResponseCode);
+ switch ((int)InHttpResponseCode)
+ {
+ case 400:
+ SetResponseString(TEXT("Invalid ID supplied"));
+ break;
+ case 404:
+ SetResponseString(TEXT("Pet not found"));
+ break;
+ case 405:
+ SetResponseString(TEXT("Validation exception"));
+ break;
+ }
+}
+
+bool OpenAPIPetApi::UpdatePetResponse::FromJson(const TSharedPtr& JsonValue)
+{
+ return true;
+}
+
+FString OpenAPIPetApi::UpdatePetWithFormRequest::ComputePath() const
+{
+ TMap PathParams = {
+ { TEXT("petId"), ToStringFormatArg(PetId) } };
+
+ FString Path = FString::Format(TEXT("/pet/{petId}"), PathParams);
+
+ return Path;
+}
+
+void OpenAPIPetApi::UpdatePetWithFormRequest::SetupHttpRequest(const TSharedRef& HttpRequest) const
+{
+ static const TArray Consumes = { TEXT("application/x-www-form-urlencoded") };
+ //static const TArray Produces = { };
+
+ HttpRequest->SetVerb(TEXT("POST"));
+
+ // Default to Json Body request
+ if (Consumes.Num() == 0 || Consumes.Contains(TEXT("application/json")))
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Form parameter (name) was ignored, cannot be used in JsonBody"));
+ UE_LOG(LogOpenAPI, Error, TEXT("Form parameter (status) was ignored, cannot be used in JsonBody"));
+ }
+ else if (Consumes.Contains(TEXT("multipart/form-data")))
+ {
+ HttpMultipartFormData FormData;
+ if(Name.IsSet())
+ {
+ FormData.AddStringPart(TEXT("name"), *ToUrlString(Name.GetValue()));
+ }
+ if(Status.IsSet())
+ {
+ FormData.AddStringPart(TEXT("status"), *ToUrlString(Status.GetValue()));
+ }
+
+ FormData.SetupHttpRequest(HttpRequest);
+ }
+ else if (Consumes.Contains(TEXT("application/x-www-form-urlencoded")))
+ {
+ TArray FormParams;
+ if(Name.IsSet())
+ {
+ FormParams.Add(FString(TEXT("name=")) + ToUrlString(Name.GetValue()));
+ }
+ if(Status.IsSet())
+ {
+ FormParams.Add(FString(TEXT("status=")) + ToUrlString(Status.GetValue()));
+ }
+
+ HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/x-www-form-urlencoded; charset=utf-8"));
+ HttpRequest->SetContentAsString(FString::Join(FormParams, TEXT("&")));
+ }
+ else
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Request ContentType not supported (%s)"), *FString::Join(Consumes, TEXT(",")));
+ }
+}
+
+void OpenAPIPetApi::UpdatePetWithFormResponse::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
+{
+ Response::SetHttpResponseCode(InHttpResponseCode);
+ switch ((int)InHttpResponseCode)
+ {
+ case 405:
+ SetResponseString(TEXT("Invalid input"));
+ break;
+ }
+}
+
+bool OpenAPIPetApi::UpdatePetWithFormResponse::FromJson(const TSharedPtr& JsonValue)
+{
+ return true;
+}
+
+FString OpenAPIPetApi::UploadFileRequest::ComputePath() const
+{
+ TMap PathParams = {
+ { TEXT("petId"), ToStringFormatArg(PetId) } };
+
+ FString Path = FString::Format(TEXT("/pet/{petId}/uploadImage"), PathParams);
+
+ return Path;
+}
+
+void OpenAPIPetApi::UploadFileRequest::SetupHttpRequest(const TSharedRef& HttpRequest) const
+{
+ static const TArray Consumes = { TEXT("multipart/form-data") };
+ //static const TArray Produces = { TEXT("application/json") };
+
+ HttpRequest->SetVerb(TEXT("POST"));
+
+ // Default to Json Body request
+ if (Consumes.Num() == 0 || Consumes.Contains(TEXT("application/json")))
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Form parameter (additionalMetadata) was ignored, cannot be used in JsonBody"));
+ UE_LOG(LogOpenAPI, Error, TEXT("Form parameter (file) was ignored, cannot be used in JsonBody"));
+ }
+ else if (Consumes.Contains(TEXT("multipart/form-data")))
+ {
+ HttpMultipartFormData FormData;
+ if(AdditionalMetadata.IsSet())
+ {
+ FormData.AddStringPart(TEXT("additionalMetadata"), *ToUrlString(AdditionalMetadata.GetValue()));
+ }
+ if(File.IsSet())
+ {
+ FormData.AddFilePart(TEXT("file"), File.GetValue());
+ FormData.AddBinaryPart(TEXT("file"), File.GetValue());
+ }
+
+ FormData.SetupHttpRequest(HttpRequest);
+ }
+ else if (Consumes.Contains(TEXT("application/x-www-form-urlencoded")))
+ {
+ TArray FormParams;
+ if(AdditionalMetadata.IsSet())
+ {
+ FormParams.Add(FString(TEXT("additionalMetadata=")) + ToUrlString(AdditionalMetadata.GetValue()));
+ }
+ UE_LOG(LogOpenAPI, Error, TEXT("Form parameter (file) was ignored, Files are not supported in urlencoded requests"));
+
+ HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/x-www-form-urlencoded; charset=utf-8"));
+ HttpRequest->SetContentAsString(FString::Join(FormParams, TEXT("&")));
+ }
+ else
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Request ContentType not supported (%s)"), *FString::Join(Consumes, TEXT(",")));
+ }
+}
+
+void OpenAPIPetApi::UploadFileResponse::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
+{
+ Response::SetHttpResponseCode(InHttpResponseCode);
+ switch ((int)InHttpResponseCode)
+ {
+ case 200:
+ default:
+ SetResponseString(TEXT("successful operation"));
+ break;
+ }
+}
+
+bool OpenAPIPetApi::UploadFileResponse::FromJson(const TSharedPtr& JsonValue)
+{
+ return TryGetJsonValue(JsonValue, Content);
+}
+
+}
diff --git a/samples/client/petstore/cpp-ue4/Private/OpenAPIStoreApi.cpp b/samples/client/petstore/cpp-ue4/Private/OpenAPIStoreApi.cpp
new file mode 100644
index 000000000000..ace92ce83396
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/Private/OpenAPIStoreApi.cpp
@@ -0,0 +1,201 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator
+ * https://github.com/OpenAPITools/openapi-generator
+ * Do not edit the class manually.
+ */
+
+#include "OpenAPIStoreApi.h"
+
+#include "OpenAPIStoreApiOperations.h"
+#include "OpenAPIModule.h"
+
+#include "HttpModule.h"
+#include "Serialization/JsonSerializer.h"
+
+namespace OpenAPI
+{
+
+OpenAPIStoreApi::OpenAPIStoreApi()
+: Url(TEXT("http://petstore.swagger.io/v2"))
+{
+}
+
+OpenAPIStoreApi::~OpenAPIStoreApi() {}
+
+void OpenAPIStoreApi::SetURL(const FString& InUrl)
+{
+ Url = InUrl;
+}
+
+void OpenAPIStoreApi::AddHeaderParam(const FString& Key, const FString& Value)
+{
+ AdditionalHeaderParams.Add(Key, Value);
+}
+
+void OpenAPIStoreApi::ClearHeaderParams()
+{
+ AdditionalHeaderParams.Reset();
+}
+
+bool OpenAPIStoreApi::IsValid() const
+{
+ if (Url.IsEmpty())
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("OpenAPIStoreApi: Endpoint Url is not set, request cannot be performed"));
+ return false;
+ }
+
+ return true;
+}
+
+void OpenAPIStoreApi::HandleResponse(FHttpResponsePtr HttpResponse, bool bSucceeded, Response& InOutResponse) const
+{
+ InOutResponse.SetHttpResponse(HttpResponse);
+ InOutResponse.SetSuccessful(bSucceeded);
+
+ if (bSucceeded && HttpResponse.IsValid())
+ {
+ InOutResponse.SetHttpResponseCode((EHttpResponseCodes::Type)HttpResponse->GetResponseCode());
+ FString ContentType = HttpResponse->GetContentType();
+ FString Content;
+
+ if (ContentType == TEXT("application/json"))
+ {
+ Content = HttpResponse->GetContentAsString();
+
+ TSharedPtr JsonValue;
+ auto Reader = TJsonReaderFactory<>::Create(Content);
+
+ if (FJsonSerializer::Deserialize(Reader, JsonValue) && JsonValue.IsValid())
+ {
+ if (InOutResponse.FromJson(JsonValue))
+ return; // Successfully parsed
+ }
+ }
+ else if(ContentType == TEXT("text/plain"))
+ {
+ Content = HttpResponse->GetContentAsString();
+ InOutResponse.SetResponseString(Content);
+ return; // Successfully parsed
+ }
+
+ // Report the parse error but do not mark the request as unsuccessful. Data could be partial or malformed, but the request succeeded.
+ UE_LOG(LogOpenAPI, Error, TEXT("Failed to deserialize Http response content (type:%s):\n%s"), *ContentType , *Content);
+ return;
+ }
+
+ // By default, assume we failed to establish connection
+ InOutResponse.SetHttpResponseCode(EHttpResponseCodes::RequestTimeout);
+}
+
+bool OpenAPIStoreApi::DeleteOrder(const DeleteOrderRequest& Request, const FDeleteOrderDelegate& Delegate /*= FDeleteOrderDelegate()*/) const
+{
+ if (!IsValid())
+ return false;
+
+ TSharedRef HttpRequest = FHttpModule::Get().CreateRequest();
+ HttpRequest->SetURL(*(Url + Request.ComputePath()));
+
+ for(const auto& It : AdditionalHeaderParams)
+ {
+ HttpRequest->SetHeader(It.Key, It.Value);
+ }
+
+ Request.SetupHttpRequest(HttpRequest);
+
+ HttpRequest->OnProcessRequestComplete().BindRaw(this, &OpenAPIStoreApi::OnDeleteOrderResponse, Delegate);
+ return HttpRequest->ProcessRequest();
+}
+
+void OpenAPIStoreApi::OnDeleteOrderResponse(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, FDeleteOrderDelegate Delegate) const
+{
+ DeleteOrderResponse Response;
+ HandleResponse(HttpResponse, bSucceeded, Response);
+ Delegate.ExecuteIfBound(Response);
+}
+
+bool OpenAPIStoreApi::GetInventory(const GetInventoryRequest& Request, const FGetInventoryDelegate& Delegate /*= FGetInventoryDelegate()*/) const
+{
+ if (!IsValid())
+ return false;
+
+ TSharedRef HttpRequest = FHttpModule::Get().CreateRequest();
+ HttpRequest->SetURL(*(Url + Request.ComputePath()));
+
+ for(const auto& It : AdditionalHeaderParams)
+ {
+ HttpRequest->SetHeader(It.Key, It.Value);
+ }
+
+ Request.SetupHttpRequest(HttpRequest);
+
+ HttpRequest->OnProcessRequestComplete().BindRaw(this, &OpenAPIStoreApi::OnGetInventoryResponse, Delegate);
+ return HttpRequest->ProcessRequest();
+}
+
+void OpenAPIStoreApi::OnGetInventoryResponse(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, FGetInventoryDelegate Delegate) const
+{
+ GetInventoryResponse Response;
+ HandleResponse(HttpResponse, bSucceeded, Response);
+ Delegate.ExecuteIfBound(Response);
+}
+
+bool OpenAPIStoreApi::GetOrderById(const GetOrderByIdRequest& Request, const FGetOrderByIdDelegate& Delegate /*= FGetOrderByIdDelegate()*/) const
+{
+ if (!IsValid())
+ return false;
+
+ TSharedRef HttpRequest = FHttpModule::Get().CreateRequest();
+ HttpRequest->SetURL(*(Url + Request.ComputePath()));
+
+ for(const auto& It : AdditionalHeaderParams)
+ {
+ HttpRequest->SetHeader(It.Key, It.Value);
+ }
+
+ Request.SetupHttpRequest(HttpRequest);
+
+ HttpRequest->OnProcessRequestComplete().BindRaw(this, &OpenAPIStoreApi::OnGetOrderByIdResponse, Delegate);
+ return HttpRequest->ProcessRequest();
+}
+
+void OpenAPIStoreApi::OnGetOrderByIdResponse(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, FGetOrderByIdDelegate Delegate) const
+{
+ GetOrderByIdResponse Response;
+ HandleResponse(HttpResponse, bSucceeded, Response);
+ Delegate.ExecuteIfBound(Response);
+}
+
+bool OpenAPIStoreApi::PlaceOrder(const PlaceOrderRequest& Request, const FPlaceOrderDelegate& Delegate /*= FPlaceOrderDelegate()*/) const
+{
+ if (!IsValid())
+ return false;
+
+ TSharedRef HttpRequest = FHttpModule::Get().CreateRequest();
+ HttpRequest->SetURL(*(Url + Request.ComputePath()));
+
+ for(const auto& It : AdditionalHeaderParams)
+ {
+ HttpRequest->SetHeader(It.Key, It.Value);
+ }
+
+ Request.SetupHttpRequest(HttpRequest);
+
+ HttpRequest->OnProcessRequestComplete().BindRaw(this, &OpenAPIStoreApi::OnPlaceOrderResponse, Delegate);
+ return HttpRequest->ProcessRequest();
+}
+
+void OpenAPIStoreApi::OnPlaceOrderResponse(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, FPlaceOrderDelegate Delegate) const
+{
+ PlaceOrderResponse Response;
+ HandleResponse(HttpResponse, bSucceeded, Response);
+ Delegate.ExecuteIfBound(Response);
+}
+
+}
diff --git a/samples/client/petstore/cpp-ue4/Private/OpenAPIStoreApiOperations.cpp b/samples/client/petstore/cpp-ue4/Private/OpenAPIStoreApiOperations.cpp
new file mode 100644
index 000000000000..d28de39cf14c
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/Private/OpenAPIStoreApiOperations.cpp
@@ -0,0 +1,242 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator
+ * https://github.com/OpenAPITools/openapi-generator
+ * Do not edit the class manually.
+ */
+
+#include "OpenAPIStoreApiOperations.h"
+
+#include "OpenAPIModule.h"
+#include "OpenAPIHelpers.h"
+
+#include "Dom/JsonObject.h"
+#include "Templates/SharedPointer.h"
+#include "HttpModule.h"
+#include "PlatformHttp.h"
+
+namespace OpenAPI
+{
+
+FString OpenAPIStoreApi::DeleteOrderRequest::ComputePath() const
+{
+ TMap PathParams = {
+ { TEXT("orderId"), ToStringFormatArg(OrderId) } };
+
+ FString Path = FString::Format(TEXT("/store/order/{orderId}"), PathParams);
+
+ return Path;
+}
+
+void OpenAPIStoreApi::DeleteOrderRequest::SetupHttpRequest(const TSharedRef& HttpRequest) const
+{
+ static const TArray Consumes = { };
+ //static const TArray Produces = { };
+
+ HttpRequest->SetVerb(TEXT("DELETE"));
+
+ // Default to Json Body request
+ if (Consumes.Num() == 0 || Consumes.Contains(TEXT("application/json")))
+ {
+ }
+ else if (Consumes.Contains(TEXT("multipart/form-data")))
+ {
+ }
+ else if (Consumes.Contains(TEXT("application/x-www-form-urlencoded")))
+ {
+ }
+ else
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Request ContentType not supported (%s)"), *FString::Join(Consumes, TEXT(",")));
+ }
+}
+
+void OpenAPIStoreApi::DeleteOrderResponse::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
+{
+ Response::SetHttpResponseCode(InHttpResponseCode);
+ switch ((int)InHttpResponseCode)
+ {
+ case 400:
+ SetResponseString(TEXT("Invalid ID supplied"));
+ break;
+ case 404:
+ SetResponseString(TEXT("Order not found"));
+ break;
+ }
+}
+
+bool OpenAPIStoreApi::DeleteOrderResponse::FromJson(const TSharedPtr& JsonValue)
+{
+ return true;
+}
+
+FString OpenAPIStoreApi::GetInventoryRequest::ComputePath() const
+{
+ FString Path(TEXT("/store/inventory"));
+ return Path;
+}
+
+void OpenAPIStoreApi::GetInventoryRequest::SetupHttpRequest(const TSharedRef& HttpRequest) const
+{
+ static const TArray Consumes = { };
+ //static const TArray Produces = { TEXT("application/json") };
+
+ HttpRequest->SetVerb(TEXT("GET"));
+
+ // Default to Json Body request
+ if (Consumes.Num() == 0 || Consumes.Contains(TEXT("application/json")))
+ {
+ }
+ else if (Consumes.Contains(TEXT("multipart/form-data")))
+ {
+ }
+ else if (Consumes.Contains(TEXT("application/x-www-form-urlencoded")))
+ {
+ }
+ else
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Request ContentType not supported (%s)"), *FString::Join(Consumes, TEXT(",")));
+ }
+}
+
+void OpenAPIStoreApi::GetInventoryResponse::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
+{
+ Response::SetHttpResponseCode(InHttpResponseCode);
+ switch ((int)InHttpResponseCode)
+ {
+ case 200:
+ default:
+ SetResponseString(TEXT("successful operation"));
+ break;
+ }
+}
+
+bool OpenAPIStoreApi::GetInventoryResponse::FromJson(const TSharedPtr& JsonValue)
+{
+ return TryGetJsonValue(JsonValue, Content);
+}
+
+FString OpenAPIStoreApi::GetOrderByIdRequest::ComputePath() const
+{
+ TMap PathParams = {
+ { TEXT("orderId"), ToStringFormatArg(OrderId) } };
+
+ FString Path = FString::Format(TEXT("/store/order/{orderId}"), PathParams);
+
+ return Path;
+}
+
+void OpenAPIStoreApi::GetOrderByIdRequest::SetupHttpRequest(const TSharedRef& HttpRequest) const
+{
+ static const TArray Consumes = { };
+ //static const TArray Produces = { TEXT("application/xml"), TEXT("application/json") };
+
+ HttpRequest->SetVerb(TEXT("GET"));
+
+ // Default to Json Body request
+ if (Consumes.Num() == 0 || Consumes.Contains(TEXT("application/json")))
+ {
+ }
+ else if (Consumes.Contains(TEXT("multipart/form-data")))
+ {
+ }
+ else if (Consumes.Contains(TEXT("application/x-www-form-urlencoded")))
+ {
+ }
+ else
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Request ContentType not supported (%s)"), *FString::Join(Consumes, TEXT(",")));
+ }
+}
+
+void OpenAPIStoreApi::GetOrderByIdResponse::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
+{
+ Response::SetHttpResponseCode(InHttpResponseCode);
+ switch ((int)InHttpResponseCode)
+ {
+ case 200:
+ default:
+ SetResponseString(TEXT("successful operation"));
+ break;
+ case 400:
+ SetResponseString(TEXT("Invalid ID supplied"));
+ break;
+ case 404:
+ SetResponseString(TEXT("Order not found"));
+ break;
+ }
+}
+
+bool OpenAPIStoreApi::GetOrderByIdResponse::FromJson(const TSharedPtr& JsonValue)
+{
+ return TryGetJsonValue(JsonValue, Content);
+}
+
+FString OpenAPIStoreApi::PlaceOrderRequest::ComputePath() const
+{
+ FString Path(TEXT("/store/order"));
+ return Path;
+}
+
+void OpenAPIStoreApi::PlaceOrderRequest::SetupHttpRequest(const TSharedRef& HttpRequest) const
+{
+ static const TArray Consumes = { };
+ //static const TArray Produces = { TEXT("application/xml"), TEXT("application/json") };
+
+ HttpRequest->SetVerb(TEXT("POST"));
+
+ // Default to Json Body request
+ if (Consumes.Num() == 0 || Consumes.Contains(TEXT("application/json")))
+ {
+ // Body parameters
+ FString JsonBody;
+ JsonWriter Writer = TJsonWriterFactory<>::Create(&JsonBody);
+
+ Writer->WriteObjectStart();
+ Writer->WriteIdentifierPrefix(TEXT("body")); WriteJsonValue(Writer, Body);
+ Writer->WriteObjectEnd();
+ Writer->Close();
+
+ HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json; charset=utf-8"));
+ HttpRequest->SetContentAsString(JsonBody);
+ }
+ else if (Consumes.Contains(TEXT("multipart/form-data")))
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Body parameter (body) was ignored, not supported in multipart form"));
+ }
+ else if (Consumes.Contains(TEXT("application/x-www-form-urlencoded")))
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Body parameter (body) was ignored, not supported in urlencoded requests"));
+ }
+ else
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Request ContentType not supported (%s)"), *FString::Join(Consumes, TEXT(",")));
+ }
+}
+
+void OpenAPIStoreApi::PlaceOrderResponse::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
+{
+ Response::SetHttpResponseCode(InHttpResponseCode);
+ switch ((int)InHttpResponseCode)
+ {
+ case 200:
+ default:
+ SetResponseString(TEXT("successful operation"));
+ break;
+ case 400:
+ SetResponseString(TEXT("Invalid Order"));
+ break;
+ }
+}
+
+bool OpenAPIStoreApi::PlaceOrderResponse::FromJson(const TSharedPtr& JsonValue)
+{
+ return TryGetJsonValue(JsonValue, Content);
+}
+
+}
diff --git a/samples/client/petstore/cpp-ue4/Private/OpenAPIUserApi.cpp b/samples/client/petstore/cpp-ue4/Private/OpenAPIUserApi.cpp
new file mode 100644
index 000000000000..c079f042d92d
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/Private/OpenAPIUserApi.cpp
@@ -0,0 +1,305 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator
+ * https://github.com/OpenAPITools/openapi-generator
+ * Do not edit the class manually.
+ */
+
+#include "OpenAPIUserApi.h"
+
+#include "OpenAPIUserApiOperations.h"
+#include "OpenAPIModule.h"
+
+#include "HttpModule.h"
+#include "Serialization/JsonSerializer.h"
+
+namespace OpenAPI
+{
+
+OpenAPIUserApi::OpenAPIUserApi()
+: Url(TEXT("http://petstore.swagger.io/v2"))
+{
+}
+
+OpenAPIUserApi::~OpenAPIUserApi() {}
+
+void OpenAPIUserApi::SetURL(const FString& InUrl)
+{
+ Url = InUrl;
+}
+
+void OpenAPIUserApi::AddHeaderParam(const FString& Key, const FString& Value)
+{
+ AdditionalHeaderParams.Add(Key, Value);
+}
+
+void OpenAPIUserApi::ClearHeaderParams()
+{
+ AdditionalHeaderParams.Reset();
+}
+
+bool OpenAPIUserApi::IsValid() const
+{
+ if (Url.IsEmpty())
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("OpenAPIUserApi: Endpoint Url is not set, request cannot be performed"));
+ return false;
+ }
+
+ return true;
+}
+
+void OpenAPIUserApi::HandleResponse(FHttpResponsePtr HttpResponse, bool bSucceeded, Response& InOutResponse) const
+{
+ InOutResponse.SetHttpResponse(HttpResponse);
+ InOutResponse.SetSuccessful(bSucceeded);
+
+ if (bSucceeded && HttpResponse.IsValid())
+ {
+ InOutResponse.SetHttpResponseCode((EHttpResponseCodes::Type)HttpResponse->GetResponseCode());
+ FString ContentType = HttpResponse->GetContentType();
+ FString Content;
+
+ if (ContentType == TEXT("application/json"))
+ {
+ Content = HttpResponse->GetContentAsString();
+
+ TSharedPtr JsonValue;
+ auto Reader = TJsonReaderFactory<>::Create(Content);
+
+ if (FJsonSerializer::Deserialize(Reader, JsonValue) && JsonValue.IsValid())
+ {
+ if (InOutResponse.FromJson(JsonValue))
+ return; // Successfully parsed
+ }
+ }
+ else if(ContentType == TEXT("text/plain"))
+ {
+ Content = HttpResponse->GetContentAsString();
+ InOutResponse.SetResponseString(Content);
+ return; // Successfully parsed
+ }
+
+ // Report the parse error but do not mark the request as unsuccessful. Data could be partial or malformed, but the request succeeded.
+ UE_LOG(LogOpenAPI, Error, TEXT("Failed to deserialize Http response content (type:%s):\n%s"), *ContentType , *Content);
+ return;
+ }
+
+ // By default, assume we failed to establish connection
+ InOutResponse.SetHttpResponseCode(EHttpResponseCodes::RequestTimeout);
+}
+
+bool OpenAPIUserApi::CreateUser(const CreateUserRequest& Request, const FCreateUserDelegate& Delegate /*= FCreateUserDelegate()*/) const
+{
+ if (!IsValid())
+ return false;
+
+ TSharedRef HttpRequest = FHttpModule::Get().CreateRequest();
+ HttpRequest->SetURL(*(Url + Request.ComputePath()));
+
+ for(const auto& It : AdditionalHeaderParams)
+ {
+ HttpRequest->SetHeader(It.Key, It.Value);
+ }
+
+ Request.SetupHttpRequest(HttpRequest);
+
+ HttpRequest->OnProcessRequestComplete().BindRaw(this, &OpenAPIUserApi::OnCreateUserResponse, Delegate);
+ return HttpRequest->ProcessRequest();
+}
+
+void OpenAPIUserApi::OnCreateUserResponse(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, FCreateUserDelegate Delegate) const
+{
+ CreateUserResponse Response;
+ HandleResponse(HttpResponse, bSucceeded, Response);
+ Delegate.ExecuteIfBound(Response);
+}
+
+bool OpenAPIUserApi::CreateUsersWithArrayInput(const CreateUsersWithArrayInputRequest& Request, const FCreateUsersWithArrayInputDelegate& Delegate /*= FCreateUsersWithArrayInputDelegate()*/) const
+{
+ if (!IsValid())
+ return false;
+
+ TSharedRef HttpRequest = FHttpModule::Get().CreateRequest();
+ HttpRequest->SetURL(*(Url + Request.ComputePath()));
+
+ for(const auto& It : AdditionalHeaderParams)
+ {
+ HttpRequest->SetHeader(It.Key, It.Value);
+ }
+
+ Request.SetupHttpRequest(HttpRequest);
+
+ HttpRequest->OnProcessRequestComplete().BindRaw(this, &OpenAPIUserApi::OnCreateUsersWithArrayInputResponse, Delegate);
+ return HttpRequest->ProcessRequest();
+}
+
+void OpenAPIUserApi::OnCreateUsersWithArrayInputResponse(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, FCreateUsersWithArrayInputDelegate Delegate) const
+{
+ CreateUsersWithArrayInputResponse Response;
+ HandleResponse(HttpResponse, bSucceeded, Response);
+ Delegate.ExecuteIfBound(Response);
+}
+
+bool OpenAPIUserApi::CreateUsersWithListInput(const CreateUsersWithListInputRequest& Request, const FCreateUsersWithListInputDelegate& Delegate /*= FCreateUsersWithListInputDelegate()*/) const
+{
+ if (!IsValid())
+ return false;
+
+ TSharedRef HttpRequest = FHttpModule::Get().CreateRequest();
+ HttpRequest->SetURL(*(Url + Request.ComputePath()));
+
+ for(const auto& It : AdditionalHeaderParams)
+ {
+ HttpRequest->SetHeader(It.Key, It.Value);
+ }
+
+ Request.SetupHttpRequest(HttpRequest);
+
+ HttpRequest->OnProcessRequestComplete().BindRaw(this, &OpenAPIUserApi::OnCreateUsersWithListInputResponse, Delegate);
+ return HttpRequest->ProcessRequest();
+}
+
+void OpenAPIUserApi::OnCreateUsersWithListInputResponse(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, FCreateUsersWithListInputDelegate Delegate) const
+{
+ CreateUsersWithListInputResponse Response;
+ HandleResponse(HttpResponse, bSucceeded, Response);
+ Delegate.ExecuteIfBound(Response);
+}
+
+bool OpenAPIUserApi::DeleteUser(const DeleteUserRequest& Request, const FDeleteUserDelegate& Delegate /*= FDeleteUserDelegate()*/) const
+{
+ if (!IsValid())
+ return false;
+
+ TSharedRef HttpRequest = FHttpModule::Get().CreateRequest();
+ HttpRequest->SetURL(*(Url + Request.ComputePath()));
+
+ for(const auto& It : AdditionalHeaderParams)
+ {
+ HttpRequest->SetHeader(It.Key, It.Value);
+ }
+
+ Request.SetupHttpRequest(HttpRequest);
+
+ HttpRequest->OnProcessRequestComplete().BindRaw(this, &OpenAPIUserApi::OnDeleteUserResponse, Delegate);
+ return HttpRequest->ProcessRequest();
+}
+
+void OpenAPIUserApi::OnDeleteUserResponse(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, FDeleteUserDelegate Delegate) const
+{
+ DeleteUserResponse Response;
+ HandleResponse(HttpResponse, bSucceeded, Response);
+ Delegate.ExecuteIfBound(Response);
+}
+
+bool OpenAPIUserApi::GetUserByName(const GetUserByNameRequest& Request, const FGetUserByNameDelegate& Delegate /*= FGetUserByNameDelegate()*/) const
+{
+ if (!IsValid())
+ return false;
+
+ TSharedRef HttpRequest = FHttpModule::Get().CreateRequest();
+ HttpRequest->SetURL(*(Url + Request.ComputePath()));
+
+ for(const auto& It : AdditionalHeaderParams)
+ {
+ HttpRequest->SetHeader(It.Key, It.Value);
+ }
+
+ Request.SetupHttpRequest(HttpRequest);
+
+ HttpRequest->OnProcessRequestComplete().BindRaw(this, &OpenAPIUserApi::OnGetUserByNameResponse, Delegate);
+ return HttpRequest->ProcessRequest();
+}
+
+void OpenAPIUserApi::OnGetUserByNameResponse(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, FGetUserByNameDelegate Delegate) const
+{
+ GetUserByNameResponse Response;
+ HandleResponse(HttpResponse, bSucceeded, Response);
+ Delegate.ExecuteIfBound(Response);
+}
+
+bool OpenAPIUserApi::LoginUser(const LoginUserRequest& Request, const FLoginUserDelegate& Delegate /*= FLoginUserDelegate()*/) const
+{
+ if (!IsValid())
+ return false;
+
+ TSharedRef HttpRequest = FHttpModule::Get().CreateRequest();
+ HttpRequest->SetURL(*(Url + Request.ComputePath()));
+
+ for(const auto& It : AdditionalHeaderParams)
+ {
+ HttpRequest->SetHeader(It.Key, It.Value);
+ }
+
+ Request.SetupHttpRequest(HttpRequest);
+
+ HttpRequest->OnProcessRequestComplete().BindRaw(this, &OpenAPIUserApi::OnLoginUserResponse, Delegate);
+ return HttpRequest->ProcessRequest();
+}
+
+void OpenAPIUserApi::OnLoginUserResponse(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, FLoginUserDelegate Delegate) const
+{
+ LoginUserResponse Response;
+ HandleResponse(HttpResponse, bSucceeded, Response);
+ Delegate.ExecuteIfBound(Response);
+}
+
+bool OpenAPIUserApi::LogoutUser(const LogoutUserRequest& Request, const FLogoutUserDelegate& Delegate /*= FLogoutUserDelegate()*/) const
+{
+ if (!IsValid())
+ return false;
+
+ TSharedRef HttpRequest = FHttpModule::Get().CreateRequest();
+ HttpRequest->SetURL(*(Url + Request.ComputePath()));
+
+ for(const auto& It : AdditionalHeaderParams)
+ {
+ HttpRequest->SetHeader(It.Key, It.Value);
+ }
+
+ Request.SetupHttpRequest(HttpRequest);
+
+ HttpRequest->OnProcessRequestComplete().BindRaw(this, &OpenAPIUserApi::OnLogoutUserResponse, Delegate);
+ return HttpRequest->ProcessRequest();
+}
+
+void OpenAPIUserApi::OnLogoutUserResponse(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, FLogoutUserDelegate Delegate) const
+{
+ LogoutUserResponse Response;
+ HandleResponse(HttpResponse, bSucceeded, Response);
+ Delegate.ExecuteIfBound(Response);
+}
+
+bool OpenAPIUserApi::UpdateUser(const UpdateUserRequest& Request, const FUpdateUserDelegate& Delegate /*= FUpdateUserDelegate()*/) const
+{
+ if (!IsValid())
+ return false;
+
+ TSharedRef HttpRequest = FHttpModule::Get().CreateRequest();
+ HttpRequest->SetURL(*(Url + Request.ComputePath()));
+
+ for(const auto& It : AdditionalHeaderParams)
+ {
+ HttpRequest->SetHeader(It.Key, It.Value);
+ }
+
+ Request.SetupHttpRequest(HttpRequest);
+
+ HttpRequest->OnProcessRequestComplete().BindRaw(this, &OpenAPIUserApi::OnUpdateUserResponse, Delegate);
+ return HttpRequest->ProcessRequest();
+}
+
+void OpenAPIUserApi::OnUpdateUserResponse(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded, FUpdateUserDelegate Delegate) const
+{
+ UpdateUserResponse Response;
+ HandleResponse(HttpResponse, bSucceeded, Response);
+ Delegate.ExecuteIfBound(Response);
+}
+
+}
diff --git a/samples/client/petstore/cpp-ue4/Private/OpenAPIUserApiOperations.cpp b/samples/client/petstore/cpp-ue4/Private/OpenAPIUserApiOperations.cpp
new file mode 100644
index 000000000000..c31afe5ba13e
--- /dev/null
+++ b/samples/client/petstore/cpp-ue4/Private/OpenAPIUserApiOperations.cpp
@@ -0,0 +1,477 @@
+/**
+ * OpenAPI Petstore
+ * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
+ *
+ * OpenAPI spec version: 1.0.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator
+ * https://github.com/OpenAPITools/openapi-generator
+ * Do not edit the class manually.
+ */
+
+#include "OpenAPIUserApiOperations.h"
+
+#include "OpenAPIModule.h"
+#include "OpenAPIHelpers.h"
+
+#include "Dom/JsonObject.h"
+#include "Templates/SharedPointer.h"
+#include "HttpModule.h"
+#include "PlatformHttp.h"
+
+namespace OpenAPI
+{
+
+FString OpenAPIUserApi::CreateUserRequest::ComputePath() const
+{
+ FString Path(TEXT("/user"));
+ return Path;
+}
+
+void OpenAPIUserApi::CreateUserRequest::SetupHttpRequest(const TSharedRef& HttpRequest) const
+{
+ static const TArray Consumes = { };
+ //static const TArray Produces = { };
+
+ HttpRequest->SetVerb(TEXT("POST"));
+
+ // Default to Json Body request
+ if (Consumes.Num() == 0 || Consumes.Contains(TEXT("application/json")))
+ {
+ // Body parameters
+ FString JsonBody;
+ JsonWriter Writer = TJsonWriterFactory<>::Create(&JsonBody);
+
+ Writer->WriteObjectStart();
+ Writer->WriteIdentifierPrefix(TEXT("body")); WriteJsonValue(Writer, Body);
+ Writer->WriteObjectEnd();
+ Writer->Close();
+
+ HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json; charset=utf-8"));
+ HttpRequest->SetContentAsString(JsonBody);
+ }
+ else if (Consumes.Contains(TEXT("multipart/form-data")))
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Body parameter (body) was ignored, not supported in multipart form"));
+ }
+ else if (Consumes.Contains(TEXT("application/x-www-form-urlencoded")))
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Body parameter (body) was ignored, not supported in urlencoded requests"));
+ }
+ else
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Request ContentType not supported (%s)"), *FString::Join(Consumes, TEXT(",")));
+ }
+}
+
+void OpenAPIUserApi::CreateUserResponse::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
+{
+ Response::SetHttpResponseCode(InHttpResponseCode);
+ switch ((int)InHttpResponseCode)
+ {
+ case 0:
+ default:
+ SetResponseString(TEXT("successful operation"));
+ break;
+ }
+}
+
+bool OpenAPIUserApi::CreateUserResponse::FromJson(const TSharedPtr& JsonValue)
+{
+ return true;
+}
+
+FString OpenAPIUserApi::CreateUsersWithArrayInputRequest::ComputePath() const
+{
+ FString Path(TEXT("/user/createWithArray"));
+ return Path;
+}
+
+void OpenAPIUserApi::CreateUsersWithArrayInputRequest::SetupHttpRequest(const TSharedRef& HttpRequest) const
+{
+ static const TArray Consumes = { };
+ //static const TArray Produces = { };
+
+ HttpRequest->SetVerb(TEXT("POST"));
+
+ // Default to Json Body request
+ if (Consumes.Num() == 0 || Consumes.Contains(TEXT("application/json")))
+ {
+ // Body parameters
+ FString JsonBody;
+ JsonWriter Writer = TJsonWriterFactory<>::Create(&JsonBody);
+
+ Writer->WriteObjectStart();
+ Writer->WriteIdentifierPrefix(TEXT("body")); WriteJsonValue(Writer, Body);
+ Writer->WriteObjectEnd();
+ Writer->Close();
+
+ HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json; charset=utf-8"));
+ HttpRequest->SetContentAsString(JsonBody);
+ }
+ else if (Consumes.Contains(TEXT("multipart/form-data")))
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Body parameter (body) was ignored, not supported in multipart form"));
+ }
+ else if (Consumes.Contains(TEXT("application/x-www-form-urlencoded")))
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Body parameter (body) was ignored, not supported in urlencoded requests"));
+ }
+ else
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Request ContentType not supported (%s)"), *FString::Join(Consumes, TEXT(",")));
+ }
+}
+
+void OpenAPIUserApi::CreateUsersWithArrayInputResponse::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
+{
+ Response::SetHttpResponseCode(InHttpResponseCode);
+ switch ((int)InHttpResponseCode)
+ {
+ case 0:
+ default:
+ SetResponseString(TEXT("successful operation"));
+ break;
+ }
+}
+
+bool OpenAPIUserApi::CreateUsersWithArrayInputResponse::FromJson(const TSharedPtr& JsonValue)
+{
+ return true;
+}
+
+FString OpenAPIUserApi::CreateUsersWithListInputRequest::ComputePath() const
+{
+ FString Path(TEXT("/user/createWithList"));
+ return Path;
+}
+
+void OpenAPIUserApi::CreateUsersWithListInputRequest::SetupHttpRequest(const TSharedRef& HttpRequest) const
+{
+ static const TArray Consumes = { };
+ //static const TArray Produces = { };
+
+ HttpRequest->SetVerb(TEXT("POST"));
+
+ // Default to Json Body request
+ if (Consumes.Num() == 0 || Consumes.Contains(TEXT("application/json")))
+ {
+ // Body parameters
+ FString JsonBody;
+ JsonWriter Writer = TJsonWriterFactory<>::Create(&JsonBody);
+
+ Writer->WriteObjectStart();
+ Writer->WriteIdentifierPrefix(TEXT("body")); WriteJsonValue(Writer, Body);
+ Writer->WriteObjectEnd();
+ Writer->Close();
+
+ HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json; charset=utf-8"));
+ HttpRequest->SetContentAsString(JsonBody);
+ }
+ else if (Consumes.Contains(TEXT("multipart/form-data")))
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Body parameter (body) was ignored, not supported in multipart form"));
+ }
+ else if (Consumes.Contains(TEXT("application/x-www-form-urlencoded")))
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Body parameter (body) was ignored, not supported in urlencoded requests"));
+ }
+ else
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Request ContentType not supported (%s)"), *FString::Join(Consumes, TEXT(",")));
+ }
+}
+
+void OpenAPIUserApi::CreateUsersWithListInputResponse::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
+{
+ Response::SetHttpResponseCode(InHttpResponseCode);
+ switch ((int)InHttpResponseCode)
+ {
+ case 0:
+ default:
+ SetResponseString(TEXT("successful operation"));
+ break;
+ }
+}
+
+bool OpenAPIUserApi::CreateUsersWithListInputResponse::FromJson(const TSharedPtr& JsonValue)
+{
+ return true;
+}
+
+FString OpenAPIUserApi::DeleteUserRequest::ComputePath() const
+{
+ TMap PathParams = {
+ { TEXT("username"), ToStringFormatArg(Username) } };
+
+ FString Path = FString::Format(TEXT("/user/{username}"), PathParams);
+
+ return Path;
+}
+
+void OpenAPIUserApi::DeleteUserRequest::SetupHttpRequest(const TSharedRef& HttpRequest) const
+{
+ static const TArray Consumes = { };
+ //static const TArray Produces = { };
+
+ HttpRequest->SetVerb(TEXT("DELETE"));
+
+ // Default to Json Body request
+ if (Consumes.Num() == 0 || Consumes.Contains(TEXT("application/json")))
+ {
+ }
+ else if (Consumes.Contains(TEXT("multipart/form-data")))
+ {
+ }
+ else if (Consumes.Contains(TEXT("application/x-www-form-urlencoded")))
+ {
+ }
+ else
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Request ContentType not supported (%s)"), *FString::Join(Consumes, TEXT(",")));
+ }
+}
+
+void OpenAPIUserApi::DeleteUserResponse::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
+{
+ Response::SetHttpResponseCode(InHttpResponseCode);
+ switch ((int)InHttpResponseCode)
+ {
+ case 400:
+ SetResponseString(TEXT("Invalid username supplied"));
+ break;
+ case 404:
+ SetResponseString(TEXT("User not found"));
+ break;
+ }
+}
+
+bool OpenAPIUserApi::DeleteUserResponse::FromJson(const TSharedPtr& JsonValue)
+{
+ return true;
+}
+
+FString OpenAPIUserApi::GetUserByNameRequest::ComputePath() const
+{
+ TMap PathParams = {
+ { TEXT("username"), ToStringFormatArg(Username) } };
+
+ FString Path = FString::Format(TEXT("/user/{username}"), PathParams);
+
+ return Path;
+}
+
+void OpenAPIUserApi::GetUserByNameRequest::SetupHttpRequest(const TSharedRef& HttpRequest) const
+{
+ static const TArray Consumes = { };
+ //static const TArray Produces = { TEXT("application/xml"), TEXT("application/json") };
+
+ HttpRequest->SetVerb(TEXT("GET"));
+
+ // Default to Json Body request
+ if (Consumes.Num() == 0 || Consumes.Contains(TEXT("application/json")))
+ {
+ }
+ else if (Consumes.Contains(TEXT("multipart/form-data")))
+ {
+ }
+ else if (Consumes.Contains(TEXT("application/x-www-form-urlencoded")))
+ {
+ }
+ else
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Request ContentType not supported (%s)"), *FString::Join(Consumes, TEXT(",")));
+ }
+}
+
+void OpenAPIUserApi::GetUserByNameResponse::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
+{
+ Response::SetHttpResponseCode(InHttpResponseCode);
+ switch ((int)InHttpResponseCode)
+ {
+ case 200:
+ default:
+ SetResponseString(TEXT("successful operation"));
+ break;
+ case 400:
+ SetResponseString(TEXT("Invalid username supplied"));
+ break;
+ case 404:
+ SetResponseString(TEXT("User not found"));
+ break;
+ }
+}
+
+bool OpenAPIUserApi::GetUserByNameResponse::FromJson(const TSharedPtr& JsonValue)
+{
+ return TryGetJsonValue(JsonValue, Content);
+}
+
+FString OpenAPIUserApi::LoginUserRequest::ComputePath() const
+{
+ FString Path(TEXT("/user/login"));
+ TArray QueryParams;
+ QueryParams.Add(FString(TEXT("username=")) + ToUrlString(Username));
+ QueryParams.Add(FString(TEXT("password=")) + ToUrlString(Password));
+ Path += TCHAR('?');
+ Path += FString::Join(QueryParams, TEXT("&"));
+
+ return Path;
+}
+
+void OpenAPIUserApi::LoginUserRequest::SetupHttpRequest(const TSharedRef& HttpRequest) const
+{
+ static const TArray Consumes = { };
+ //static const TArray Produces = { TEXT("application/xml"), TEXT("application/json") };
+
+ HttpRequest->SetVerb(TEXT("GET"));
+
+ // Default to Json Body request
+ if (Consumes.Num() == 0 || Consumes.Contains(TEXT("application/json")))
+ {
+ }
+ else if (Consumes.Contains(TEXT("multipart/form-data")))
+ {
+ }
+ else if (Consumes.Contains(TEXT("application/x-www-form-urlencoded")))
+ {
+ }
+ else
+ {
+ UE_LOG(LogOpenAPI, Error, TEXT("Request ContentType not supported (%s)"), *FString::Join(Consumes, TEXT(",")));
+ }
+}
+
+void OpenAPIUserApi::LoginUserResponse::SetHttpResponseCode(EHttpResponseCodes::Type InHttpResponseCode)
+{
+ Response::SetHttpResponseCode(InHttpResponseCode);
+ switch ((int)InHttpResponseCode)
+ {
+ case 200:
+ default:
+ SetResponseString(TEXT("successful operation"));
+ break;
+ case 400:
+ SetResponseString(TEXT("Invalid username/password supplied"));
+ break;
+ }
+}
+
+bool OpenAPIUserApi::LoginUserResponse::FromJson(const TSharedPtr& JsonValue)
+{
+ return TryGetJsonValue(JsonValue, Content);
+}
+
+FString OpenAPIUserApi::LogoutUserRequest::ComputePath() const
+{
+ FString Path(TEXT("/user/logout"));
+ return Path;
+}
+
+void OpenAPIUserApi::LogoutUserRequest::SetupHttpRequest(const TSharedRef