diff --git a/.github/workflows/samples-spring.yaml b/.github/workflows/samples-spring.yaml index 74b901fe0676..e145efb18285 100644 --- a/.github/workflows/samples-spring.yaml +++ b/.github/workflows/samples-spring.yaml @@ -44,6 +44,8 @@ jobs: - samples/server/petstore/spring-boot-nullable-set - samples/server/petstore/spring-boot-defaultInterface-unhandledExcp - samples/server/petstore/springboot + - samples/server/petstore/springboot-byte-format-edge-cases + - samples/server/petstore/springboot-byte-format-edge-cases-reactive - samples/server/petstore/springboot-include-http-request-context - samples/server/petstore/springboot-beanvalidation - samples/server/petstore/springboot-builtin-validation diff --git a/bin/configs/spring-boot-byte-format-edge-cases-reactive.yaml b/bin/configs/spring-boot-byte-format-edge-cases-reactive.yaml new file mode 100644 index 000000000000..b4a874f984a3 --- /dev/null +++ b/bin/configs/spring-boot-byte-format-edge-cases-reactive.yaml @@ -0,0 +1,11 @@ +generatorName: spring +outputDir: samples/server/petstore/springboot-byte-format-edge-cases-reactive +inputSpec: modules/openapi-generator/src/test/resources/3_0/spring/byte-format-edge-cases.yaml +templateDir: modules/openapi-generator/src/main/resources/JavaSpring +additionalProperties: + artifactId: springboot + snapshotVersion: "true" + hideGenerationTimestamp: "true" + reactive: true + interfaceOnly: "true" + requestMappingMode: "none" diff --git a/bin/configs/spring-boot-byte-format-edge-cases.yaml b/bin/configs/spring-boot-byte-format-edge-cases.yaml new file mode 100644 index 000000000000..4dec629decf8 --- /dev/null +++ b/bin/configs/spring-boot-byte-format-edge-cases.yaml @@ -0,0 +1,10 @@ +generatorName: spring +outputDir: samples/server/petstore/springboot-byte-format-edge-cases +inputSpec: modules/openapi-generator/src/test/resources/3_0/spring/byte-format-edge-cases.yaml +templateDir: modules/openapi-generator/src/main/resources/JavaSpring +additionalProperties: + artifactId: springboot + snapshotVersion: "true" + hideGenerationTimestamp: "true" + interfaceOnly: "true" + requestMappingMode: "none" diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java index bf7e272e91a7..a29ae793a142 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java @@ -888,6 +888,27 @@ public void processOpts() { additionalProperties.put("lambdaSplitString", new SplitStringLambda()); + // Lambda to add type comment only if actual type differs from implemented type + // Format: "implementedType|actualType" -> " /* actualType */" or "" + additionalProperties.put("lambdaTypeComment", (Mustache.Lambda) (fragment, writer) -> { + String input = fragment.execute().trim(); + String[] parts = input.split("\\|", 2); + if (parts.length == 2) { + String implementedType = parts[0].trim(); + String actualType = parts[1].trim(); + + // Only add comment if types differ + if (!implementedType.equals(actualType)) { + // Also check if implementedType is a collection of actualType (e.g., List vs String) + String expectedCollection = "List<" + actualType + ">"; + String expectedFlux = "Flux<" + actualType + ">"; + if (!implementedType.equals(expectedCollection) && !implementedType.equals(expectedFlux)) { + writer.write(" /* " + actualType + " */"); + } + } + } + }); + // apiController: hide implementation behind undocumented flag to temporarily preserve code additionalProperties.put("_api_controller_impl_", false); // HEADS-UP: Do not add more template file after this block @@ -1142,6 +1163,8 @@ public void setIsVoid(boolean isVoid) { prepareVersioningParameters(ops); handleImplicitHeaders(operation); + convertByteArrayParamsToStringType(operation); + markMultipartFormDataParameters(operation); normalizeVendorExtensionWithStringList(operation.vendorExtensions, VendorExtension.X_OPERATION_EXTRA_ANNOTATION.getName()); normalizeOperationParameterVendorExtensions(operation, VendorExtension.X_FIELD_EXTRA_ANNOTATION.getName()); @@ -1174,6 +1197,76 @@ public void setIsVoid(boolean isVoid) { return objs; } + /** + * Converts parameters of type {@code byte[]} (i.e., OpenAPI {@code type: string, format: byte}) to {@code String}. + *

+ * In OpenAPI, {@code type: string, format: byte} is a base64-encoded string. However, Spring does not automatically + * decode base64-encoded request parameters into {@code byte[]} for query, path, header, cookie, or form parameters. + * Therefore, these parameters are mapped to {@code String} to avoid incorrect type handling and to ensure the + * application receives the raw base64 string as provided by the client. + *

+ * + * @param operation the codegen operation whose parameters will be checked and converted if necessary + **/ + private void convertByteArrayParamsToStringType(CodegenOperation operation) { + var convertedParams = operation.allParams.stream() + .filter(param -> param.isQueryParam || param.isPathParam || param.isHeaderParam || param.isCookieParam || param.isFormParam) + .filter(param -> { + if (param.getIsByteArray()) { + param.dataType = "String"; + return true; + } else if (param.isArray && param.items != null && param.items.getIsByteArray()) { + param.items.dataType = "String"; + param.dataType = param.dataType.replace("byte[]", "String"); + param.isByteArray = true; + return true; + } + return false; + }) + .collect(Collectors.toList()); + if (!convertedParams.isEmpty()) { + LOGGER.debug("Converted parameters [{}] from byte[] to String in operation [{}]", convertedParams.stream().map(param -> param.paramName).collect(Collectors.toList()), operation.operationId); + } + } + + /** + * Marks form parameters that are in multipart/form-data operations for special handling in reactive mode. + *

+ * In reactive Spring WebFlux, multipart/form-data parameters must use @RequestPart instead of @RequestParam, + * and non-model parameters (primitives, enums, strings) must be received as String or Flux<String> and + * converted manually in the implementation. + *

+ * + * @param operation the codegen operation whose parameters will be marked if necessary + **/ + private void markMultipartFormDataParameters(CodegenOperation operation) { + if (!reactive) { + return; // Only applies to reactive mode + } + + // Check if this operation consumes multipart/form-data + boolean isMultipartFormData = false; + if (operation.hasConsumes) { + for (Map consume : operation.consumes) { + if ("multipart/form-data".equalsIgnoreCase(consume.get("mediaType"))) { + isMultipartFormData = true; + break; + } + } + } + + if (!isMultipartFormData) { + return; + } + + // Mark all form parameters as multipart form data + for (CodegenParameter param : operation.allParams) { + if (param.isFormParam) { + param.vendorExtensions.put("x-isMultipartFormData", true); + } + } + } + /** * Adds a Spring Security expression that preserves the OpenAPI security requirement semantics: * entries in a {@code security} array are OR alternatives, while schemes and scopes in one diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache index 70ea6228ff77..04ca59050dcd 100644 --- a/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache +++ b/modules/openapi-generator/src/main/resources/JavaSpring/api.mustache @@ -150,7 +150,7 @@ public interface {{classname}} { {{/notes}} * {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{#isByteArray}} (base64 encoded){{/isByteArray}} {{/allParams}} * @return {{#responses}}{{message}} (status code {{code}}){{^-last}} * or {{/-last}}{{/responses}} diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/apiController.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/apiController.mustache index b5e42a1d19d6..f5fc80619ff4 100644 --- a/modules/openapi-generator/src/main/resources/JavaSpring/apiController.mustache +++ b/modules/openapi-generator/src/main/resources/JavaSpring/apiController.mustache @@ -104,7 +104,7 @@ public class {{classname}}Controller implements {{classname}} { {{/notes}} * {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{#isByteArray}} (base64 encoded){{/isByteArray}} {{/allParams}} * @return {{#responses}}{{message}} (status code {{code}}){{^-last}} * or {{/-last}}{{/responses}} diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/apiDelegate.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/apiDelegate.mustache index 20a9560d2dce..2900ad5f7e53 100644 --- a/modules/openapi-generator/src/main/resources/JavaSpring/apiDelegate.mustache +++ b/modules/openapi-generator/src/main/resources/JavaSpring/apiDelegate.mustache @@ -61,7 +61,7 @@ public interface {{classname}}Delegate { {{/notes}} * {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{#isByteArray}} (base64 encoded){{/isByteArray}} {{/allParams}} * @return {{#responses}}{{message}} (status code {{code}}){{^-last}} * or {{/-last}}{{/responses}} diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/formParams.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/formParams.mustache index ca41fa6a80a9..92439d099239 100644 --- a/modules/openapi-generator/src/main/resources/JavaSpring/formParams.mustache +++ b/modules/openapi-generator/src/main/resources/JavaSpring/formParams.mustache @@ -1 +1 @@ -{{#isFormParam}}{{^isFile}}{{>paramDoc}}{{#useBeanValidation}} {{>beanValidationBodyParams}}{{^isContainer}}{{#isModel}}@Valid {{/isModel}}{{^isModel}}{{^useOptional}}@Valid {{/useOptional}}{{#useOptional}}{{#required}}@Valid {{/required}}{{/useOptional}}{{/isModel}}{{/isContainer}}{{/useBeanValidation}}{{^useBeanValidation}} {{/useBeanValidation}}{{#isModel}}@RequestPart{{/isModel}}{{^isModel}}{{#isArray}}@RequestPart{{/isArray}}{{^isArray}}{{#reactive}}@RequestPart{{/reactive}}{{^reactive}}@RequestParam{{/reactive}}{{/isArray}}{{/isModel}}(value = "{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}){{>dateTimeParam}} {{^required}}{{#useOptional}}Optional<{{/useOptional}}{{/required}}{{{dataType}}}{{^required}}{{#useOptional}}>{{/useOptional}}{{/required}} {{paramName}}{{/isFile}}{{#isFile}}{{>paramDoc}} {{#vendorExtensions.x-field-extra-annotation}}{{{.}}} {{/vendorExtensions.x-field-extra-annotation}}@RequestPart(value = "{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}) {{#reactive}}{{#isArray}}Flux<{{/isArray}}Part{{#isArray}}>{{/isArray}}{{/reactive}}{{^reactive}}{{#isArray}}List<{{/isArray}}MultipartFile{{#isArray}}>{{/isArray}}{{/reactive}} {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file +{{#isFormParam}}{{^isFile}}{{>paramDoc}}{{#useBeanValidation}} {{>beanValidationBodyParams}}{{^isContainer}}{{#isModel}}@Valid {{/isModel}}{{^isModel}}{{^useOptional}}@Valid {{/useOptional}}{{#useOptional}}{{#required}}@Valid {{/required}}{{/useOptional}}{{/isModel}}{{/isContainer}}{{/useBeanValidation}}{{^useBeanValidation}} {{/useBeanValidation}}{{#isModel}}@RequestPart{{/isModel}}{{^isModel}}{{#isArray}}{{#items.isModel}}@RequestPart{{/items.isModel}}{{^items.isModel}}{{#reactive}}{{#vendorExtensions.x-isMultipartFormData}}@RequestPart{{/vendorExtensions.x-isMultipartFormData}}{{^vendorExtensions.x-isMultipartFormData}}@RequestParam{{/vendorExtensions.x-isMultipartFormData}}{{/reactive}}{{^reactive}}@RequestParam{{/reactive}}{{/items.isModel}}{{/isArray}}{{^isArray}}{{#reactive}}{{#vendorExtensions.x-isMultipartFormData}}@RequestPart{{/vendorExtensions.x-isMultipartFormData}}{{^vendorExtensions.x-isMultipartFormData}}@RequestParam{{/vendorExtensions.x-isMultipartFormData}}{{/reactive}}{{^reactive}}@RequestParam{{/reactive}}{{/isArray}}{{/isModel}}(value = "{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}){{>dateTimeParam}} {{^required}}{{#useOptional}}Optional<{{/useOptional}}{{/required}}{{#reactive}}{{#vendorExtensions.x-isMultipartFormData}}{{#isModel}}{{{dataType}}}{{/isModel}}{{^isModel}}{{#isArray}}{{#items.isModel}}{{{dataType}}}{{/items.isModel}}{{^items.isModel}}Flux{{#lambdaTypeComment}}Flux|{{{dataType}}}{{/lambdaTypeComment}}{{/items.isModel}}{{/isArray}}{{^isArray}}String{{#lambdaTypeComment}}String|{{{dataType}}}{{/lambdaTypeComment}}{{/isArray}}{{/isModel}}{{/vendorExtensions.x-isMultipartFormData}}{{^vendorExtensions.x-isMultipartFormData}}{{{dataType}}}{{/vendorExtensions.x-isMultipartFormData}}{{/reactive}}{{^reactive}}{{{dataType}}}{{/reactive}}{{^required}}{{#useOptional}}>{{/useOptional}}{{/required}} {{paramName}}{{/isFile}}{{#isByteArray}} /* base64 encoded binary */{{/isByteArray}}{{#isFile}}{{>paramDoc}} {{#vendorExtensions.x-field-extra-annotation}}{{{.}}} {{/vendorExtensions.x-field-extra-annotation}}@RequestPart(value = "{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}) {{#reactive}}{{#isArray}}Flux<{{/isArray}}Part{{#isArray}}>{{/isArray}}{{/reactive}}{{^reactive}}{{#isArray}}List<{{/isArray}}MultipartFile{{#isArray}}>{{/isArray}}{{/reactive}} {{paramName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/README.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/README.mustache index 33666dbdd57a..eabfd8c422a9 100644 --- a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/README.mustache +++ b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/README.mustache @@ -38,7 +38,7 @@ This code was generated by the [OpenAPI Generator](https://openapi-generator.tec By using the [OpenAPI-Spec](https://openapis.org), you can easily generate an API stub. This is an example of building API stub interfaces in Java using the Spring framework. -The stubs generated can be used in your existing Spring-MVC or Spring-Boot application to create controller endpoints +The stubs generated can be used in your existing {{#reactive}}Spring-WebFlux{{/reactive}}{{^reactive}}Spring-MVC{{/reactive}} or Spring-Boot application to create controller endpoints by adding ```@Controller``` classes that implement the interface. Eg: ```java @Controller diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-http-interface/api.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-http-interface/api.mustache index f7bcdc7b12bb..c80369ba89a8 100644 --- a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-http-interface/api.mustache +++ b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-http-interface/api.mustache @@ -55,7 +55,7 @@ public interface {{classname}} { {{/notes}} * {{#allParams}} - * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}} + * @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{.}}{{/defaultValue}}){{/required}}{{#isByteArray}} (base64 encoded){{/isByteArray}} {{/allParams}} * @return {{#responses}}{{message}} (status code {{code}}){{^-last}} * or {{/-last}}{{/responses}} diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/optionalDataType.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/optionalDataType.mustache index feb2ecf37e1d..16df5cd7b7ca 100644 --- a/modules/openapi-generator/src/main/resources/JavaSpring/optionalDataType.mustache +++ b/modules/openapi-generator/src/main/resources/JavaSpring/optionalDataType.mustache @@ -1 +1 @@ -{{#useOptional}}{{#required}}{{{dataType}}}{{/required}}{{^required}}Optional<{{#useBeanValidation}}{{>beanValidationCore}}{{/useBeanValidation}}{{{dataType}}}>{{/required}}{{/useOptional}}{{^useOptional}}{{#lambda.jSpecifyDatatype}}{{{dataType}}}{{/lambda.jSpecifyDatatype}}{{/useOptional}} \ No newline at end of file +{{#useOptional}}{{#required}}{{{dataType}}}{{/required}}{{^required}}Optional<{{#useBeanValidation}}{{>beanValidationCore}}{{/useBeanValidation}}{{{dataType}}}>{{/required}}{{/useOptional}}{{^useOptional}}{{#lambda.jSpecifyDatatype}}{{{dataType}}}{{/lambda.jSpecifyDatatype}}{{/useOptional}}{{#isByteArray}} /* base64 encoded binary */{{/isByteArray}} \ No newline at end of file diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java index 43f9b8d6ec18..f7e2b70ff2bc 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java @@ -1569,7 +1569,7 @@ public void testWebClientWithUseAbstractionForFiles() { .addAdditionalProperty(CodegenConstants.API_PACKAGE, "xyz.abcdef.api") .addAdditionalProperty(JavaClientCodegen.USE_ABSTRACTION_FOR_FILES, true) .setLibrary(JavaClientCodegen.WEBCLIENT) - .setInputSpec("src/test/resources/3_0/form-multipart-binary-array.yaml") + .setInputSpec("src/test/resources/3_0/form-multipart-binary-array-extended.yaml") .setOutputDir(output.toString().replace("\\", "/")); List files = new DefaultGenerator().opts(configurator.toClientOptInput()).generate(); @@ -1582,7 +1582,7 @@ public void testWebClientWithUseAbstractionForFiles() { "formParams.addAll(\"files\", files.stream().collect(Collectors.toList()));", // mixed - "multipartMixed(@javax.annotation.Nonnull MultipartMixedStatus status, @javax.annotation.Nonnull org.springframework.core.io.Resource _file, @javax.annotation.Nullable MultipartMixedRequestMarker marker, @javax.annotation.Nullable List statusArray)", + "multipartMixed(@javax.annotation.Nonnull MultipartMixedStatus status, @javax.annotation.Nonnull org.springframework.core.io.Resource _file, @javax.annotation.Nullable MultipartMixedRequestMarker marker, @javax.annotation.Nullable List markerArray, @javax.annotation.Nullable List statusArray)", "formParams.add(\"file\", _file);", // single file @@ -3031,7 +3031,7 @@ public void testRestClientFormMultipart() { .setGeneratorName(JAVA_GENERATOR) .setLibrary(JavaClientCodegen.RESTCLIENT) .setAdditionalProperties(Map.of(CodegenConstants.API_PACKAGE, "xyz.abcdef.api")) - .setInputSpec("src/test/resources/3_0/form-multipart-binary-array.yaml") + .setInputSpec("src/test/resources/3_0/form-multipart-binary-array-extended.yaml") .setOutputDir(output.toString().replace("\\", "/")); List files = new DefaultGenerator().opts(configurator.toClientOptInput()).generate(); @@ -3045,7 +3045,7 @@ public void testRestClientFormMultipart() { + " files.stream().map(FileSystemResource::new).collect(Collectors.toList()));", // mixed - "multipartMixed(@jakarta.annotation.Nonnull MultipartMixedStatus status, @jakarta.annotation.Nonnull File _file, @jakarta.annotation.Nullable MultipartMixedRequestMarker marker, @jakarta.annotation.Nullable List statusArray)", + "multipartMixed(@jakarta.annotation.Nonnull MultipartMixedStatus status, @jakarta.annotation.Nonnull File _file, @jakarta.annotation.Nullable MultipartMixedRequestMarker marker, @jakarta.annotation.Nullable List markerArray, @jakarta.annotation.Nullable List statusArray)", "formParams.add(\"file\", new FileSystemResource(_file));", // single file @@ -3062,7 +3062,7 @@ public void testRestClientWithUseAbstractionForFiles() { .addAdditionalProperty(CodegenConstants.API_PACKAGE, "xyz.abcdef.api") .addAdditionalProperty(JavaClientCodegen.USE_ABSTRACTION_FOR_FILES, true) .setLibrary(JavaClientCodegen.RESTCLIENT) - .setInputSpec("src/test/resources/3_0/form-multipart-binary-array.yaml") + .setInputSpec("src/test/resources/3_0/form-multipart-binary-array-extended.yaml") .setOutputDir(output.toString().replace("\\", "/")); List files = new DefaultGenerator().opts(configurator.toClientOptInput()).generate(); @@ -3075,7 +3075,7 @@ public void testRestClientWithUseAbstractionForFiles() { "formParams.addAll(\"files\", files.stream().collect(Collectors.toList()));", // mixed - "multipartMixed(@jakarta.annotation.Nonnull MultipartMixedStatus status, @jakarta.annotation.Nonnull org.springframework.core.io.Resource _file, @jakarta.annotation.Nullable MultipartMixedRequestMarker marker, @jakarta.annotation.Nullable List statusArray)", + "multipartMixed(@jakarta.annotation.Nonnull MultipartMixedStatus status, @jakarta.annotation.Nonnull org.springframework.core.io.Resource _file, @jakarta.annotation.Nullable MultipartMixedRequestMarker marker, @jakarta.annotation.Nullable List markerArray, @jakarta.annotation.Nullable List statusArray)", "formParams.add(\"file\", _file);", // single file @@ -5277,7 +5277,7 @@ public void testMicroprofileFormMultipartArray() { .setGeneratorName(JAVA_GENERATOR) .setLibrary(JavaClientCodegen.MICROPROFILE) .setAdditionalProperties(Map.of(CodegenConstants.API_PACKAGE, "xyz.abcdef.api")) - .setInputSpec("src/test/resources/3_0/form-multipart-binary-array.yaml") + .setInputSpec("src/test/resources/3_0/form-multipart-binary-array-extended.yaml") .setOutputDir(output.toString().replace("\\", "/")); List files = new DefaultGenerator().opts(configurator.toClientOptInput()).generate(); @@ -5291,6 +5291,7 @@ public void testMicroprofileFormMultipartArray() { "@FormParam(\"file\") File _fileDetail", // a file next to a non-file array: only the file type is affected "@FormParam(\"file\") File _fileDetail, @FormParam(\"marker\") MultipartMixedRequestMarker marker," + + " @FormParam(\"markerArray\") List markerArray," + " @FormParam(\"statusArray\") List statusArray"); } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/assertions/PropertyAssert.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/assertions/PropertyAssert.java index e598c210a1f6..401d87fddfca 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/assertions/PropertyAssert.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/assertions/PropertyAssert.java @@ -26,6 +26,20 @@ public PropertyAssert withType(final String expectedType) { return this; } + public PropertyAssert isArray() { + Assertions.assertThat(actual.getCommonType().isArrayType()) + .withFailMessage("Expected property %s to be array, but it was NOT", actual.getVariable(0).getNameAsString()) + .isEqualTo(true); + return this; + } + + public PropertyAssert isNotArray() { + Assertions.assertThat(actual.getCommonType().isArrayType()) + .withFailMessage("Expected property %s NOT to be array, but it was", actual.getVariable(0).getNameAsString()) + .isEqualTo(false); + return this; + } + public PropertyAnnotationsAssert assertPropertyAnnotations() { return new PropertyAnnotationsAssert(this, actual.getAnnotations()); } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java index 6dba11b7c8e2..29ff9f3f88e3 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java @@ -743,7 +743,7 @@ public void testMultipartBoot() throws IOException { codegen.setLibrary("spring-boot"); codegen.setDelegatePattern(true); - final Map files = generateFiles(codegen, "src/test/resources/3_0/form-multipart-binary-array.yaml"); + final Map files = generateFiles(codegen, "src/test/resources/3_0/form-multipart-binary-array-extended.yaml"); // Check that the delegate handles the array JavaFileAssert.assertThat(files.get("MultipartArrayApiDelegate.java")) @@ -775,7 +775,7 @@ public void testMultipartBoot() throws IOException { // Check that api validates mixed multipart request JavaFileAssert.assertThat(files.get("MultipartMixedApi.java")) - .assertMethod("multipartMixed", "MultipartMixedStatus", "MultipartFile", "MultipartMixedRequestMarker", "List") + .assertMethod("multipartMixed", "MultipartMixedStatus", "MultipartFile", "MultipartMixedRequestMarker", "List", "List") .assertParameter("status").hasType("MultipartMixedStatus") .assertParameterAnnotations() .containsWithName("Valid") @@ -789,10 +789,15 @@ public void testMultipartBoot() throws IOException { .assertParameter("marker").hasType("MultipartMixedRequestMarker") .assertParameterAnnotations() .containsWithNameAndAttributes("RequestPart", ImmutableMap.of("value", "\"marker\"", "required", "false")) + // markerArray (array of objects — IMPORTANT) + .toParameter().toMethod() + .assertParameter("markerArray").hasType("List") + .assertParameterAnnotations() + .containsWithNameAndAttributes("RequestPart", ImmutableMap.of("value", "\"markerArray\"", "required", "false")) .toParameter().toMethod() .assertParameter("statusArray").hasType("List") .assertParameterAnnotations() - .containsWithNameAndAttributes("RequestPart", ImmutableMap.of("value", "\"statusArray\"", "required", "false")); + .containsWithNameAndAttributes("RequestParam", ImmutableMap.of("value", "\"statusArray\"", "required", "false")); // Check extra annotation JavaFileAssert.assertThat(files.get("ExtraAnnotationApi.java")) @@ -963,7 +968,7 @@ public void testReactiveMultipartBoot() throws IOException { codegen.setDelegatePattern(true); codegen.additionalProperties().put(SpringCodegen.REACTIVE, "true"); - final Map files = generateFiles(codegen, "src/test/resources/3_0/form-multipart-binary-array.yaml"); + final Map files = generateFiles(codegen, "src/test/resources/3_0/form-multipart-binary-array-extended.yaml"); // Check that the delegate handles the array JavaFileAssert.assertThat(files.get("MultipartArrayApiDelegate.java")) @@ -995,8 +1000,8 @@ public void testReactiveMultipartBoot() throws IOException { // Check that api validates mixed multipart request JavaFileAssert.assertThat(files.get("MultipartMixedApi.java")) - .assertMethod("multipartMixed", "MultipartMixedStatus", "Part", "MultipartMixedRequestMarker", "List", "ServerWebExchange") - .assertParameter("status").hasType("MultipartMixedStatus") + .assertMethod("multipartMixed", "String", "Part", "MultipartMixedRequestMarker", "List", "Flux", "ServerWebExchange") + .assertParameter("status").hasType("String") .assertParameterAnnotations() .containsWithName("Valid") .containsWithNameAndAttributes("Parameter", ImmutableMap.of("name", "\"status\"", "description", "\"\"")) @@ -1010,9 +1015,23 @@ public void testReactiveMultipartBoot() throws IOException { .assertParameterAnnotations() .containsWithNameAndAttributes("RequestPart", ImmutableMap.of("value", "\"marker\"", "required", "false")) .toParameter().toMethod() - .assertParameter("statusArray").hasType("List") + // markerArray (array of objects — IMPORTANT) + .assertParameter("markerArray").hasType("List") + .assertParameterAnnotations() + .containsWithNameAndAttributes("RequestPart", ImmutableMap.of("value", "\"markerArray\"", "required", "false")) + .toParameter().toMethod() + .assertParameter("statusArray").hasType("Flux") .assertParameterAnnotations() .containsWithNameAndAttributes("RequestPart", ImmutableMap.of("value", "\"statusArray\"", "required", "false")); + + // Media type comparison for multipart/form-data must be case-insensitive (per RFC 7231); + // a mixed-case "Multipart/Form-Data" media type should still be treated as multipart and + // bind its form field via @RequestPart (not @RequestParam) + JavaFileAssert.assertThat(files.get("MultipartMixedCaseMediaTypeApi.java")) + .assertMethod("multipartMixedCaseMediaType", "String", "ServerWebExchange") + .assertParameter("status").hasType("String") + .assertParameterAnnotations() + .containsWithNameAndAttributes("RequestPart", ImmutableMap.of("value", "\"status\"", "required", "true")); } @Test @@ -1152,6 +1171,121 @@ public void testSchemaImplements() throws IOException { .implementsInterfaces(fooInterface, fooAnotherInterface); } + + @Test + public void shouldHandleFormatByteCorrectlyForAllApiParametersAndProperties() throws IOException { + final SpringCodegen codegen = new SpringCodegen(); + + final Map files = generateFiles(codegen, "src/test/resources/3_0/spring/byte-format-baseline.yaml"); + // Query parameters: both plain text and Base64-encoded fields are mapped to String + JavaFileAssert.assertThat(files.get("QueryApi.java")) + .assertMethod("queryParams") + .assertParameter("plain") + .hasType("String"); // plain query param → always String + JavaFileAssert.assertThat(files.get("QueryApi.java")) + .assertMethod("queryParams") + .assertParameter("bytes") + .hasType("String"); // Base64 query param → String (manual decoding needed) + + // Array of Base64-encoded query parameters: converted to List (was List, + // which Spring cannot bind correctly element-by-element) + JavaFileAssert.assertThat(files.get("QueryArrayApi.java")) + .assertMethod("queryArrayParams") + .assertParameter("bytesArray") + .hasType("List"); + + // Path parameters: same behavior as query params + JavaFileAssert.assertThat(files.get("PathApi.java")) + .assertMethod("pathParams") + .assertParameter("plain") + .hasType("String"); // path param → String + JavaFileAssert.assertThat(files.get("PathApi.java")) + .assertMethod("pathParams") + .assertParameter("bytes") + .hasType("String"); // Base64 path param → String + + // Header parameters: always String + JavaFileAssert.assertThat(files.get("HeaderApi.java")) + .assertMethod("headerParams") + .assertParameter("xPlain") + .hasType("String"); // header → String + JavaFileAssert.assertThat(files.get("HeaderApi.java")) + .assertMethod("headerParams") + .assertParameter("xByte") + .hasType("String"); // Base64 header → String + + // Cookie parameters: always String + JavaFileAssert.assertThat(files.get("CookieApi.java")) + .assertMethod("cookieParams") + .assertParameter("plain") + .hasType("String"); // cookie → String + JavaFileAssert.assertThat(files.get("CookieApi.java")) + .assertMethod("cookieParams") + .assertParameter("bytes") + .hasType("String"); // Base64 cookie → String + + // Form fields: text fields → String + JavaFileAssert.assertThat(files.get("FormApi.java")) + .assertMethod("formParams") + .assertParameter("plain") + .hasType("String"); // form field → String + JavaFileAssert.assertThat(files.get("FormApi.java")) + .assertMethod("formParams") + .assertParameter("bytes") + .hasType("String"); // Base64 form field → String + + // Multipart fields: text fields → String, files → MultipartFile + // Verifies that a simple multipart text field is generated as a String parameter + JavaFileAssert.assertThat(files.get("MultipartApi.java")) + .assertMethod("multipartParams") + .assertParameter("plain") + .hasType("String"); // multipart text field → String + + // Verifies that a Base64-encoded multipart field is treated as text (String) + // and is bound using @RequestParam rather than @RequestPart + JavaFileAssert.assertThat(files.get("MultipartApi.java")) + .assertMethod("multipartParams") + .assertParameter("bytes") + .hasType("String") // Base64 multipart text → String + .assertParameterAnnotations() + .containsWithName("RequestParam"); + + // Verifies that a binary file upload is exposed as MultipartFile + // and correctly bound from a multipart section using @RequestPart + JavaFileAssert.assertThat(files.get("MultipartApi.java")) + .assertMethod("multipartParams") + .assertParameter("file") + .hasType("MultipartFile") // binary file upload → MultipartFile + .assertParameterAnnotations() + .containsWithName("RequestPart"); + + // Form request DTO: JSON or form object mapping + JavaFileAssert.assertThat(files.get("FormParamsRequest.java")) + .assertProperty("plain") + .withType("String"); // text property → String + JavaFileAssert.assertThat(files.get("FormParamsRequest.java")) + .assertProperty("bytes") + .isArray() + .withType("byte"); // Base64 property in DTO → auto-decoded to byte[] + + // JSON request body: the inline JSON body schema is deduplicated by the + // InlineModelResolver into the same FormParamsRequest model asserted above + // (identical shape), so the JSON body operation's parameter must reference + // that model. This ensures a regression that widens convertByteArrayParamsToStringType + // to request bodies (which should stay byte[], auto-decoded by Jackson, unlike + // query/path/header/cookie/form params) would be caught here. + JavaFileAssert.assertThat(files.get("JsonBodyApi.java")) + .assertMethod("jsonBody") + .assertParameter("formParamsRequest") + .hasType("FormParamsRequest"); + + // Binary request body: bound as Resource for streaming + JavaFileAssert.assertThat(files.get("BinaryBodyApi.java")) + .assertMethod("binaryBody") + .assertParameter("body") + .hasType("org.springframework.core.io.Resource"); // raw binary body → Resource (streamable) + } + @Test public void shouldAddParameterWithInHeaderWhenImplicitHeadersIsTrue_issue14418() throws IOException { File output = Files.createTempDirectory("test").toFile().getCanonicalFile(); @@ -5584,7 +5718,6 @@ public void givenMultipartForm_whenGenerateReactiveServer_thenParameterAreCreate generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "true"); generator.opts(input).generate(); - assertFileContains(Paths.get(outputPath + "/src/main/java/org/openapitools/api/PetApi.java"), "@Valid @RequestPart(value = \"additionalMetadata\", required = false) String additionalMetadata"); } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java index bdd8a1008307..113ee6139349 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/spring/KotlinSpringServerCodegenTest.java @@ -1039,6 +1039,40 @@ public void givenOctetStreamResponseType_whenGenerateServer_thenReturnTypeIsReso assertFileContains(outputFilepath, "): ResponseEntity"); } + @Test + public void givenMultipartForm_whenGenerateBlockingServer_thenParameterAreCreatedAsRequestParam() throws IOException { + File output = Files.createTempDirectory("test").toFile().getCanonicalFile(); + output.deleteOnExit(); + String outputPath = output.getAbsolutePath().replace('\\', '/'); + + final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/kotlin/petstore-with-tags.yaml"); + final KotlinSpringServerCodegen codegen = new KotlinSpringServerCodegen(); + codegen.setOpenAPI(openAPI); + codegen.setOutputDir(output.getAbsolutePath()); + + ClientOptInput input = new ClientOptInput(); + input.openAPI(openAPI); + input.config(codegen); + + DefaultGenerator generator = new DefaultGenerator(); + + generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "false"); + generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "false"); + generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false"); + generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "true"); + generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "false"); + + generator.opts(input).generate(); + + Path outputFilepath = Paths.get(outputPath + "/src/main/kotlin/org/openapitools/api/PetApiController.kt"); + + assertFileContains(outputFilepath, + "@Parameter(description = \"Additional data to pass to server\") @Valid @RequestParam(value = \"additionalMetadata\", required = false) additionalMetadata: kotlin.String?"); + assertFileContains(outputFilepath, + "@Parameter(description = \"image to upload\") @Valid @RequestPart(\"image\", required = false) image: org.springframework.web.multipart.MultipartFile"); + + } + @Test public void givenMultipartForm_whenGenerateReactiveServer_thenParameterAreCreatedAsRequestPart() throws IOException { Map files = generateFromContract( diff --git a/modules/openapi-generator/src/test/resources/3_0/form-multipart-binary-array-extended.yaml b/modules/openapi-generator/src/test/resources/3_0/form-multipart-binary-array-extended.yaml new file mode 100644 index 000000000000..372b806a09ab --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/form-multipart-binary-array-extended.yaml @@ -0,0 +1,155 @@ +openapi: '3.0.1' +info: + version: 1.0.0 + title: MultipartFile test +paths: + /multipart-array: + post: + tags: + - multipart + description: MultipartFile array test + operationId: multipartArray + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + files: + type: array + description: "Many files" + items: + type: string + format: binary + responses: + '204': + description: Successful operation + /multipart-single: + post: + tags: + - multipart + description: Single MultipartFile test + operationId: multipartSingle + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + file: + description: "One file" + type: string + format: binary + responses: + '204': + description: Successful operation + /multipart-mixed: + post: + tags: + - multipart + description: Mixed MultipartFile test + operationId: multipartMixed + requestBody: + content: + multipart/form-data: + schema: + type: object + required: + - status + - file + properties: + status: + $ref: '#/components/schemas/MultipartMixedStatus' + marker: + description: "additional object" + type: object + properties: + name: + type: string + markerArray: + description: "array of objects" + type: array + items: + $ref: '#/components/schemas/MultipartMixedRequestMarker' + file: + description: "a file" + type: string + format: binary + statusArray: + type: array + items: + $ref: '#/components/schemas/MultipartMixedStatus' + responses: + '204': + description: Successful operation + + /extra-annotation: + post: + tags: + - multipart + description: MultipartFile extra annotation test + operationId: multipartExtraAnnotation + requestBody: + content: + multipart/form-data: + schema: + type: object + required: + - file + properties: + file: + x-field-extra-annotation: "@jakarta.validation.constraints.NotNull" + type: string + format: binary + description: The file to upload. + responses: + '204': + description: Successful operation + /multipart-mixed-case-media-type: + post: + tags: + - multipart + description: MultipartFile test with a mixed-case multipart/form-data media type + operationId: multipartMixedCaseMediaType + requestBody: + content: + Multipart/Form-Data: + schema: + type: object + required: + - status + properties: + status: + type: string + responses: + '204': + description: Successful operation +components: + schemas: + MultipartMixedStatus: + description: "additional field as Enum" + type: string + enum: + - ALLOWED + - IN_PROGRESS + - REJECTED + example: REJECTED + MultipartMixedRequestMarker: + type: object + description: Marker metadata sent as JSON part in multipart request + required: + - name + properties: + name: + type: string + description: Marker name + example: example-marker + priority: + type: integer + format: int32 + description: Optional priority + example: 10 + active: + type: boolean + description: Whether the marker is active + example: true \ No newline at end of file diff --git a/modules/openapi-generator/src/test/resources/3_0/spring/byte-format-baseline.yaml b/modules/openapi-generator/src/test/resources/3_0/spring/byte-format-baseline.yaml new file mode 100644 index 000000000000..0b12aa34b75a --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/spring/byte-format-baseline.yaml @@ -0,0 +1,173 @@ +openapi: 3.0.3 +info: + title: Byte Format Edge Cases + version: 1.0.0 + +paths: + /query: + get: + operationId: queryParams + summary: Query parameters + parameters: + - name: plain + in: query + schema: + type: string + - name: bytes + in: query + schema: + type: string + format: byte + responses: + '204': + description: No content + + /query-array: + get: + operationId: queryArrayParams + summary: Array of byte-format query parameters + parameters: + - name: bytesArray + in: query + schema: + type: array + items: + type: string + format: byte + responses: + '204': + description: No content + + /path/{plain}/{bytes}: + get: + operationId: pathParams + summary: Path parameters + parameters: + - name: plain + in: path + required: true + schema: + type: string + - name: bytes + in: path + required: true + schema: + type: string + format: byte + responses: + '204': + description: No content + + /header: + get: + operationId: headerParams + summary: Header parameters + parameters: + - name: X-Plain + in: header + schema: + type: string + - name: X-Byte + in: header + schema: + type: string + format: byte + responses: + '204': + description: No content + + /cookie: + get: + operationId: cookieParams + summary: Cookie parameters + parameters: + - name: plain + in: cookie + schema: + type: string + - name: bytes + in: cookie + schema: + type: string + format: byte + responses: + '204': + description: No content + + /form: + post: + operationId: formParams + summary: application/x-www-form-urlencoded + requestBody: + required: true + content: + application/x-www-form-urlencoded: + schema: + type: object + properties: + plain: + type: string + bytes: + type: string + format: byte + responses: + '204': + description: No content + + /multipart: + post: + operationId: multipartParams + summary: multipart/form-data + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + properties: + plain: + type: string + bytes: + type: string + format: byte + file: + type: string + format: binary + responses: + '204': + description: No content + + /json-body: + post: + operationId: jsonBody + summary: JSON request body + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + plain: + type: string + bytes: + type: string + format: byte + responses: + '204': + description: No content + + /binary-body: + post: + operationId: binaryBody + summary: Raw binary body + requestBody: + required: true + content: + application/octet-stream: + schema: + type: string + format: binary + responses: + '204': + description: No content diff --git a/modules/openapi-generator/src/test/resources/3_0/spring/byte-format-edge-cases.yaml b/modules/openapi-generator/src/test/resources/3_0/spring/byte-format-edge-cases.yaml new file mode 100644 index 000000000000..a6fbdd909578 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/spring/byte-format-edge-cases.yaml @@ -0,0 +1,332 @@ +openapi: 3.0.3 +info: + title: Multipart & Byte Edge Case Coverage + version: 1.0.0 +servers: + - url: / +tags: + - name: coverage +paths: + /coverage/query: + get: + operationId: queryParams + parameters: + - explode: true + in: query + name: plain + required: false + schema: + type: string + style: form + - explode: true + in: query + name: bytes + required: false + schema: + format: byte + type: string + style: form + responses: + "204": + description: No content + tags: + - coverage + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/path/{plain}/{bytes}: + get: + operationId: pathParams + parameters: + - explode: false + in: path + name: plain + required: true + schema: + type: string + style: simple + - description: >- + Base64-encoded value embedded in the URL path. Standard Base64 + (RFC 4648 §4) can produce a `/` character, which is not safe to + use unescaped inside a path segment: most servers (including + Spring's default Tomcat/Jetty configuration) reject or misroute + requests containing an encoded slash (`%2F`) unless the server is + explicitly configured to allow it. Clients must percent-encode + the value (and servers may need to enable encoded-slash handling) + before using a base64 value as a path parameter. Prefer + Base64URL (RFC 4648 §5, using `-`/`_` instead of `+`/`/`) or a + query/body parameter to avoid this caveat entirely. + explode: false + in: path + name: bytes + required: true + schema: + format: byte + type: string + style: simple + responses: + "204": + description: No content + tags: + - coverage + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/header: + get: + operationId: headerParams + parameters: + - explode: false + in: header + name: X-Plain + required: false + schema: + type: string + style: simple + - explode: false + in: header + name: X-Byte + required: false + schema: + format: byte + type: string + style: simple + responses: + "204": + description: No content + tags: + - coverage + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/cookie: + get: + operationId: cookieParams + parameters: + - explode: true + in: cookie + name: plain + required: false + schema: + type: string + style: form + - explode: true + in: cookie + name: bytes + required: false + schema: + format: byte + type: string + style: form + responses: + "204": + description: No content + tags: + - coverage + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/form: + post: + operationId: formParams + requestBody: + content: + application/x-www-form-urlencoded: + schema: + $ref: "#/components/schemas/formParams_request" + required: true + responses: + "204": + description: No content + tags: + - coverage + x-content-type: application/x-www-form-urlencoded + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/multipart/simple: + post: + operationId: multipartSimple + requestBody: + content: + multipart/form-data: + schema: + $ref: "#/components/schemas/multipartSimple_request" + required: true + responses: + "204": + description: No content + tags: + - coverage + x-content-type: multipart/form-data + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/multipart/simple-validated: + post: + operationId: multipartSimpleValidated + requestBody: + content: + multipart/form-data: + schema: + $ref: "#/components/schemas/multipartSimple_request" + required: true + responses: + "204": + description: No content + tags: + - coverage + x-content-type: multipart/form-data + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/multipart/files: + post: + operationId: multipartFileArray + requestBody: + content: + multipart/form-data: + schema: + $ref: "#/components/schemas/multipartFileArray_request" + responses: + "204": + description: No content + tags: + - coverage + x-content-type: multipart/form-data + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/multipart/mixed: + post: + operationId: multipartMixed + requestBody: + content: + multipart/form-data: + schema: + $ref: "#/components/schemas/multipartMixed_request" + responses: + "204": + description: No content + tags: + - coverage + x-content-type: multipart/form-data + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/json: + post: + operationId: jsonBody + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/formParams_request" + required: true + responses: + "204": + description: No content + tags: + - coverage + x-content-type: application/json + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/binary: + post: + operationId: binaryBody + requestBody: + content: + application/octet-stream: + schema: + format: binary + type: string + required: true + responses: + "204": + description: No content + tags: + - coverage + x-content-type: application/octet-stream + x-accepts: + - application/json + x-tags: + - tag: coverage +components: + schemas: + MultipartMixedStatus: + enum: + - ALLOWED + - IN_PROGRESS + - REJECTED + type: string + MultipartMixedRequestMarker: + properties: + name: + type: string + priority: + format: int32 + type: integer + active: + type: boolean + required: + - name + type: object + formParams_request: + properties: + plain: + type: string + bytes: + format: byte + type: string + type: object + multipartSimple_request: + properties: + plain: + type: string + bytes: + format: byte + type: string + file: + format: binary + type: string + type: object + multipartFileArray_request: + properties: + files: + items: + format: binary + type: string + type: array + type: object + multipartMixed_request: + properties: + status: + $ref: "#/components/schemas/MultipartMixedStatus" + statusArray: + items: + $ref: "#/components/schemas/MultipartMixedStatus" + type: array + marker: + $ref: "#/components/schemas/MultipartMixedRequestMarker" + markerArray: + items: + $ref: "#/components/schemas/MultipartMixedRequestMarker" + type: array + file: + format: binary + type: string + required: + - file + - status + type: object diff --git a/samples/client/petstore/spring-http-interface-bean-validation/src/main/java/org/openapitools/api/FakeApi.java b/samples/client/petstore/spring-http-interface-bean-validation/src/main/java/org/openapitools/api/FakeApi.java index 6e73da75a378..f0385e54c3ae 100644 --- a/samples/client/petstore/spring-http-interface-bean-validation/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/client/petstore/spring-http-interface-bean-validation/src/main/java/org/openapitools/api/FakeApi.java @@ -215,7 +215,7 @@ ResponseEntity testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -239,7 +239,7 @@ ResponseEntity testEndpointParameters( @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Valid @RequestParam(value = "byte", required = true) byte[] _byte, + @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, @Min(value = 10) @Max(value = 100) @Valid @RequestParam(value = "integer", required = false) Integer integer, @Min(value = 20) @Max(value = 200) @Valid @RequestParam(value = "int32", required = false) Integer int32, @Valid @RequestParam(value = "int64", required = false) Long int64, @@ -282,7 +282,7 @@ ResponseEntity testEnumParameters( @Valid @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @Valid @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @Valid @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, + @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString ); diff --git a/samples/client/petstore/spring-http-interface-noResponseEntity/src/main/java/org/openapitools/api/FakeApi.java b/samples/client/petstore/spring-http-interface-noResponseEntity/src/main/java/org/openapitools/api/FakeApi.java index 3cef548dcc27..0a8612f706e5 100644 --- a/samples/client/petstore/spring-http-interface-noResponseEntity/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/client/petstore/spring-http-interface-noResponseEntity/src/main/java/org/openapitools/api/FakeApi.java @@ -221,7 +221,7 @@ ClientDto testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -246,7 +246,7 @@ void testEndpointParameters( @RequestParam(value = "number", required = true) BigDecimal number, @RequestParam(value = "double", required = true) Double _double, @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @RequestParam(value = "byte", required = true) byte[] _byte, + @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, @RequestParam(value = "integer", required = false) Integer integer, @RequestParam(value = "int32", required = false) Integer int32, @RequestParam(value = "int64", required = false) Long int64, @@ -290,7 +290,7 @@ void testEnumParameters( @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, + @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, @RequestParam(value = "enum_form_string", required = false) String enumFormString ); diff --git a/samples/client/petstore/spring-http-interface-reactive-bean-validation/src/main/java/org/openapitools/api/FakeApi.java b/samples/client/petstore/spring-http-interface-reactive-bean-validation/src/main/java/org/openapitools/api/FakeApi.java index c96ecd17b026..6d91e95baa8b 100644 --- a/samples/client/petstore/spring-http-interface-reactive-bean-validation/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/client/petstore/spring-http-interface-reactive-bean-validation/src/main/java/org/openapitools/api/FakeApi.java @@ -219,7 +219,7 @@ Mono> testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -240,20 +240,20 @@ Mono> testClientModel( contentType = "application/x-www-form-urlencoded" ) Mono> testEndpointParameters( - @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestPart(value = "number", required = true) BigDecimal number, - @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestPart(value = "double", required = true) Double _double, - @Pattern(regexp = "^[A-Z].*") @Valid @RequestPart(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Valid @RequestPart(value = "byte", required = true) byte[] _byte, - @Min(value = 10) @Max(value = 100) @Valid @RequestPart(value = "integer", required = false) Integer integer, - @Min(value = 20) @Max(value = 200) @Valid @RequestPart(value = "int32", required = false) Integer int32, - @Valid @RequestPart(value = "int64", required = false) Long int64, - @DecimalMax(value = "987.6") @Valid @RequestPart(value = "float", required = false) Float _float, - @Pattern(regexp = "[a-zA-Z]") @Valid @RequestPart(value = "string", required = false) String string, + @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, + @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, + @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, + @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, + @Min(value = 10) @Max(value = 100) @Valid @RequestParam(value = "integer", required = false) Integer integer, + @Min(value = 20) @Max(value = 200) @Valid @RequestParam(value = "int32", required = false) Integer int32, + @Valid @RequestParam(value = "int64", required = false) Long int64, + @DecimalMax(value = "987.6") @Valid @RequestParam(value = "float", required = false) Float _float, + @Pattern(regexp = "[a-zA-Z]") @Valid @RequestParam(value = "string", required = false) String string, @RequestPart(value = "binary", required = false) Part binary, - @Valid @RequestPart(value = "date", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date, - @Valid @RequestPart(value = "dateTime", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) OffsetDateTime dateTime, - @Size(min = 10, max = 64) @Valid @RequestPart(value = "password", required = false) String password, - @Valid @RequestPart(value = "callback", required = false) String paramCallback + @Valid @RequestParam(value = "date", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date, + @Valid @RequestParam(value = "dateTime", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) OffsetDateTime dateTime, + @Size(min = 10, max = 64) @Valid @RequestParam(value = "password", required = false) String password, + @Valid @RequestParam(value = "callback", required = false) String paramCallback ); @@ -286,8 +286,8 @@ Mono> testEnumParameters( @Valid @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @Valid @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @Valid @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, - @Valid @RequestPart(value = "enum_form_string", required = false) String enumFormString + @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, + @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString ); @@ -354,8 +354,8 @@ Mono> testInlineAdditionalProperties( contentType = "application/x-www-form-urlencoded" ) Mono> testJsonFormData( - @Valid @RequestPart(value = "param", required = true) String param, - @Valid @RequestPart(value = "param2", required = true) String param2 + @Valid @RequestParam(value = "param", required = true) String param, + @Valid @RequestParam(value = "param2", required = true) String param2 ); diff --git a/samples/client/petstore/spring-http-interface-reactive-bean-validation/src/main/java/org/openapitools/api/PetApi.java b/samples/client/petstore/spring-http-interface-reactive-bean-validation/src/main/java/org/openapitools/api/PetApi.java index 05be1b2127b9..78380105a1a7 100644 --- a/samples/client/petstore/spring-http-interface-reactive-bean-validation/src/main/java/org/openapitools/api/PetApi.java +++ b/samples/client/petstore/spring-http-interface-reactive-bean-validation/src/main/java/org/openapitools/api/PetApi.java @@ -172,8 +172,8 @@ Mono> updatePet( ) Mono> updatePetWithForm( @PathVariable("petId") Long petId, - @Valid @RequestPart(value = "name", required = false) String name, - @Valid @RequestPart(value = "status", required = false) String status + @Valid @RequestParam(value = "name", required = false) String name, + @Valid @RequestParam(value = "status", required = false) String status ); diff --git a/samples/client/petstore/spring-http-interface-reactive-noResponseEntity/src/main/java/org/openapitools/api/FakeApi.java b/samples/client/petstore/spring-http-interface-reactive-noResponseEntity/src/main/java/org/openapitools/api/FakeApi.java index b467f726e9d9..abd760ef2b76 100644 --- a/samples/client/petstore/spring-http-interface-reactive-noResponseEntity/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/client/petstore/spring-http-interface-reactive-noResponseEntity/src/main/java/org/openapitools/api/FakeApi.java @@ -205,7 +205,7 @@ Mono testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -227,20 +227,20 @@ Mono testClientModel( contentType = "application/x-www-form-urlencoded" ) Mono testEndpointParameters( - @RequestPart(value = "number", required = true) BigDecimal number, - @RequestPart(value = "double", required = true) Double _double, - @RequestPart(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @RequestPart(value = "byte", required = true) byte[] _byte, - @RequestPart(value = "integer", required = false) Integer integer, - @RequestPart(value = "int32", required = false) Integer int32, - @RequestPart(value = "int64", required = false) Long int64, - @RequestPart(value = "float", required = false) Float _float, - @RequestPart(value = "string", required = false) String string, + @RequestParam(value = "number", required = true) BigDecimal number, + @RequestParam(value = "double", required = true) Double _double, + @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, + @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, + @RequestParam(value = "integer", required = false) Integer integer, + @RequestParam(value = "int32", required = false) Integer int32, + @RequestParam(value = "int64", required = false) Long int64, + @RequestParam(value = "float", required = false) Float _float, + @RequestParam(value = "string", required = false) String string, @RequestPart(value = "binary", required = false) Part binary, - @RequestPart(value = "date", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date, - @RequestPart(value = "dateTime", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) OffsetDateTime dateTime, - @RequestPart(value = "password", required = false) String password, - @RequestPart(value = "callback", required = false) String paramCallback + @RequestParam(value = "date", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date, + @RequestParam(value = "dateTime", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) OffsetDateTime dateTime, + @RequestParam(value = "password", required = false) String password, + @RequestParam(value = "callback", required = false) String paramCallback ); @@ -274,8 +274,8 @@ Mono testEnumParameters( @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, - @RequestPart(value = "enum_form_string", required = false) String enumFormString + @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, + @RequestParam(value = "enum_form_string", required = false) String enumFormString ); @@ -345,8 +345,8 @@ Mono testInlineAdditionalProperties( contentType = "application/x-www-form-urlencoded" ) Mono testJsonFormData( - @RequestPart(value = "param", required = true) String param, - @RequestPart(value = "param2", required = true) String param2 + @RequestParam(value = "param", required = true) String param, + @RequestParam(value = "param2", required = true) String param2 ); diff --git a/samples/client/petstore/spring-http-interface-reactive-noResponseEntity/src/main/java/org/openapitools/api/PetApi.java b/samples/client/petstore/spring-http-interface-reactive-noResponseEntity/src/main/java/org/openapitools/api/PetApi.java index 75fec8644b46..712168886d4c 100644 --- a/samples/client/petstore/spring-http-interface-reactive-noResponseEntity/src/main/java/org/openapitools/api/PetApi.java +++ b/samples/client/petstore/spring-http-interface-reactive-noResponseEntity/src/main/java/org/openapitools/api/PetApi.java @@ -195,8 +195,8 @@ Mono updatePet( ) Mono updatePetWithForm( @PathVariable("petId") Long petId, - @RequestPart(value = "name", required = false) String name, - @RequestPart(value = "status", required = false) String status + @RequestParam(value = "name", required = false) String name, + @RequestParam(value = "status", required = false) String status ); diff --git a/samples/client/petstore/spring-http-interface-reactive/src/main/java/org/openapitools/api/FakeApi.java b/samples/client/petstore/spring-http-interface-reactive/src/main/java/org/openapitools/api/FakeApi.java index 3c7c45ec49cc..afeee523fe0a 100644 --- a/samples/client/petstore/spring-http-interface-reactive/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/client/petstore/spring-http-interface-reactive/src/main/java/org/openapitools/api/FakeApi.java @@ -197,7 +197,7 @@ Mono> testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -218,20 +218,20 @@ Mono> testClientModel( contentType = "application/x-www-form-urlencoded" ) Mono> testEndpointParameters( - @RequestPart(value = "number", required = true) BigDecimal number, - @RequestPart(value = "double", required = true) Double _double, - @RequestPart(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @RequestPart(value = "byte", required = true) byte[] _byte, - @RequestPart(value = "integer", required = false) Integer integer, - @RequestPart(value = "int32", required = false) Integer int32, - @RequestPart(value = "int64", required = false) Long int64, - @RequestPart(value = "float", required = false) Float _float, - @RequestPart(value = "string", required = false) String string, + @RequestParam(value = "number", required = true) BigDecimal number, + @RequestParam(value = "double", required = true) Double _double, + @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, + @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, + @RequestParam(value = "integer", required = false) Integer integer, + @RequestParam(value = "int32", required = false) Integer int32, + @RequestParam(value = "int64", required = false) Long int64, + @RequestParam(value = "float", required = false) Float _float, + @RequestParam(value = "string", required = false) String string, @RequestPart(value = "binary", required = false) Part binary, - @RequestPart(value = "date", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date, - @RequestPart(value = "dateTime", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) OffsetDateTime dateTime, - @RequestPart(value = "password", required = false) String password, - @RequestPart(value = "callback", required = false) String paramCallback + @RequestParam(value = "date", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date, + @RequestParam(value = "dateTime", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) OffsetDateTime dateTime, + @RequestParam(value = "password", required = false) String password, + @RequestParam(value = "callback", required = false) String paramCallback ); @@ -264,8 +264,8 @@ Mono> testEnumParameters( @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, - @RequestPart(value = "enum_form_string", required = false) String enumFormString + @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, + @RequestParam(value = "enum_form_string", required = false) String enumFormString ); @@ -332,8 +332,8 @@ Mono> testInlineAdditionalProperties( contentType = "application/x-www-form-urlencoded" ) Mono> testJsonFormData( - @RequestPart(value = "param", required = true) String param, - @RequestPart(value = "param2", required = true) String param2 + @RequestParam(value = "param", required = true) String param, + @RequestParam(value = "param2", required = true) String param2 ); diff --git a/samples/client/petstore/spring-http-interface-reactive/src/main/java/org/openapitools/api/PetApi.java b/samples/client/petstore/spring-http-interface-reactive/src/main/java/org/openapitools/api/PetApi.java index 103fd5621774..af81f686d6ed 100644 --- a/samples/client/petstore/spring-http-interface-reactive/src/main/java/org/openapitools/api/PetApi.java +++ b/samples/client/petstore/spring-http-interface-reactive/src/main/java/org/openapitools/api/PetApi.java @@ -187,8 +187,8 @@ Mono> updatePet( ) Mono> updatePetWithForm( @PathVariable("petId") Long petId, - @RequestPart(value = "name", required = false) String name, - @RequestPart(value = "status", required = false) String status + @RequestParam(value = "name", required = false) String name, + @RequestParam(value = "status", required = false) String status ); diff --git a/samples/client/petstore/spring-http-interface-springboot-4/src/main/java/org/openapitools/api/FakeApi.java b/samples/client/petstore/spring-http-interface-springboot-4/src/main/java/org/openapitools/api/FakeApi.java index 6e73da75a378..f0385e54c3ae 100644 --- a/samples/client/petstore/spring-http-interface-springboot-4/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/client/petstore/spring-http-interface-springboot-4/src/main/java/org/openapitools/api/FakeApi.java @@ -215,7 +215,7 @@ ResponseEntity testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -239,7 +239,7 @@ ResponseEntity testEndpointParameters( @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Valid @RequestParam(value = "byte", required = true) byte[] _byte, + @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, @Min(value = 10) @Max(value = 100) @Valid @RequestParam(value = "integer", required = false) Integer integer, @Min(value = 20) @Max(value = 200) @Valid @RequestParam(value = "int32", required = false) Integer int32, @Valid @RequestParam(value = "int64", required = false) Long int64, @@ -282,7 +282,7 @@ ResponseEntity testEnumParameters( @Valid @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @Valid @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @Valid @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, + @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString ); diff --git a/samples/client/petstore/spring-http-interface-useHttpServiceProxyFactoryInterfacesConfigurator/src/main/java/org/openapitools/api/FakeApi.java b/samples/client/petstore/spring-http-interface-useHttpServiceProxyFactoryInterfacesConfigurator/src/main/java/org/openapitools/api/FakeApi.java index 316ff91cb2a3..fcd41636a321 100644 --- a/samples/client/petstore/spring-http-interface-useHttpServiceProxyFactoryInterfacesConfigurator/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/client/petstore/spring-http-interface-useHttpServiceProxyFactoryInterfacesConfigurator/src/main/java/org/openapitools/api/FakeApi.java @@ -196,7 +196,7 @@ ResponseEntity testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -220,7 +220,7 @@ ResponseEntity testEndpointParameters( @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Valid @RequestParam(value = "byte", required = true) byte[] _byte, + @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, @Min(value = 10) @Max(value = 100) @Valid @RequestParam(value = "integer", required = false) Integer integer, @Min(value = 20) @Max(value = 200) @Valid @RequestParam(value = "int32", required = false) Integer int32, @Valid @RequestParam(value = "int64", required = false) Long int64, @@ -263,7 +263,7 @@ ResponseEntity testEnumParameters( @Valid @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @Valid @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @Valid @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, + @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString ); diff --git a/samples/client/petstore/spring-http-interface/src/main/java/org/openapitools/api/FakeApi.java b/samples/client/petstore/spring-http-interface/src/main/java/org/openapitools/api/FakeApi.java index 836a70922310..f8f76991fe79 100644 --- a/samples/client/petstore/spring-http-interface/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/client/petstore/spring-http-interface/src/main/java/org/openapitools/api/FakeApi.java @@ -193,7 +193,7 @@ ResponseEntity testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -217,7 +217,7 @@ ResponseEntity testEndpointParameters( @RequestParam(value = "number", required = true) BigDecimal number, @RequestParam(value = "double", required = true) Double _double, @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @RequestParam(value = "byte", required = true) byte[] _byte, + @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, @RequestParam(value = "integer", required = false) Integer integer, @RequestParam(value = "int32", required = false) Integer int32, @RequestParam(value = "int64", required = false) Long int64, @@ -260,7 +260,7 @@ ResponseEntity testEnumParameters( @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, + @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, @RequestParam(value = "enum_form_string", required = false) String enumFormString ); diff --git a/samples/openapi3/client/petstore/spring-cloud-oas3-fakeapi/src/main/java/org/openapitools/api/FakeApi.java b/samples/openapi3/client/petstore/spring-cloud-oas3-fakeapi/src/main/java/org/openapitools/api/FakeApi.java index da305c464065..a37e76569904 100644 --- a/samples/openapi3/client/petstore/spring-cloud-oas3-fakeapi/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/openapi3/client/petstore/spring-cloud-oas3-fakeapi/src/main/java/org/openapitools/api/FakeApi.java @@ -279,7 +279,7 @@ ResponseEntity testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -315,7 +315,7 @@ ResponseEntity testEndpointParameters( @Parameter(name = "number", description = "None", required = true) @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, @Parameter(name = "double", description = "None", required = true) @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, @Parameter(name = "pattern_without_delimiter", description = "None", required = true) @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) byte[] _byte, + @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, @Parameter(name = "integer", description = "None") @Min(value = 10) @Max(value = 100) @Valid @RequestParam(value = "integer", required = false) Integer integer, @Parameter(name = "int32", description = "None") @Min(value = 20) @Max(value = 200) @Valid @RequestParam(value = "int32", required = false) Integer int32, @Parameter(name = "int64", description = "None") @Valid @RequestParam(value = "int64", required = false) Long int64, @@ -367,7 +367,7 @@ ResponseEntity testEnumParameters( @Parameter(name = "enum_query_string", description = "Query parameter enum test (string)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @Parameter(name = "enum_query_integer", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @Parameter(name = "enum_query_double", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, + @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, @Parameter(name = "enum_form_string", description = "Form parameter enum test (string)") @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString ); diff --git a/samples/openapi3/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/FakeApi.java b/samples/openapi3/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/FakeApi.java index 700e045b496e..95dbb0e0eca3 100644 --- a/samples/openapi3/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/openapi3/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/FakeApi.java @@ -328,7 +328,7 @@ default ResponseEntity testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -364,7 +364,7 @@ default ResponseEntity testEndpointParameters( @Parameter(name = "number", description = "None", required = true) @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, @Parameter(name = "double", description = "None", required = true) @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, @Parameter(name = "pattern_without_delimiter", description = "None", required = true) @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) byte[] _byte, + @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, @Parameter(name = "integer", description = "None") @Min(value = 10) @Max(value = 100) @Valid @RequestParam(value = "integer", required = false) Integer integer, @Parameter(name = "int32", description = "None") @Min(value = 20) @Max(value = 200) @Valid @RequestParam(value = "int32", required = false) Integer int32, @Parameter(name = "int64", description = "None") @Valid @RequestParam(value = "int64", required = false) Long int64, @@ -418,7 +418,7 @@ default ResponseEntity testEnumParameters( @Parameter(name = "enum_query_string", description = "Query parameter enum test (string)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @Parameter(name = "enum_query_integer", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @Parameter(name = "enum_query_double", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, + @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, @Parameter(name = "enum_form_string", description = "Form parameter enum test (string)") @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString ) { return getDelegate().testEnumParameters(enumHeaderStringArray, enumHeaderString, enumQueryStringArray, enumQueryString, enumQueryInteger, enumQueryDouble, enumFormStringArray, enumFormString); diff --git a/samples/openapi3/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/FakeApiDelegate.java b/samples/openapi3/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/FakeApiDelegate.java index 5b6cdd7f828f..fc5d2b5a6d98 100644 --- a/samples/openapi3/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/FakeApiDelegate.java +++ b/samples/openapi3/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/FakeApiDelegate.java @@ -189,7 +189,7 @@ default ResponseEntity testClientModel(Client client) { * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -207,7 +207,7 @@ default ResponseEntity testClientModel(Client client) { default ResponseEntity testEndpointParameters(BigDecimal number, Double _double, String patternWithoutDelimiter, - byte[] _byte, + String /* base64 encoded binary */ _byte, Integer integer, Integer int32, Long int64, diff --git a/samples/openapi3/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/FakeApi.java b/samples/openapi3/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/FakeApi.java index 3bd55f263449..9cb79eed3d58 100644 --- a/samples/openapi3/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/openapi3/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/FakeApi.java @@ -368,7 +368,7 @@ default ResponseEntity testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -404,7 +404,7 @@ default ResponseEntity testEndpointParameters( @Parameter(name = "number", description = "None", required = true) @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, @Parameter(name = "double", description = "None", required = true) @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, @Parameter(name = "pattern_without_delimiter", description = "None", required = true) @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) byte[] _byte, + @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, @Parameter(name = "integer", description = "None") @Min(value = 10) @Max(value = 100) @Valid @RequestParam(value = "integer", required = false) Integer integer, @Parameter(name = "int32", description = "None") @Min(value = 20) @Max(value = 200) @Valid @RequestParam(value = "int32", required = false) Integer int32, @Parameter(name = "int64", description = "None") @Valid @RequestParam(value = "int64", required = false) Long int64, @@ -459,7 +459,7 @@ default ResponseEntity testEnumParameters( @Parameter(name = "enum_query_string", description = "Query parameter enum test (string)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @Parameter(name = "enum_query_integer", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @Parameter(name = "enum_query_double", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, + @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, @Parameter(name = "enum_form_string", description = "Form parameter enum test (string)") @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString ) { return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); diff --git a/samples/server/petstore/java-camel/src/test/java/org/openapitools/api/PetApiTest.java b/samples/server/petstore/java-camel/src/test/java/org/openapitools/api/PetApiTest.java index db242ade0a0a..e55f136c415e 100644 --- a/samples/server/petstore/java-camel/src/test/java/org/openapitools/api/PetApiTest.java +++ b/samples/server/petstore/java-camel/src/test/java/org/openapitools/api/PetApiTest.java @@ -1,5 +1,5 @@ -/** -* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (7.11.0-SNAPSHOT). +/* +* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (7.20.0-SNAPSHOT). * https://openapi-generator.tech * Do not edit the class manually. */ diff --git a/samples/server/petstore/java-camel/src/test/java/org/openapitools/api/StoreApiTest.java b/samples/server/petstore/java-camel/src/test/java/org/openapitools/api/StoreApiTest.java index 2316853508bc..249efd225573 100644 --- a/samples/server/petstore/java-camel/src/test/java/org/openapitools/api/StoreApiTest.java +++ b/samples/server/petstore/java-camel/src/test/java/org/openapitools/api/StoreApiTest.java @@ -1,5 +1,5 @@ -/** -* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (7.11.0-SNAPSHOT). +/* +* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (7.20.0-SNAPSHOT). * https://openapi-generator.tech * Do not edit the class manually. */ diff --git a/samples/server/petstore/java-camel/src/test/java/org/openapitools/api/UserApiTest.java b/samples/server/petstore/java-camel/src/test/java/org/openapitools/api/UserApiTest.java index 9d71548a6d7f..199e78ab9152 100644 --- a/samples/server/petstore/java-camel/src/test/java/org/openapitools/api/UserApiTest.java +++ b/samples/server/petstore/java-camel/src/test/java/org/openapitools/api/UserApiTest.java @@ -1,5 +1,5 @@ -/** -* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (7.11.0-SNAPSHOT). +/* +* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (7.20.0-SNAPSHOT). * https://openapi-generator.tech * Do not edit the class manually. */ diff --git a/samples/server/petstore/spring-boot-defaultInterface-unhandledExcp/src/main/java/org/openapitools/api/FakeApi.java b/samples/server/petstore/spring-boot-defaultInterface-unhandledExcp/src/main/java/org/openapitools/api/FakeApi.java index 59eeed7a8269..9f8700b7e4a2 100644 --- a/samples/server/petstore/spring-boot-defaultInterface-unhandledExcp/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/server/petstore/spring-boot-defaultInterface-unhandledExcp/src/main/java/org/openapitools/api/FakeApi.java @@ -307,7 +307,7 @@ ResponseEntity testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -343,7 +343,7 @@ ResponseEntity testEndpointParameters( @Parameter(name = "number", description = "None", required = true) @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, @Parameter(name = "double", description = "None", required = true) @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, @Parameter(name = "pattern_without_delimiter", description = "None", required = true) @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) byte[] _byte, + @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, @Parameter(name = "integer", description = "None") @Min(value = 10) @Max(value = 100) @Valid @RequestParam(value = "integer", required = false) Integer integer, @Parameter(name = "int32", description = "None") @Min(value = 20) @Max(value = 200) @Valid @RequestParam(value = "int32", required = false) Integer int32, @Parameter(name = "int64", description = "None") @Valid @RequestParam(value = "int64", required = false) Long int64, @@ -395,7 +395,7 @@ ResponseEntity testEnumParameters( @Parameter(name = "enum_query_string", description = "Query parameter enum test (string)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @Parameter(name = "enum_query_integer", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @Parameter(name = "enum_query_double", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, + @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, @Parameter(name = "enum_form_string", description = "Form parameter enum test (string)") @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString ) throws Exception; diff --git a/samples/server/petstore/springboot-beanvalidation-no-nullable/src/main/java/org/openapitools/api/FakeApi.java b/samples/server/petstore/springboot-beanvalidation-no-nullable/src/main/java/org/openapitools/api/FakeApi.java index 5f74932d8aaf..5a4dc064a48d 100644 --- a/samples/server/petstore/springboot-beanvalidation-no-nullable/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/server/petstore/springboot-beanvalidation-no-nullable/src/main/java/org/openapitools/api/FakeApi.java @@ -368,7 +368,7 @@ default ResponseEntity testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -404,7 +404,7 @@ default ResponseEntity testEndpointParameters( @Parameter(name = "number", description = "None", required = true) @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, @Parameter(name = "double", description = "None", required = true) @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, @Parameter(name = "pattern_without_delimiter", description = "None", required = true) @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) byte[] _byte, + @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, @Parameter(name = "integer", description = "None") @Min(value = 10) @Max(value = 100) @Valid @RequestParam(value = "integer", required = false) Integer integer, @Parameter(name = "int32", description = "None") @Min(value = 20) @Max(value = 200) @Valid @RequestParam(value = "int32", required = false) Integer int32, @Parameter(name = "int64", description = "None") @Valid @RequestParam(value = "int64", required = false) Long int64, @@ -459,7 +459,7 @@ default ResponseEntity testEnumParameters( @Parameter(name = "enum_query_string", description = "Query parameter enum test (string)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @Parameter(name = "enum_query_integer", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @Parameter(name = "enum_query_double", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, + @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, @Parameter(name = "enum_form_string", description = "Form parameter enum test (string)") @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString ) { return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); diff --git a/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/FakeApi.java b/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/FakeApi.java index 5f74932d8aaf..5a4dc064a48d 100644 --- a/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/FakeApi.java @@ -368,7 +368,7 @@ default ResponseEntity testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -404,7 +404,7 @@ default ResponseEntity testEndpointParameters( @Parameter(name = "number", description = "None", required = true) @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, @Parameter(name = "double", description = "None", required = true) @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, @Parameter(name = "pattern_without_delimiter", description = "None", required = true) @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) byte[] _byte, + @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, @Parameter(name = "integer", description = "None") @Min(value = 10) @Max(value = 100) @Valid @RequestParam(value = "integer", required = false) Integer integer, @Parameter(name = "int32", description = "None") @Min(value = 20) @Max(value = 200) @Valid @RequestParam(value = "int32", required = false) Integer int32, @Parameter(name = "int64", description = "None") @Valid @RequestParam(value = "int64", required = false) Long int64, @@ -459,7 +459,7 @@ default ResponseEntity testEnumParameters( @Parameter(name = "enum_query_string", description = "Query parameter enum test (string)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @Parameter(name = "enum_query_integer", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @Parameter(name = "enum_query_double", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, + @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, @Parameter(name = "enum_form_string", description = "Form parameter enum test (string)") @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString ) { return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); diff --git a/samples/server/petstore/springboot-builtin-validation/src/main/java/org/openapitools/api/FakeApi.java b/samples/server/petstore/springboot-builtin-validation/src/main/java/org/openapitools/api/FakeApi.java index f7a6a0fdc8a3..4ad801c5e6c6 100644 --- a/samples/server/petstore/springboot-builtin-validation/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/server/petstore/springboot-builtin-validation/src/main/java/org/openapitools/api/FakeApi.java @@ -368,7 +368,7 @@ default ResponseEntity testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -404,7 +404,7 @@ default ResponseEntity testEndpointParameters( @Parameter(name = "number", description = "None", required = true) @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, @Parameter(name = "double", description = "None", required = true) @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, @Parameter(name = "pattern_without_delimiter", description = "None", required = true) @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) byte[] _byte, + @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, @Parameter(name = "integer", description = "None") @Min(value = 10) @Max(value = 100) @Valid @RequestParam(value = "integer", required = false) Integer integer, @Parameter(name = "int32", description = "None") @Min(value = 20) @Max(value = 200) @Valid @RequestParam(value = "int32", required = false) Integer int32, @Parameter(name = "int64", description = "None") @Valid @RequestParam(value = "int64", required = false) Long int64, @@ -459,7 +459,7 @@ default ResponseEntity testEnumParameters( @Parameter(name = "enum_query_string", description = "Query parameter enum test (string)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @Parameter(name = "enum_query_integer", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @Parameter(name = "enum_query_double", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, + @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, @Parameter(name = "enum_form_string", description = "Form parameter enum test (string)") @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString ) { return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); diff --git a/samples/server/petstore/springboot-byte-format-edge-cases-reactive/.openapi-generator-ignore b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/.openapi-generator-ignore new file mode 100644 index 000000000000..7484ee590a38 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/.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/server/petstore/springboot-byte-format-edge-cases-reactive/.openapi-generator/FILES b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/.openapi-generator/FILES new file mode 100644 index 000000000000..7e2ea15534aa --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/.openapi-generator/FILES @@ -0,0 +1,8 @@ +README.md +pom.xml +src/main/java/org/openapitools/api/ApiUtil.java +src/main/java/org/openapitools/api/CoverageApi.java +src/main/java/org/openapitools/configuration/EnumConverterConfiguration.java +src/main/java/org/openapitools/model/FormParamsRequest.java +src/main/java/org/openapitools/model/MultipartMixedRequestMarker.java +src/main/java/org/openapitools/model/MultipartMixedStatus.java diff --git a/samples/server/petstore/springboot-byte-format-edge-cases-reactive/.openapi-generator/VERSION b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/.openapi-generator/VERSION new file mode 100644 index 000000000000..32a8cfaceeb9 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/.openapi-generator/VERSION @@ -0,0 +1 @@ +7.26.0-SNAPSHOT diff --git a/samples/server/petstore/springboot-byte-format-edge-cases-reactive/README.md b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/README.md new file mode 100644 index 000000000000..35ac4f77e389 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/README.md @@ -0,0 +1,27 @@ + +# OpenAPI generated API stub + +Spring Framework stub + + +## Overview +This code was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. +By using the [OpenAPI-Spec](https://openapis.org), you can easily generate an API stub. +This is an example of building API stub interfaces in Java using the Spring framework. + +The stubs generated can be used in your existing Spring-WebFlux or Spring-Boot application to create controller endpoints +by adding ```@Controller``` classes that implement the interface. Eg: +```java +@Controller +public class PetController implements PetApi { +// implement all PetApi methods +} +``` + +You can also use the interface to create [Spring-Cloud Feign clients](http://projects.spring.io/spring-cloud/spring-cloud.html#spring-cloud-feign-inheritance).Eg: +```java +@FeignClient(name="pet", url="http://petstore.swagger.io/v2") +public interface PetClient extends PetApi { + +} +``` diff --git a/samples/server/petstore/springboot-byte-format-edge-cases-reactive/pom.xml b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/pom.xml new file mode 100644 index 000000000000..f3f429517a78 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/pom.xml @@ -0,0 +1,84 @@ + + 4.0.0 + org.openapitools + springboot + jar + springboot + 1.0.0-SNAPSHOT + + 17 + ${java.version} + UTF-8 + 2.6.0 + 5.17.14 + + + org.springframework.boot + spring-boot-starter-parent + 3.3.13 + + + + + src/main/java + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + + + + + org.springframework.boot + spring-boot-starter-webflux + + + org.springframework.data + spring-data-commons + + + + org.springdoc + springdoc-openapi-starter-webflux-ui + ${springdoc.version} + + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + org.openapitools + jackson-databind-nullable + 0.2.11 + + + + org.springframework.boot + spring-boot-starter-validation + + + com.fasterxml.jackson.core + jackson-databind + + + org.springframework.boot + spring-boot-starter-test + test + + + diff --git a/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/OpenApiGeneratorApplication.java b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/OpenApiGeneratorApplication.java new file mode 100644 index 000000000000..97252a8a9402 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/OpenApiGeneratorApplication.java @@ -0,0 +1,30 @@ +package org.openapitools; + +import com.fasterxml.jackson.databind.Module; +import org.openapitools.jackson.nullable.JsonNullableModule; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.FilterType; +import org.springframework.context.annotation.FullyQualifiedAnnotationBeanNameGenerator; + +@SpringBootApplication( + nameGenerator = FullyQualifiedAnnotationBeanNameGenerator.class +) +@ComponentScan( + basePackages = {"org.openapitools", "org.openapitools.api" , "org.openapitools.configuration"}, + nameGenerator = FullyQualifiedAnnotationBeanNameGenerator.class +) +public class OpenApiGeneratorApplication { + + public static void main(String[] args) { + SpringApplication.run(OpenApiGeneratorApplication.class, args); + } + + @Bean(name = "org.openapitools.OpenApiGeneratorApplication.jsonNullableModule") + public Module jsonNullableModule() { + return new JsonNullableModule(); + } + +} \ No newline at end of file diff --git a/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/RFC3339DateFormat.java b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/RFC3339DateFormat.java new file mode 100644 index 000000000000..052060e8e76a --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/RFC3339DateFormat.java @@ -0,0 +1,41 @@ +package org.openapitools; + +import com.fasterxml.jackson.databind.util.StdDateFormat; + +import java.text.DateFormat; +import java.text.FieldPosition; +import java.text.ParsePosition; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.TimeZone; + +public class RFC3339DateFormat extends DateFormat { + private static final long serialVersionUID = 1L; + private static final TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC"); + + private final StdDateFormat fmt = new StdDateFormat() + .withTimeZone(TIMEZONE_Z) + .withColonInTimeZone(true); + + public RFC3339DateFormat() { + this.calendar = new GregorianCalendar(); + } + + @Override + public Date parse(String source, ParsePosition pos) { + return fmt.parse(source, pos); + } + + @Override + public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { + return fmt.format(date, toAppendTo, fieldPosition); + } + + @Override + public Object clone() { + // Delegate to DateFormat's own clone(), which creates a distinct instance and clones the + // mutable `calendar`/`numberFormat` fields; returning `this` would violate the + // Cloneable/DateFormat contract and share mutable state between callers. + return super.clone(); + } +} \ No newline at end of file diff --git a/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/api/ApiUtil.java b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/api/ApiUtil.java new file mode 100644 index 000000000000..7ed3b0ab28d9 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/api/ApiUtil.java @@ -0,0 +1,20 @@ +package org.openapitools.api; + +import java.nio.charset.StandardCharsets; +import org.springframework.core.io.buffer.DefaultDataBuffer; +import org.springframework.core.io.buffer.DefaultDataBufferFactory; +import org.springframework.http.MediaType; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Mono; + +public class ApiUtil { + public static Mono getExampleResponse(ServerWebExchange exchange, MediaType mediaType, String example) { + ServerHttpResponse response = exchange.getResponse(); + response.getHeaders().setContentType(mediaType); + + byte[] exampleBytes = example.getBytes(StandardCharsets.UTF_8); + DefaultDataBuffer data = new DefaultDataBufferFactory().wrap(exampleBytes); + return response.writeWith(Mono.just(data)); + } +} diff --git a/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/api/CoverageApi.java b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/api/CoverageApi.java new file mode 100644 index 000000000000..6bf198f0fe24 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/api/CoverageApi.java @@ -0,0 +1,431 @@ +/* + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (7.26.0-SNAPSHOT). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +package org.openapitools.api; + +import org.openapitools.model.FormParamsRequest; +import org.openapitools.model.MultipartMixedRequestMarker; +import org.openapitools.model.MultipartMixedStatus; +import org.springframework.lang.Nullable; +import io.swagger.v3.oas.annotations.ExternalDocumentation; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.server.ServerWebExchange; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import org.springframework.http.codec.multipart.Part; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.*; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import jakarta.annotation.Generated; + +@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", comments = "Generator version: 7.26.0-SNAPSHOT") +@Validated +@Tag(name = "coverage", description = "the coverage API") +public interface CoverageApi { + + String PATH_BINARY_BODY = "/coverage/binary"; + /** + * POST /coverage/binary + * + * @param body (required) + * @return No content (status code 204) + */ + @Operation( + operationId = "binaryBody", + tags = { "coverage" }, + responses = { + @ApiResponse(responseCode = "204", description = "No content") + } + ) + @RequestMapping( + method = RequestMethod.POST, + value = CoverageApi.PATH_BINARY_BODY, + consumes = { "application/octet-stream" } + ) + default Mono> binaryBody( + @Parameter(name = "body", description = "", required = true) @Valid @RequestBody Mono body, + @Parameter(hidden = true) final ServerWebExchange exchange + ) { + Mono result = Mono.empty(); + + + exchange.getResponse().setStatusCode(HttpStatus.NOT_IMPLEMENTED); + + return result.then(body).then(Mono.empty()); + + } + + + String PATH_COOKIE_PARAMS = "/coverage/cookie"; + /** + * GET /coverage/cookie + * + * @param plain (optional) + * @param bytes (optional) (base64 encoded) + * @return No content (status code 204) + */ + @Operation( + operationId = "cookieParams", + tags = { "coverage" }, + responses = { + @ApiResponse(responseCode = "204", description = "No content") + } + ) + @RequestMapping( + method = RequestMethod.GET, + value = CoverageApi.PATH_COOKIE_PARAMS + ) + default Mono> cookieParams( + @Parameter(name = "plain", description = "", in = ParameterIn.COOKIE) @CookieValue(name = "plain", required = false) @Nullable String plain, + @Parameter(name = "bytes", description = "", in = ParameterIn.COOKIE) @CookieValue(name = "bytes", required = false) @Nullable String /* base64 encoded binary */ bytes, + @Parameter(hidden = true) final ServerWebExchange exchange + ) { + Mono result = Mono.empty(); + + + exchange.getResponse().setStatusCode(HttpStatus.NOT_IMPLEMENTED); + + return result.then(Mono.empty()); + + } + + + String PATH_FORM_PARAMS = "/coverage/form"; + /** + * POST /coverage/form + * + * @param plain (optional) + * @param bytes (optional) (base64 encoded) + * @return No content (status code 204) + */ + @Operation( + operationId = "formParams", + tags = { "coverage" }, + responses = { + @ApiResponse(responseCode = "204", description = "No content") + } + ) + @RequestMapping( + method = RequestMethod.POST, + value = CoverageApi.PATH_FORM_PARAMS, + consumes = { "application/x-www-form-urlencoded" } + ) + default Mono> formParams( + @Parameter(name = "plain", description = "") @Valid @RequestParam(value = "plain", required = false) String plain, + @Parameter(name = "bytes", description = "") @Valid @RequestParam(value = "bytes", required = false) String bytes /* base64 encoded binary */, + @Parameter(hidden = true) final ServerWebExchange exchange + ) { + Mono result = Mono.empty(); + + + exchange.getResponse().setStatusCode(HttpStatus.NOT_IMPLEMENTED); + + return result.then(Mono.empty()); + + } + + + String PATH_HEADER_PARAMS = "/coverage/header"; + /** + * GET /coverage/header + * + * @param xPlain (optional) + * @param xByte (optional) (base64 encoded) + * @return No content (status code 204) + */ + @Operation( + operationId = "headerParams", + tags = { "coverage" }, + responses = { + @ApiResponse(responseCode = "204", description = "No content") + } + ) + @RequestMapping( + method = RequestMethod.GET, + value = CoverageApi.PATH_HEADER_PARAMS + ) + default Mono> headerParams( + @Parameter(name = "X-Plain", description = "", in = ParameterIn.HEADER) @RequestHeader(value = "X-Plain", required = false) @Nullable String xPlain, + @Parameter(name = "X-Byte", description = "", in = ParameterIn.HEADER) @RequestHeader(value = "X-Byte", required = false) @Nullable String /* base64 encoded binary */ xByte, + @Parameter(hidden = true) final ServerWebExchange exchange + ) { + Mono result = Mono.empty(); + + + exchange.getResponse().setStatusCode(HttpStatus.NOT_IMPLEMENTED); + + return result.then(Mono.empty()); + + } + + + String PATH_JSON_BODY = "/coverage/json"; + /** + * POST /coverage/json + * + * @param formParamsRequest (required) + * @return No content (status code 204) + */ + @Operation( + operationId = "jsonBody", + tags = { "coverage" }, + responses = { + @ApiResponse(responseCode = "204", description = "No content") + } + ) + @RequestMapping( + method = RequestMethod.POST, + value = CoverageApi.PATH_JSON_BODY, + consumes = { "application/json" } + ) + default Mono> jsonBody( + @Parameter(name = "FormParamsRequest", description = "", required = true) @Valid @RequestBody Mono formParamsRequest, + @Parameter(hidden = true) final ServerWebExchange exchange + ) { + Mono result = Mono.empty(); + + + exchange.getResponse().setStatusCode(HttpStatus.NOT_IMPLEMENTED); + + return result.then(formParamsRequest).then(Mono.empty()); + + } + + + String PATH_MULTIPART_FILE_ARRAY = "/coverage/multipart/files"; + /** + * POST /coverage/multipart/files + * + * @param files (optional) + * @return No content (status code 204) + */ + @Operation( + operationId = "multipartFileArray", + tags = { "coverage" }, + responses = { + @ApiResponse(responseCode = "204", description = "No content") + } + ) + @RequestMapping( + method = RequestMethod.POST, + value = CoverageApi.PATH_MULTIPART_FILE_ARRAY, + consumes = { "multipart/form-data" } + ) + default Mono> multipartFileArray( + @Parameter(name = "files", description = "") @RequestPart(value = "files", required = false) Flux files, + @Parameter(hidden = true) final ServerWebExchange exchange + ) { + Mono result = Mono.empty(); + + + exchange.getResponse().setStatusCode(HttpStatus.NOT_IMPLEMENTED); + + return result.then(Mono.empty()); + + } + + + String PATH_MULTIPART_MIXED = "/coverage/multipart/mixed"; + /** + * POST /coverage/multipart/mixed + * + * @param status (required) + * @param file (required) + * @param statusArray (optional) + * @param marker (optional) + * @param markerArray (optional) + * @return No content (status code 204) + */ + @Operation( + operationId = "multipartMixed", + tags = { "coverage" }, + responses = { + @ApiResponse(responseCode = "204", description = "No content") + } + ) + @RequestMapping( + method = RequestMethod.POST, + value = CoverageApi.PATH_MULTIPART_MIXED, + consumes = { "multipart/form-data" } + ) + default Mono> multipartMixed( + @Parameter(name = "status", description = "", required = true) @Valid @RequestPart(value = "status", required = true) String /* MultipartMixedStatus */ status, + @Parameter(name = "file", description = "", required = true) @RequestPart(value = "file", required = true) Part file, + @Parameter(name = "statusArray", description = "") @RequestPart(value = "statusArray", required = false) Flux /* List */ statusArray, + @Parameter(name = "marker", description = "") @Valid @RequestPart(value = "marker", required = false) MultipartMixedRequestMarker marker, + @Parameter(name = "markerArray", description = "") @RequestPart(value = "markerArray", required = false) List<@Valid MultipartMixedRequestMarker> markerArray, + @Parameter(hidden = true) final ServerWebExchange exchange + ) { + Mono result = Mono.empty(); + + + exchange.getResponse().setStatusCode(HttpStatus.NOT_IMPLEMENTED); + + return result.then(Mono.empty()); + + } + + + String PATH_MULTIPART_SIMPLE = "/coverage/multipart/simple"; + /** + * POST /coverage/multipart/simple + * + * @param plain (optional) + * @param bytes (optional) (base64 encoded) + * @param file (optional) + * @return No content (status code 204) + */ + @Operation( + operationId = "multipartSimple", + tags = { "coverage" }, + responses = { + @ApiResponse(responseCode = "204", description = "No content") + } + ) + @RequestMapping( + method = RequestMethod.POST, + value = CoverageApi.PATH_MULTIPART_SIMPLE, + consumes = { "multipart/form-data" } + ) + default Mono> multipartSimple( + @Parameter(name = "plain", description = "") @Valid @RequestPart(value = "plain", required = false) String plain, + @Parameter(name = "bytes", description = "") @Valid @RequestPart(value = "bytes", required = false) String bytes /* base64 encoded binary */, + @Parameter(name = "file", description = "") @RequestPart(value = "file", required = false) Part file, + @Parameter(hidden = true) final ServerWebExchange exchange + ) { + Mono result = Mono.empty(); + + + exchange.getResponse().setStatusCode(HttpStatus.NOT_IMPLEMENTED); + + return result.then(Mono.empty()); + + } + + + String PATH_MULTIPART_SIMPLE_VALIDATED = "/coverage/multipart/simple-validated"; + /** + * POST /coverage/multipart/simple-validated + * + * @param plain (optional) + * @param bytes (optional) (base64 encoded) + * @param file (optional) + * @return No content (status code 204) + */ + @Operation( + operationId = "multipartSimpleValidated", + tags = { "coverage" }, + responses = { + @ApiResponse(responseCode = "204", description = "No content") + } + ) + @RequestMapping( + method = RequestMethod.POST, + value = CoverageApi.PATH_MULTIPART_SIMPLE_VALIDATED, + consumes = { "multipart/form-data" } + ) + default Mono> multipartSimpleValidated( + @Parameter(name = "plain", description = "") @Valid @RequestPart(value = "plain", required = false) String plain, + @Parameter(name = "bytes", description = "") @Valid @RequestPart(value = "bytes", required = false) String bytes /* base64 encoded binary */, + @Parameter(name = "file", description = "") @RequestPart(value = "file", required = false) Part file, + @Parameter(hidden = true) final ServerWebExchange exchange + ) { + Mono result = Mono.empty(); + + + exchange.getResponse().setStatusCode(HttpStatus.NOT_IMPLEMENTED); + + return result.then(Mono.empty()); + + } + + + String PATH_PATH_PARAMS = "/coverage/path/{plain}/{bytes}"; + /** + * GET /coverage/path/{plain}/{bytes} + * + * @param plain (required) + * @param bytes Base64-encoded value embedded in the URL path. Standard Base64 (RFC 4648 §4) can produce a `/` character, which is not safe to use unescaped inside a path segment: most servers (including Spring's default Tomcat/Jetty configuration) reject or misroute requests containing an encoded slash (`%2F`) unless the server is explicitly configured to allow it. Clients must percent-encode the value (and servers may need to enable encoded-slash handling) before using a base64 value as a path parameter. Prefer Base64URL (RFC 4648 §5, using `-`/`_` instead of `+`/`/`) or a query/body parameter to avoid this caveat entirely. (required) (base64 encoded) + * @return No content (status code 204) + */ + @Operation( + operationId = "pathParams", + tags = { "coverage" }, + responses = { + @ApiResponse(responseCode = "204", description = "No content") + } + ) + @RequestMapping( + method = RequestMethod.GET, + value = CoverageApi.PATH_PATH_PARAMS + ) + default Mono> pathParams( + @Parameter(name = "plain", description = "", required = true, in = ParameterIn.PATH) @PathVariable("plain") String plain, + @Parameter(name = "bytes", description = "Base64-encoded value embedded in the URL path. Standard Base64 (RFC 4648 §4) can produce a `/` character, which is not safe to use unescaped inside a path segment: most servers (including Spring's default Tomcat/Jetty configuration) reject or misroute requests containing an encoded slash (`%2F`) unless the server is explicitly configured to allow it. Clients must percent-encode the value (and servers may need to enable encoded-slash handling) before using a base64 value as a path parameter. Prefer Base64URL (RFC 4648 §5, using `-`/`_` instead of `+`/`/`) or a query/body parameter to avoid this caveat entirely.", required = true, in = ParameterIn.PATH) @PathVariable("bytes") String /* base64 encoded binary */ bytes, + @Parameter(hidden = true) final ServerWebExchange exchange + ) { + Mono result = Mono.empty(); + + + exchange.getResponse().setStatusCode(HttpStatus.NOT_IMPLEMENTED); + + return result.then(Mono.empty()); + + } + + + String PATH_QUERY_PARAMS = "/coverage/query"; + /** + * GET /coverage/query + * + * @param plain (optional) + * @param bytes (optional) (base64 encoded) + * @return No content (status code 204) + */ + @Operation( + operationId = "queryParams", + tags = { "coverage" }, + responses = { + @ApiResponse(responseCode = "204", description = "No content") + } + ) + @RequestMapping( + method = RequestMethod.GET, + value = CoverageApi.PATH_QUERY_PARAMS + ) + default Mono> queryParams( + @Parameter(name = "plain", description = "", in = ParameterIn.QUERY) @Valid @RequestParam(value = "plain", required = false) @Nullable String plain, + @Parameter(name = "bytes", description = "", in = ParameterIn.QUERY) @Valid @RequestParam(value = "bytes", required = false) @Nullable String /* base64 encoded binary */ bytes, + @Parameter(hidden = true) final ServerWebExchange exchange + ) { + Mono result = Mono.empty(); + + + exchange.getResponse().setStatusCode(HttpStatus.NOT_IMPLEMENTED); + + return result.then(Mono.empty()); + + } + +} diff --git a/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/api/CoverageApiTestControllerImpl.java b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/api/CoverageApiTestControllerImpl.java new file mode 100644 index 000000000000..39cf3644aaa7 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/api/CoverageApiTestControllerImpl.java @@ -0,0 +1,381 @@ +// manually created counterpart to unit tests. Do not delete! +package org.openapitools.api; + +import org.openapitools.model.FormParamsRequest; +import org.openapitools.model.MultipartMixedRequestMarker; +import org.openapitools.model.MultipartMixedStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; + +import org.springframework.core.io.Resource; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.core.io.buffer.DataBufferUtils; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.http.codec.multipart.Part; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.server.ServerWebExchange; + +@Controller +@RequestMapping("${openapi.multipartByteEdgeCaseCoverage.base-path:}") +public class CoverageApiTestControllerImpl implements CoverageApi { + + private static final Logger logger = LoggerFactory.getLogger(CoverageApiTestControllerImpl.class); + + // Expected content for binary data verification - matches test constants + private static final byte[] EXPECTED_BYTES = "hello".getBytes(StandardCharsets.UTF_8); + private static final String EXPECTED_BYTES_STRING = "hello"; + + private Mono verifyBytesContent(byte[] actual, String fieldName) { + if (!Arrays.equals(EXPECTED_BYTES, actual)) { + String actualString = new String(actual, StandardCharsets.UTF_8); + String errorMsg = fieldName + " content mismatch: expected '" + EXPECTED_BYTES_STRING + "', got '" + actualString + "'"; + logger.warn("Validation failed: {}", errorMsg); + return Mono.error(new IllegalArgumentException(errorMsg)); + } + logger.debug("Bytes verification passed for field: {}", fieldName); + return Mono.empty(); + } + + private Mono verifyBase64Content(String base64Value, String fieldName) { + try { + byte[] decoded = Base64.getDecoder().decode(base64Value); + logger.debug("Base64 decoded successfully for field: {}", fieldName); + return verifyBytesContent(decoded, fieldName); + } catch (IllegalArgumentException e) { + logger.warn("Invalid base64 in field {}: {}", fieldName, e.getMessage()); + return Mono.error(new IllegalArgumentException("Invalid base64 in " + fieldName, e)); + } + } + + // Joins the content of the given DataBuffers into a single byte array and releases each + // buffer afterwards, since pooled buffers (e.g. from Netty) must be released explicitly + // once consumed, or they leak. + private byte[] joinAndReleaseBuffers(List buffers) { + byte[] content = new byte[buffers.stream().mapToInt(DataBuffer::readableByteCount).sum()]; + int offset = 0; + for (DataBuffer buffer : buffers) { + int readable = buffer.readableByteCount(); + buffer.read(content, offset, readable); + offset += readable; + DataBufferUtils.release(buffer); + } + return content; + } + + @Override + public Mono> binaryBody( + Mono body, + ServerWebExchange exchange + ) { + return body.flatMap(resource -> { + if (resource == null) { + return Mono.error(new IllegalArgumentException("body is required")); + } + return Mono.fromCallable(() -> { + try (InputStream inputStream = resource.getInputStream()) { + byte[] content = readAllBytes(inputStream); + if (content.length == 0) { + throw new IllegalArgumentException("body content is empty"); + } + return content; + } catch (IOException e) { + throw new RuntimeException("Failed to read binary body", e); + } + }).flatMap(content -> verifyBytesContent(content, "body")); + }).then(Mono.just(new ResponseEntity(HttpStatus.NO_CONTENT))) + .onErrorResume(e -> { + exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); + return Mono.error(e); + }); + } + + private byte[] readAllBytes(InputStream inputStream) throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + int nRead; + byte[] data = new byte[1024]; + while ((nRead = inputStream.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, nRead); + } + buffer.flush(); + return buffer.toByteArray(); + } + + @Override + public Mono> cookieParams( + String plain, + String bytes, + ServerWebExchange exchange + ) { + if (bytes != null) { + return verifyBase64Content(bytes, "bytes") + .then(Mono.just(new ResponseEntity(HttpStatus.NO_CONTENT))) + .onErrorResume(e -> { + exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); + return Mono.error(e); + }); + } + return Mono.just(new ResponseEntity(HttpStatus.NO_CONTENT)); + } + + @Override + public Mono> formParams( + String plain, + String bytes, + ServerWebExchange exchange + ) { + if (bytes != null) { + return verifyBase64Content(bytes, "bytes") + .then(Mono.just(new ResponseEntity(HttpStatus.NO_CONTENT))) + .onErrorResume(e -> { + exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); + return Mono.error(e); + }); + } + return Mono.just(new ResponseEntity(HttpStatus.NO_CONTENT)); + } + + @Override + public Mono> headerParams( + String xPlain, + String xByte, + ServerWebExchange exchange + ) { + if (xByte != null) { + return verifyBase64Content(xByte, "X-Byte") + .then(Mono.just(new ResponseEntity(HttpStatus.NO_CONTENT))) + .onErrorResume(e -> { + exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); + return Mono.error(e); + }); + } + return Mono.just(new ResponseEntity(HttpStatus.NO_CONTENT)); + } + + @Override + public Mono> jsonBody( + Mono formParamsRequest, + ServerWebExchange exchange + ) { + return formParamsRequest.flatMap(request -> { + if (request == null) { + return Mono.error(new IllegalArgumentException("formParamsRequest is required")); + } + byte[] bytes = request.getBytes(); + if (bytes != null) { + return verifyBytesContent(bytes, "bytes"); + } + return Mono.empty(); + }).then(Mono.just(new ResponseEntity(HttpStatus.NO_CONTENT))) + .onErrorResume(e -> { + exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); + return Mono.error(e); + }); + } + + @Override + public Mono> multipartFileArray( + Flux files, + ServerWebExchange exchange + ) { + // Expected content for each file in the array - matches test constants + String[] expectedContents = { "content1", "content2", "content3" }; + + if (files == null) { + return Mono.just(new ResponseEntity(HttpStatus.NO_CONTENT)); + } + + return files.collectList().flatMap(partList -> { + return Flux.range(0, partList.size()) + .flatMap(i -> { + Part part = partList.get(i); + return part.content() + .collectList() + .flatMap(buffers -> { + byte[] content = joinAndReleaseBuffers(buffers); + + if (content.length == 0) { + return Mono.error(new IllegalArgumentException("files[" + i + "] content is empty")); + } + + if (i < expectedContents.length) { + byte[] expected = expectedContents[i].getBytes(StandardCharsets.UTF_8); + if (!Arrays.equals(expected, content)) { + String actualString = new String(content, StandardCharsets.UTF_8); + return Mono.error(new IllegalArgumentException( + "files[" + i + "] content mismatch: expected '" + expectedContents[i] + "', got '" + actualString + "'")); + } + } + return Mono.empty(); + }); + }) + .then(Mono.just(new ResponseEntity(HttpStatus.NO_CONTENT))); + }).onErrorResume(e -> { + exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); + return Mono.error(e); + }); + } + + @Override + public Mono> multipartMixed( + String status, + Part file, + Flux statusArray, + MultipartMixedRequestMarker marker, + List markerArray, + ServerWebExchange exchange + ) { + if (status == null) { + return Mono.error(new IllegalArgumentException("status is required")); + } + if (file == null) { + return Mono.error(new IllegalArgumentException("file is required")); + } + + // Verify enum value is valid; fromValue throws IllegalArgumentException for an unknown value + // (it never returns null), so no additional null-check is needed here. + MultipartMixedStatus.fromValue(status); + + return file.content() + .collectList() + .flatMap(buffers -> { + byte[] fileContent = joinAndReleaseBuffers(buffers); + return verifyBytesContent(fileContent, "file"); + }) + .then(statusArray != null ? + statusArray.index() + .doOnNext(tuple -> { + long index = tuple.getT1(); + String statusValue = tuple.getT2(); + try { + // fromValue throws IllegalArgumentException for an unknown value + // (it never returns null), so no additional null-check is needed. + MultipartMixedStatus.fromValue(statusValue); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("statusArray[" + index + "] contains invalid enum: " + statusValue, e); + } + }) + .then() + : Mono.empty()) + .then(Mono.fromCallable(() -> { + + // Verify POJO fields + if (marker != null) { + String name = marker.getName(); + if (name == null) { + throw new IllegalArgumentException("marker.name is required"); + } + } + + // Verify POJO array fields + if (markerArray != null) { + for (int i = 0; i < markerArray.size(); i++) { + MultipartMixedRequestMarker m = markerArray.get(i); + String name = m.getName(); + if (name == null) { + throw new IllegalArgumentException("markerArray[" + i + "].name is required"); + } + } + } + return null; + })) + .then(Mono.just(new ResponseEntity(HttpStatus.NO_CONTENT))) + .onErrorResume(e -> { + exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); + return Mono.error(e); + }); + } + + @Override + public Mono> multipartSimple( + String plain, + String bytes, + Part file, + ServerWebExchange exchange + ) { + return (bytes != null ? verifyBase64Content(bytes, "bytes") : Mono.empty()) + .then(file != null ? + file.content() + .collectList() + .doOnNext(this::joinAndReleaseBuffers) + .then(Mono.empty()) + : Mono.empty()) + .then(Mono.just(new ResponseEntity(HttpStatus.NO_CONTENT))) + .onErrorResume(e -> { + exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); + return Mono.error(e); + }); + } + + @Override + public Mono> multipartSimpleValidated( + String plain, + String bytes, + Part file, + ServerWebExchange exchange + ) { + return (bytes != null ? verifyBase64Content(bytes, "bytes") : Mono.empty()) + .then(file != null ? + file.content() + .collectList() + .flatMap(buffers -> { + byte[] fileContent = joinAndReleaseBuffers(buffers); + return verifyBytesContent(fileContent, "file"); + }).then() + : Mono.empty()) + .then(Mono.just(new ResponseEntity(HttpStatus.NO_CONTENT))) + .onErrorResume(e -> { + exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); + return Mono.error(e); + }); + } + + @Override + public Mono> pathParams( + String plain, + String bytes, + ServerWebExchange exchange + ) { + if (plain == null) { + return Mono.error(new IllegalArgumentException("plain is required")); + } + if (bytes == null) { + return Mono.error(new IllegalArgumentException("bytes is required")); + } + return verifyBase64Content(bytes, "bytes") + .then(Mono.just(new ResponseEntity(HttpStatus.NO_CONTENT))) + .onErrorResume(e -> { + exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); + return Mono.error(e); + }); + } + + @Override + public Mono> queryParams( + String plain, + String bytes, + ServerWebExchange exchange + ) { + if (bytes != null) { + return verifyBase64Content(bytes, "bytes") + .then(Mono.just(new ResponseEntity(HttpStatus.NO_CONTENT))) + .onErrorResume(e -> { + exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR); + return Mono.error(e); + }); + } + return Mono.just(new ResponseEntity(HttpStatus.NO_CONTENT)); + } +} + diff --git a/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/configuration/EnumConverterConfiguration.java b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/configuration/EnumConverterConfiguration.java new file mode 100644 index 000000000000..ccbb806c1b52 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/configuration/EnumConverterConfiguration.java @@ -0,0 +1,36 @@ +package org.openapitools.configuration; + +import java.math.BigDecimal; +import java.net.URI; +import java.util.UUID; + +import org.openapitools.model.MultipartMixedStatus; + +import jakarta.annotation.Generated; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.convert.converter.Converter; + +/** + * This class provides Spring Converter beans for the enum models in the OpenAPI specification. + * + * By default, Spring only converts primitive types to enums using Enum::valueOf, which can prevent + * correct conversion if the OpenAPI specification is using an `enumPropertyNaming` other than + * `original` or the specification has an integer enum. + */ +@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", comments = "Generator version: 7.26.0-SNAPSHOT") +@Configuration(value = "org.openapitools.configuration.enumConverterConfiguration") +public class EnumConverterConfiguration { + + @Bean(name = "org.openapitools.configuration.EnumConverterConfiguration.multipartMixedStatusConverter") + Converter multipartMixedStatusConverter() { + return new Converter() { + @Override + public MultipartMixedStatus convert(String source) { + return MultipartMixedStatus.fromValue(source); + } + }; + } + +} diff --git a/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/configuration/HomeController.java b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/configuration/HomeController.java new file mode 100644 index 000000000000..cf658246a9de --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/configuration/HomeController.java @@ -0,0 +1,29 @@ +package org.openapitools.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.ServerResponse; +import java.net.URI; + +import static org.springframework.web.reactive.function.server.RequestPredicates.GET; +import static org.springframework.web.reactive.function.server.RouterFunctions.route; + +/** + * Home redirection to OpenAPI api documentation + */ +@Controller +public class HomeController { + + @Bean + RouterFunction index() { + return route( + GET("/"), + req -> ServerResponse.temporaryRedirect(URI.create("swagger-ui.html")).build() + ); + } + +} \ No newline at end of file diff --git a/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/model/FormParamsRequest.java b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/model/FormParamsRequest.java new file mode 100644 index 000000000000..397043b7c203 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/model/FormParamsRequest.java @@ -0,0 +1,110 @@ +package org.openapitools.model; + +import java.net.URI; +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import java.util.Arrays; +import org.springframework.lang.Nullable; +import org.openapitools.jackson.nullable.JsonNullable; +import java.time.OffsetDateTime; +import jakarta.validation.Valid; +import jakarta.validation.constraints.*; +import io.swagger.v3.oas.annotations.media.Schema; + + +import java.util.*; +import jakarta.annotation.Generated; + +/** + * FormParamsRequest + */ + +@JsonTypeName("formParams_request") +@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", comments = "Generator version: 7.26.0-SNAPSHOT") +public class FormParamsRequest { + + private @Nullable String plain; + + private @Nullable byte[] bytes; + + public FormParamsRequest plain(@Nullable String plain) { + this.plain = plain; + return this; + } + + /** + * Get plain + * @return plain + */ + + @Schema(name = "plain", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("plain") + public @Nullable String getPlain() { + return plain; + } + + @JsonProperty("plain") + public void setPlain(@Nullable String plain) { + this.plain = plain; + } + + public FormParamsRequest bytes(@Nullable byte[] bytes) { + this.bytes = bytes; + return this; + } + + /** + * Get bytes + * @return bytes + */ + + @Schema(name = "bytes", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("bytes") + public @Nullable byte[] getBytes() { + return bytes; + } + + @JsonProperty("bytes") + public void setBytes(@Nullable byte[] bytes) { + this.bytes = bytes; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + FormParamsRequest formParamsRequest = (FormParamsRequest) o; + return Objects.equals(this.plain, formParamsRequest.plain) && + Arrays.equals(this.bytes, formParamsRequest.bytes); + } + + @Override + public int hashCode() { + return Objects.hash(plain, Arrays.hashCode(bytes)); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class FormParamsRequest {\n"); + sb.append(" plain: ").append(toIndentedString(plain)).append("\n"); + sb.append(" bytes: ").append(toIndentedString(bytes)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(@Nullable Object o) { + return o == null ? "null" : o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/model/MultipartMixedRequestMarker.java b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/model/MultipartMixedRequestMarker.java new file mode 100644 index 000000000000..034d4d610e10 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/model/MultipartMixedRequestMarker.java @@ -0,0 +1,143 @@ +package org.openapitools.model; + +import java.net.URI; +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import org.springframework.lang.Nullable; +import org.openapitools.jackson.nullable.JsonNullable; +import java.time.OffsetDateTime; +import jakarta.validation.Valid; +import jakarta.validation.constraints.*; +import io.swagger.v3.oas.annotations.media.Schema; + + +import java.util.*; +import jakarta.annotation.Generated; + +/** + * MultipartMixedRequestMarker + */ + +@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", comments = "Generator version: 7.26.0-SNAPSHOT") +public class MultipartMixedRequestMarker { + + private String name; + + private @Nullable Integer priority; + + private @Nullable Boolean active; + + public MultipartMixedRequestMarker() { + super(); + } + + /** + * Constructor with only required parameters + */ + public MultipartMixedRequestMarker(String name) { + this.name = name; + } + + public MultipartMixedRequestMarker name(String name) { + this.name = name; + return this; + } + + /** + * Get name + * @return name + */ + @NotNull + @Schema(name = "name", requiredMode = Schema.RequiredMode.REQUIRED) + @JsonProperty("name") + public String getName() { + return name; + } + + @JsonProperty("name") + public void setName(String name) { + this.name = name; + } + + public MultipartMixedRequestMarker priority(@Nullable Integer priority) { + this.priority = priority; + return this; + } + + /** + * Get priority + * @return priority + */ + + @Schema(name = "priority", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("priority") + public @Nullable Integer getPriority() { + return priority; + } + + @JsonProperty("priority") + public void setPriority(@Nullable Integer priority) { + this.priority = priority; + } + + public MultipartMixedRequestMarker active(@Nullable Boolean active) { + this.active = active; + return this; + } + + /** + * Get active + * @return active + */ + + @Schema(name = "active", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("active") + public @Nullable Boolean getActive() { + return active; + } + + @JsonProperty("active") + public void setActive(@Nullable Boolean active) { + this.active = active; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + MultipartMixedRequestMarker multipartMixedRequestMarker = (MultipartMixedRequestMarker) o; + return Objects.equals(this.name, multipartMixedRequestMarker.name) && + Objects.equals(this.priority, multipartMixedRequestMarker.priority) && + Objects.equals(this.active, multipartMixedRequestMarker.active); + } + + @Override + public int hashCode() { + return Objects.hash(name, priority, active); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class MultipartMixedRequestMarker {\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append(" priority: ").append(toIndentedString(priority)).append("\n"); + sb.append(" active: ").append(toIndentedString(active)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(@Nullable Object o) { + return o == null ? "null" : o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/model/MultipartMixedStatus.java b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/model/MultipartMixedStatus.java new file mode 100644 index 000000000000..987fbd5253d4 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/java/org/openapitools/model/MultipartMixedStatus.java @@ -0,0 +1,58 @@ +package org.openapitools.model; + +import java.net.URI; +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonValue; +import org.openapitools.jackson.nullable.JsonNullable; +import java.time.OffsetDateTime; +import jakarta.validation.Valid; +import jakarta.validation.constraints.*; +import io.swagger.v3.oas.annotations.media.Schema; + + +import java.util.*; +import jakarta.annotation.Generated; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Gets or Sets MultipartMixedStatus + */ + +@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", comments = "Generator version: 7.26.0-SNAPSHOT") +public enum MultipartMixedStatus { + + ALLOWED("ALLOWED"), + + IN_PROGRESS("IN_PROGRESS"), + + REJECTED("REJECTED"); + + private final String value; + + MultipartMixedStatus(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static MultipartMixedStatus fromValue(String value) { + for (MultipartMixedStatus b : MultipartMixedStatus.values()) { + if (b.value.equals(value)) { + return b; + } + } + throw new IllegalArgumentException("Unexpected value '" + value + "'"); + } +} + diff --git a/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/resources/application.properties b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/resources/application.properties new file mode 100644 index 000000000000..7e90813e59b2 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/resources/application.properties @@ -0,0 +1,3 @@ +server.port=8080 +spring.jackson.date-format=org.openapitools.RFC3339DateFormat +spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false diff --git a/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/resources/openapi.yaml b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/resources/openapi.yaml new file mode 100644 index 000000000000..0fdcb1301243 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/main/resources/openapi.yaml @@ -0,0 +1,321 @@ +openapi: 3.0.3 +info: + title: Multipart & Byte Edge Case Coverage + version: 1.0.0 +servers: +- url: / +tags: +- name: coverage +paths: + /coverage/query: + get: + operationId: queryParams + parameters: + - explode: true + in: query + name: plain + required: false + schema: + type: string + style: form + - explode: true + in: query + name: bytes + required: false + schema: + format: byte + type: string + style: form + responses: + "204": + description: No content + tags: + - coverage + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/path/{plain}/{bytes}: + get: + operationId: pathParams + parameters: + - explode: false + in: path + name: plain + required: true + schema: + type: string + style: simple + - explode: false + in: path + name: bytes + required: true + schema: + format: byte + type: string + style: simple + responses: + "204": + description: No content + tags: + - coverage + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/header: + get: + operationId: headerParams + parameters: + - explode: false + in: header + name: X-Plain + required: false + schema: + type: string + style: simple + - explode: false + in: header + name: X-Byte + required: false + schema: + format: byte + type: string + style: simple + responses: + "204": + description: No content + tags: + - coverage + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/cookie: + get: + operationId: cookieParams + parameters: + - explode: true + in: cookie + name: plain + required: false + schema: + type: string + style: form + - explode: true + in: cookie + name: bytes + required: false + schema: + format: byte + type: string + style: form + responses: + "204": + description: No content + tags: + - coverage + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/form: + post: + operationId: formParams + requestBody: + content: + application/x-www-form-urlencoded: + schema: + $ref: "#/components/schemas/formParams_request" + required: true + responses: + "204": + description: No content + tags: + - coverage + x-content-type: application/x-www-form-urlencoded + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/multipart/simple: + post: + operationId: multipartSimple + requestBody: + content: + multipart/form-data: + schema: + $ref: "#/components/schemas/multipartSimple_request" + required: true + responses: + "204": + description: No content + tags: + - coverage + x-content-type: multipart/form-data + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/multipart/simple-validated: + post: + operationId: multipartSimpleValidated + requestBody: + content: + multipart/form-data: + schema: + $ref: "#/components/schemas/multipartSimple_request" + required: true + responses: + "204": + description: No content + tags: + - coverage + x-content-type: multipart/form-data + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/multipart/files: + post: + operationId: multipartFileArray + requestBody: + content: + multipart/form-data: + schema: + $ref: "#/components/schemas/multipartFileArray_request" + responses: + "204": + description: No content + tags: + - coverage + x-content-type: multipart/form-data + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/multipart/mixed: + post: + operationId: multipartMixed + requestBody: + content: + multipart/form-data: + schema: + $ref: "#/components/schemas/multipartMixed_request" + responses: + "204": + description: No content + tags: + - coverage + x-content-type: multipart/form-data + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/json: + post: + operationId: jsonBody + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/formParams_request" + required: true + responses: + "204": + description: No content + tags: + - coverage + x-content-type: application/json + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/binary: + post: + operationId: binaryBody + requestBody: + content: + application/octet-stream: + schema: + format: binary + type: string + required: true + responses: + "204": + description: No content + tags: + - coverage + x-content-type: application/octet-stream + x-accepts: + - application/json + x-tags: + - tag: coverage +components: + schemas: + MultipartMixedStatus: + enum: + - ALLOWED + - IN_PROGRESS + - REJECTED + type: string + MultipartMixedRequestMarker: + properties: + name: + type: string + priority: + format: int32 + type: integer + active: + type: boolean + required: + - name + type: object + formParams_request: + properties: + plain: + type: string + bytes: + format: byte + type: string + type: object + multipartSimple_request: + properties: + plain: + type: string + bytes: + format: byte + type: string + file: + format: binary + type: string + type: object + multipartFileArray_request: + properties: + files: + items: + format: binary + type: string + type: array + type: object + multipartMixed_request: + properties: + status: + $ref: "#/components/schemas/MultipartMixedStatus" + statusArray: + items: + $ref: "#/components/schemas/MultipartMixedStatus" + type: array + marker: + $ref: "#/components/schemas/MultipartMixedRequestMarker" + markerArray: + items: + $ref: "#/components/schemas/MultipartMixedRequestMarker" + type: array + file: + format: binary + type: string + required: + - file + - status + type: object diff --git a/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/test/java/org/openapitools/OpenApiGeneratorApplicationTests.java b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/test/java/org/openapitools/OpenApiGeneratorApplicationTests.java new file mode 100644 index 000000000000..3681f67e7705 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/test/java/org/openapitools/OpenApiGeneratorApplicationTests.java @@ -0,0 +1,13 @@ +package org.openapitools; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class OpenApiGeneratorApplicationTests { + + @Test + void contextLoads() { + } + +} \ No newline at end of file diff --git a/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/test/java/org/openapitools/api/CoverageApiIntegrationTest.java b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/test/java/org/openapitools/api/CoverageApiIntegrationTest.java new file mode 100644 index 000000000000..7138207edbf3 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases-reactive/src/test/java/org/openapitools/api/CoverageApiIntegrationTest.java @@ -0,0 +1,346 @@ +// manually created counterpart to unit tests. Do not delete! +package org.openapitools.api; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; +import org.openapitools.model.MultipartMixedRequestMarker; +import org.openapitools.model.MultipartMixedStatus; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.http.MediaType; +import org.springframework.http.client.MultipartBodyBuilder; +import org.springframework.test.web.reactive.server.WebTestClient; +import org.springframework.web.reactive.function.BodyInserters; + +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; + + +@SpringBootTest +@AutoConfigureWebTestClient +class CoverageApiIntegrationTest { + + @Autowired + private WebTestClient webTestClient; + + @Autowired + private ObjectMapper objectMapper; + + private static final byte[] SAMPLE_BYTES = "hello".getBytes(StandardCharsets.UTF_8); + private static final String SAMPLE_BYTES_BASE64 = Base64.getEncoder().encodeToString(SAMPLE_BYTES); + + // ==================== multipartMixed tests ==================== + // Covers: enum @RequestParam, file @RequestPart, enum array @RequestParam, + // object @RequestPart, object array @RequestPart + + @Test + void multipartMixed_withRequiredFieldsOnly_returns204() throws Exception { + MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder(); + bodyBuilder.part("file", new ByteArrayResource(SAMPLE_BYTES), MediaType.APPLICATION_OCTET_STREAM); + bodyBuilder.part("status", MultipartMixedStatus.ALLOWED.getValue()); + + webTestClient + .post() + .uri(CoverageApi.PATH_MULTIPART_MIXED) + .contentType(MediaType.MULTIPART_FORM_DATA) + .body(BodyInserters.fromMultipartData(bodyBuilder.build())) + .exchange() + .expectStatus().isNoContent(); + } + + @Test + void multipartMixed_withAllFields_returns204() throws Exception { + MultipartMixedRequestMarker marker = new MultipartMixedRequestMarker("marker1") + .priority(10) + .active(true); + + List markerArray = Arrays.asList( + new MultipartMixedRequestMarker("marker2").priority(20).active(false), + new MultipartMixedRequestMarker("marker3").priority(30).active(true) + ); + + MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder(); + bodyBuilder.part("file", new ByteArrayResource(SAMPLE_BYTES), MediaType.APPLICATION_OCTET_STREAM); + bodyBuilder.part("status", MultipartMixedStatus.IN_PROGRESS.getValue()); + bodyBuilder.part("statusArray", MultipartMixedStatus.ALLOWED.getValue()); + bodyBuilder.part("statusArray", MultipartMixedStatus.REJECTED.getValue()); + bodyBuilder.part("marker", objectMapper.writeValueAsString(marker), MediaType.APPLICATION_JSON); + bodyBuilder.part("markerArray", objectMapper.writeValueAsString(markerArray), MediaType.APPLICATION_JSON); + + webTestClient + .post() + .uri(CoverageApi.PATH_MULTIPART_MIXED) + .contentType(MediaType.MULTIPART_FORM_DATA) + .body(BodyInserters.fromMultipartData(bodyBuilder.build())) + .exchange() + .expectStatus().isNoContent(); + } + + @Test + void multipartMixed_enumValue_deserializesCorrectly() { + for (MultipartMixedStatus status : MultipartMixedStatus.values()) { + MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder(); + bodyBuilder.part("file", new ByteArrayResource(SAMPLE_BYTES), MediaType.APPLICATION_OCTET_STREAM); + bodyBuilder.part("status", status.getValue()); + + webTestClient + .post() + .uri(CoverageApi.PATH_MULTIPART_MIXED) + .contentType(MediaType.MULTIPART_FORM_DATA) + .body(BodyInserters.fromMultipartData(bodyBuilder.build())) + .exchange() + .expectStatus().isNoContent(); + } + } + + // ==================== multipartSimple tests ==================== + // Covers: scalar @RequestParam, base64 bytes @RequestParam, file @RequestPart + + @Test + void multipartSimple_withAllFields_returns204() { + MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder(); + bodyBuilder.part("file", new ByteArrayResource("content".getBytes()), MediaType.TEXT_PLAIN); + bodyBuilder.part("plain", "plainText"); + bodyBuilder.part("bytes", SAMPLE_BYTES_BASE64); + + webTestClient + .post() + .uri(CoverageApi.PATH_MULTIPART_SIMPLE) + .contentType(MediaType.MULTIPART_FORM_DATA) + .body(BodyInserters.fromMultipartData(bodyBuilder.build())) + .exchange() + .expectStatus().isNoContent(); + } + + @Test + void multipartSimple_withNoFields_returns204() { + MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder(); + + webTestClient + .post() + .uri(CoverageApi.PATH_MULTIPART_SIMPLE) + .body(BodyInserters.fromMultipartData(bodyBuilder.build())) + .exchange() + .expectStatus().isNoContent(); + } + + @Test + void multipartSimple_withEmptyFilePart_returns204() { + MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder(); + bodyBuilder.part("file", new ByteArrayResource(new byte[0]), MediaType.APPLICATION_OCTET_STREAM); + + webTestClient + .post() + .uri(CoverageApi.PATH_MULTIPART_SIMPLE) + .contentType(MediaType.MULTIPART_FORM_DATA) + .body(BodyInserters.fromMultipartData(bodyBuilder.build())) + .exchange() + .expectStatus().isNoContent(); + } + + // ==================== multipartSimpleValidated tests ==================== + // Covers: validated file content deserialization + + @Test + void multipartSimpleValidated_withValidContent_returns204() { + MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder(); + bodyBuilder.part("file", new ByteArrayResource(SAMPLE_BYTES), MediaType.TEXT_PLAIN); + bodyBuilder.part("plain", "plainText"); + bodyBuilder.part("bytes", SAMPLE_BYTES_BASE64); + + webTestClient + .post() + .uri(CoverageApi.PATH_MULTIPART_SIMPLE_VALIDATED) + .contentType(MediaType.MULTIPART_FORM_DATA) + .body(BodyInserters.fromMultipartData(bodyBuilder.build())) + .exchange() + .expectStatus().isNoContent(); + } + + // ==================== multipartFileArray tests ==================== + // Covers: array of files @RequestPart List + + @Test + void multipartFileArray_withMultipleFiles_returns204() { + MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder(); + bodyBuilder.part("files", new ByteArrayResource("content1".getBytes()), MediaType.APPLICATION_OCTET_STREAM) + .filename("file1.bin"); + bodyBuilder.part("files", new ByteArrayResource("content2".getBytes()), MediaType.APPLICATION_OCTET_STREAM) + .filename("file2.bin"); + bodyBuilder.part("files", new ByteArrayResource("content3".getBytes()), MediaType.APPLICATION_OCTET_STREAM) + .filename("file3.bin"); + + webTestClient + .post() + .uri(CoverageApi.PATH_MULTIPART_FILE_ARRAY) + .contentType(MediaType.MULTIPART_FORM_DATA) + .body(BodyInserters.fromMultipartData(bodyBuilder.build())) + .exchange() + .expectStatus().isNoContent(); + } + + @Test + void multipartFileArray_withNoFiles_returns204() { + MultipartBodyBuilder bodyBuilder = new MultipartBodyBuilder(); + + webTestClient + .post() + .uri(CoverageApi.PATH_MULTIPART_FILE_ARRAY) + .body(BodyInserters.fromMultipartData(bodyBuilder.build())) + .exchange() + .expectStatus().isNoContent(); + } + + // ==================== formParams tests ==================== + // Covers: application/x-www-form-urlencoded with @RequestParam + + @Test + void formParams_withAllFields_returns204() { + webTestClient + .post() + .uri(CoverageApi.PATH_FORM_PARAMS) + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .bodyValue("plain=plainValue&bytes=" + SAMPLE_BYTES_BASE64) + .exchange() + .expectStatus().isNoContent(); + } + + @Test + void formParams_withNoFields_returns204() { + webTestClient + .post() + .uri(CoverageApi.PATH_FORM_PARAMS) + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .exchange() + .expectStatus().isNoContent(); + } + + // ==================== queryParams tests ==================== + // Covers: query string @RequestParam + + @Test + void queryParams_withAllParams_returns204() { + webTestClient + .get() + .uri(uriBuilder -> uriBuilder + .path(CoverageApi.PATH_QUERY_PARAMS) + .queryParam("plain", "queryPlain") + .queryParam("bytes", SAMPLE_BYTES_BASE64) + .build()) + .exchange() + .expectStatus().isNoContent(); + } + + @Test + void queryParams_withNoParams_returns204() { + webTestClient + .get() + .uri(CoverageApi.PATH_QUERY_PARAMS) + .exchange() + .expectStatus().isNoContent(); + } + + // ==================== pathParams tests ==================== + // Covers: @PathVariable + + @Test + void pathParams_withBothParams_returns204() { + webTestClient + .get() + .uri("/coverage/path/{plain}/{bytes}", "pathPlain", SAMPLE_BYTES_BASE64) + .exchange() + .expectStatus().isNoContent(); + } + + // ==================== headerParams tests ==================== + // Covers: @RequestHeader + + @Test + void headerParams_withAllHeaders_returns204() { + webTestClient + .get() + .uri(CoverageApi.PATH_HEADER_PARAMS) + .header("X-Plain", "headerPlain") + .header("X-Byte", SAMPLE_BYTES_BASE64) + .exchange() + .expectStatus().isNoContent(); + } + + @Test + void headerParams_withNoHeaders_returns204() { + webTestClient + .get() + .uri(CoverageApi.PATH_HEADER_PARAMS) + .exchange() + .expectStatus().isNoContent(); + } + + // ==================== cookieParams tests ==================== + // Covers: @CookieValue + + @Test + void cookieParams_withAllCookies_returns204() { + webTestClient + .get() + .uri(CoverageApi.PATH_COOKIE_PARAMS) + .cookie("plain", "cookiePlain") + .cookie("bytes", SAMPLE_BYTES_BASE64) + .exchange() + .expectStatus().isNoContent(); + } + + @Test + void cookieParams_withNoCookies_returns204() { + webTestClient + .get() + .uri(CoverageApi.PATH_COOKIE_PARAMS) + .exchange() + .expectStatus().isNoContent(); + } + + // ==================== jsonBody tests ==================== + // Covers: @RequestBody with JSON POJO + + @Test + void jsonBody_withValidBody_returns204() { + String json = "{\"plain\": \"jsonPlain\", \"bytes\": \"" + SAMPLE_BYTES_BASE64 + "\"}"; + + webTestClient + .post() + .uri(CoverageApi.PATH_JSON_BODY) + .contentType(MediaType.APPLICATION_JSON) + .bodyValue(json) + .exchange() + .expectStatus().isNoContent(); + } + + @Test + void jsonBody_withEmptyObject_returns204() { + webTestClient + .post() + .uri(CoverageApi.PATH_JSON_BODY) + .contentType(MediaType.APPLICATION_JSON) + .bodyValue("{}") + .exchange() + .expectStatus().isNoContent(); + } + + // ==================== binaryBody tests ==================== + // Covers: @RequestBody with application/octet-stream Resource + + @Test + void binaryBody_withBinaryContent_returns204() { + webTestClient + .post() + .uri(CoverageApi.PATH_BINARY_BODY) + .contentType(MediaType.APPLICATION_OCTET_STREAM) + .bodyValue(SAMPLE_BYTES) + .exchange() + .expectStatus().isNoContent(); + } + +} diff --git a/samples/server/petstore/springboot-byte-format-edge-cases/.openapi-generator-ignore b/samples/server/petstore/springboot-byte-format-edge-cases/.openapi-generator-ignore new file mode 100644 index 000000000000..7484ee590a38 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases/.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/server/petstore/springboot-byte-format-edge-cases/.openapi-generator/FILES b/samples/server/petstore/springboot-byte-format-edge-cases/.openapi-generator/FILES new file mode 100644 index 000000000000..7e2ea15534aa --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases/.openapi-generator/FILES @@ -0,0 +1,8 @@ +README.md +pom.xml +src/main/java/org/openapitools/api/ApiUtil.java +src/main/java/org/openapitools/api/CoverageApi.java +src/main/java/org/openapitools/configuration/EnumConverterConfiguration.java +src/main/java/org/openapitools/model/FormParamsRequest.java +src/main/java/org/openapitools/model/MultipartMixedRequestMarker.java +src/main/java/org/openapitools/model/MultipartMixedStatus.java diff --git a/samples/server/petstore/springboot-byte-format-edge-cases/.openapi-generator/VERSION b/samples/server/petstore/springboot-byte-format-edge-cases/.openapi-generator/VERSION new file mode 100644 index 000000000000..32a8cfaceeb9 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases/.openapi-generator/VERSION @@ -0,0 +1 @@ +7.26.0-SNAPSHOT diff --git a/samples/server/petstore/springboot-byte-format-edge-cases/README.md b/samples/server/petstore/springboot-byte-format-edge-cases/README.md new file mode 100644 index 000000000000..d43a1de307df --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases/README.md @@ -0,0 +1,27 @@ + +# OpenAPI generated API stub + +Spring Framework stub + + +## Overview +This code was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. +By using the [OpenAPI-Spec](https://openapis.org), you can easily generate an API stub. +This is an example of building API stub interfaces in Java using the Spring framework. + +The stubs generated can be used in your existing Spring-MVC or Spring-Boot application to create controller endpoints +by adding ```@Controller``` classes that implement the interface. Eg: +```java +@Controller +public class PetController implements PetApi { +// implement all PetApi methods +} +``` + +You can also use the interface to create [Spring-Cloud Feign clients](http://projects.spring.io/spring-cloud/spring-cloud.html#spring-cloud-feign-inheritance).Eg: +```java +@FeignClient(name="pet", url="http://petstore.swagger.io/v2") +public interface PetClient extends PetApi { + +} +``` diff --git a/samples/server/petstore/springboot-byte-format-edge-cases/pom.xml b/samples/server/petstore/springboot-byte-format-edge-cases/pom.xml new file mode 100644 index 000000000000..f52457852e3d --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases/pom.xml @@ -0,0 +1,84 @@ + + 4.0.0 + org.openapitools + springboot + jar + springboot + 1.0.0-SNAPSHOT + + 17 + ${java.version} + UTF-8 + 2.6.0 + 5.17.14 + + + org.springframework.boot + spring-boot-starter-parent + 3.3.13 + + + + + src/main/java + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.data + spring-data-commons + + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + ${springdoc.version} + + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + org.openapitools + jackson-databind-nullable + 0.2.11 + + + + org.springframework.boot + spring-boot-starter-validation + + + com.fasterxml.jackson.core + jackson-databind + + + org.springframework.boot + spring-boot-starter-test + test + + + diff --git a/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/OpenApiGeneratorApplication.java b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/OpenApiGeneratorApplication.java new file mode 100644 index 000000000000..97252a8a9402 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/OpenApiGeneratorApplication.java @@ -0,0 +1,30 @@ +package org.openapitools; + +import com.fasterxml.jackson.databind.Module; +import org.openapitools.jackson.nullable.JsonNullableModule; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.FilterType; +import org.springframework.context.annotation.FullyQualifiedAnnotationBeanNameGenerator; + +@SpringBootApplication( + nameGenerator = FullyQualifiedAnnotationBeanNameGenerator.class +) +@ComponentScan( + basePackages = {"org.openapitools", "org.openapitools.api" , "org.openapitools.configuration"}, + nameGenerator = FullyQualifiedAnnotationBeanNameGenerator.class +) +public class OpenApiGeneratorApplication { + + public static void main(String[] args) { + SpringApplication.run(OpenApiGeneratorApplication.class, args); + } + + @Bean(name = "org.openapitools.OpenApiGeneratorApplication.jsonNullableModule") + public Module jsonNullableModule() { + return new JsonNullableModule(); + } + +} \ No newline at end of file diff --git a/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/RFC3339DateFormat.java b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/RFC3339DateFormat.java new file mode 100644 index 000000000000..052060e8e76a --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/RFC3339DateFormat.java @@ -0,0 +1,41 @@ +package org.openapitools; + +import com.fasterxml.jackson.databind.util.StdDateFormat; + +import java.text.DateFormat; +import java.text.FieldPosition; +import java.text.ParsePosition; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.TimeZone; + +public class RFC3339DateFormat extends DateFormat { + private static final long serialVersionUID = 1L; + private static final TimeZone TIMEZONE_Z = TimeZone.getTimeZone("UTC"); + + private final StdDateFormat fmt = new StdDateFormat() + .withTimeZone(TIMEZONE_Z) + .withColonInTimeZone(true); + + public RFC3339DateFormat() { + this.calendar = new GregorianCalendar(); + } + + @Override + public Date parse(String source, ParsePosition pos) { + return fmt.parse(source, pos); + } + + @Override + public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { + return fmt.format(date, toAppendTo, fieldPosition); + } + + @Override + public Object clone() { + // Delegate to DateFormat's own clone(), which creates a distinct instance and clones the + // mutable `calendar`/`numberFormat` fields; returning `this` would violate the + // Cloneable/DateFormat contract and share mutable state between callers. + return super.clone(); + } +} \ No newline at end of file diff --git a/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/api/ApiUtil.java b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/api/ApiUtil.java new file mode 100644 index 000000000000..44bf770ccc47 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/api/ApiUtil.java @@ -0,0 +1,21 @@ +package org.openapitools.api; + +import org.springframework.web.context.request.NativeWebRequest; + +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class ApiUtil { + public static void setExampleResponse(NativeWebRequest req, String contentType, String example) { + try { + HttpServletResponse res = req.getNativeResponse(HttpServletResponse.class); + if (res != null) { + res.setCharacterEncoding("UTF-8"); + res.addHeader("Content-Type", contentType); + res.getWriter().print(example); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/api/CoverageApi.java b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/api/CoverageApi.java new file mode 100644 index 000000000000..342e4da4992b --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/api/CoverageApi.java @@ -0,0 +1,366 @@ +/* + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech) (7.26.0-SNAPSHOT). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +package org.openapitools.api; + +import org.openapitools.model.FormParamsRequest; +import org.openapitools.model.MultipartMixedRequestMarker; +import org.openapitools.model.MultipartMixedStatus; +import org.springframework.lang.Nullable; +import io.swagger.v3.oas.annotations.ExternalDocumentation; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.multipart.MultipartFile; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.*; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import jakarta.annotation.Generated; + +@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", comments = "Generator version: 7.26.0-SNAPSHOT") +@Validated +@Tag(name = "coverage", description = "the coverage API") +public interface CoverageApi { + + default Optional getRequest() { + return Optional.empty(); + } + + String PATH_BINARY_BODY = "/coverage/binary"; + /** + * POST /coverage/binary + * + * @param body (required) + * @return No content (status code 204) + */ + @Operation( + operationId = "binaryBody", + tags = { "coverage" }, + responses = { + @ApiResponse(responseCode = "204", description = "No content") + } + ) + @RequestMapping( + method = RequestMethod.POST, + value = CoverageApi.PATH_BINARY_BODY, + consumes = { "application/octet-stream" } + ) + default ResponseEntity binaryBody( + @Parameter(name = "body", description = "", required = true) @Valid @RequestBody org.springframework.core.io.Resource body + ) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + + String PATH_COOKIE_PARAMS = "/coverage/cookie"; + /** + * GET /coverage/cookie + * + * @param plain (optional) + * @param bytes (optional) (base64 encoded) + * @return No content (status code 204) + */ + @Operation( + operationId = "cookieParams", + tags = { "coverage" }, + responses = { + @ApiResponse(responseCode = "204", description = "No content") + } + ) + @RequestMapping( + method = RequestMethod.GET, + value = CoverageApi.PATH_COOKIE_PARAMS + ) + default ResponseEntity cookieParams( + @Parameter(name = "plain", description = "", in = ParameterIn.COOKIE) @CookieValue(name = "plain", required = false) @Nullable String plain, + @Parameter(name = "bytes", description = "", in = ParameterIn.COOKIE) @CookieValue(name = "bytes", required = false) @Nullable String /* base64 encoded binary */ bytes + ) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + + String PATH_FORM_PARAMS = "/coverage/form"; + /** + * POST /coverage/form + * + * @param plain (optional) + * @param bytes (optional) (base64 encoded) + * @return No content (status code 204) + */ + @Operation( + operationId = "formParams", + tags = { "coverage" }, + responses = { + @ApiResponse(responseCode = "204", description = "No content") + } + ) + @RequestMapping( + method = RequestMethod.POST, + value = CoverageApi.PATH_FORM_PARAMS, + consumes = { "application/x-www-form-urlencoded" } + ) + default ResponseEntity formParams( + @Parameter(name = "plain", description = "") @Valid @RequestParam(value = "plain", required = false) String plain, + @Parameter(name = "bytes", description = "") @Valid @RequestParam(value = "bytes", required = false) String bytes /* base64 encoded binary */ + ) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + + String PATH_HEADER_PARAMS = "/coverage/header"; + /** + * GET /coverage/header + * + * @param xPlain (optional) + * @param xByte (optional) (base64 encoded) + * @return No content (status code 204) + */ + @Operation( + operationId = "headerParams", + tags = { "coverage" }, + responses = { + @ApiResponse(responseCode = "204", description = "No content") + } + ) + @RequestMapping( + method = RequestMethod.GET, + value = CoverageApi.PATH_HEADER_PARAMS + ) + default ResponseEntity headerParams( + @Parameter(name = "X-Plain", description = "", in = ParameterIn.HEADER) @RequestHeader(value = "X-Plain", required = false) @Nullable String xPlain, + @Parameter(name = "X-Byte", description = "", in = ParameterIn.HEADER) @RequestHeader(value = "X-Byte", required = false) @Nullable String /* base64 encoded binary */ xByte + ) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + + String PATH_JSON_BODY = "/coverage/json"; + /** + * POST /coverage/json + * + * @param formParamsRequest (required) + * @return No content (status code 204) + */ + @Operation( + operationId = "jsonBody", + tags = { "coverage" }, + responses = { + @ApiResponse(responseCode = "204", description = "No content") + } + ) + @RequestMapping( + method = RequestMethod.POST, + value = CoverageApi.PATH_JSON_BODY, + consumes = { "application/json" } + ) + default ResponseEntity jsonBody( + @Parameter(name = "FormParamsRequest", description = "", required = true) @Valid @RequestBody FormParamsRequest formParamsRequest + ) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + + String PATH_MULTIPART_FILE_ARRAY = "/coverage/multipart/files"; + /** + * POST /coverage/multipart/files + * + * @param files (optional) + * @return No content (status code 204) + */ + @Operation( + operationId = "multipartFileArray", + tags = { "coverage" }, + responses = { + @ApiResponse(responseCode = "204", description = "No content") + } + ) + @RequestMapping( + method = RequestMethod.POST, + value = CoverageApi.PATH_MULTIPART_FILE_ARRAY, + consumes = { "multipart/form-data" } + ) + default ResponseEntity multipartFileArray( + @Parameter(name = "files", description = "") @RequestPart(value = "files", required = false) List files + ) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + + String PATH_MULTIPART_MIXED = "/coverage/multipart/mixed"; + /** + * POST /coverage/multipart/mixed + * + * @param status (required) + * @param file (required) + * @param statusArray (optional) + * @param marker (optional) + * @param markerArray (optional) + * @return No content (status code 204) + */ + @Operation( + operationId = "multipartMixed", + tags = { "coverage" }, + responses = { + @ApiResponse(responseCode = "204", description = "No content") + } + ) + @RequestMapping( + method = RequestMethod.POST, + value = CoverageApi.PATH_MULTIPART_MIXED, + consumes = { "multipart/form-data" } + ) + default ResponseEntity multipartMixed( + @Parameter(name = "status", description = "", required = true) @Valid @RequestParam(value = "status", required = true) MultipartMixedStatus status, + @Parameter(name = "file", description = "", required = true) @RequestPart(value = "file", required = true) MultipartFile file, + @Parameter(name = "statusArray", description = "") @RequestParam(value = "statusArray", required = false) List statusArray, + @Parameter(name = "marker", description = "") @Valid @RequestPart(value = "marker", required = false) MultipartMixedRequestMarker marker, + @Parameter(name = "markerArray", description = "") @RequestPart(value = "markerArray", required = false) List<@Valid MultipartMixedRequestMarker> markerArray + ) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + + String PATH_MULTIPART_SIMPLE = "/coverage/multipart/simple"; + /** + * POST /coverage/multipart/simple + * + * @param plain (optional) + * @param bytes (optional) (base64 encoded) + * @param file (optional) + * @return No content (status code 204) + */ + @Operation( + operationId = "multipartSimple", + tags = { "coverage" }, + responses = { + @ApiResponse(responseCode = "204", description = "No content") + } + ) + @RequestMapping( + method = RequestMethod.POST, + value = CoverageApi.PATH_MULTIPART_SIMPLE, + consumes = { "multipart/form-data" } + ) + default ResponseEntity multipartSimple( + @Parameter(name = "plain", description = "") @Valid @RequestParam(value = "plain", required = false) String plain, + @Parameter(name = "bytes", description = "") @Valid @RequestParam(value = "bytes", required = false) String bytes /* base64 encoded binary */, + @Parameter(name = "file", description = "") @RequestPart(value = "file", required = false) MultipartFile file + ) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + + String PATH_MULTIPART_SIMPLE_VALIDATED = "/coverage/multipart/simple-validated"; + /** + * POST /coverage/multipart/simple-validated + * + * @param plain (optional) + * @param bytes (optional) (base64 encoded) + * @param file (optional) + * @return No content (status code 204) + */ + @Operation( + operationId = "multipartSimpleValidated", + tags = { "coverage" }, + responses = { + @ApiResponse(responseCode = "204", description = "No content") + } + ) + @RequestMapping( + method = RequestMethod.POST, + value = CoverageApi.PATH_MULTIPART_SIMPLE_VALIDATED, + consumes = { "multipart/form-data" } + ) + default ResponseEntity multipartSimpleValidated( + @Parameter(name = "plain", description = "") @Valid @RequestParam(value = "plain", required = false) String plain, + @Parameter(name = "bytes", description = "") @Valid @RequestParam(value = "bytes", required = false) String bytes /* base64 encoded binary */, + @Parameter(name = "file", description = "") @RequestPart(value = "file", required = false) MultipartFile file + ) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + + String PATH_PATH_PARAMS = "/coverage/path/{plain}/{bytes}"; + /** + * GET /coverage/path/{plain}/{bytes} + * + * @param plain (required) + * @param bytes Base64-encoded value embedded in the URL path. Standard Base64 (RFC 4648 §4) can produce a `/` character, which is not safe to use unescaped inside a path segment: most servers (including Spring's default Tomcat/Jetty configuration) reject or misroute requests containing an encoded slash (`%2F`) unless the server is explicitly configured to allow it. Clients must percent-encode the value (and servers may need to enable encoded-slash handling) before using a base64 value as a path parameter. Prefer Base64URL (RFC 4648 §5, using `-`/`_` instead of `+`/`/`) or a query/body parameter to avoid this caveat entirely. (required) (base64 encoded) + * @return No content (status code 204) + */ + @Operation( + operationId = "pathParams", + tags = { "coverage" }, + responses = { + @ApiResponse(responseCode = "204", description = "No content") + } + ) + @RequestMapping( + method = RequestMethod.GET, + value = CoverageApi.PATH_PATH_PARAMS + ) + default ResponseEntity pathParams( + @Parameter(name = "plain", description = "", required = true, in = ParameterIn.PATH) @PathVariable("plain") String plain, + @Parameter(name = "bytes", description = "Base64-encoded value embedded in the URL path. Standard Base64 (RFC 4648 §4) can produce a `/` character, which is not safe to use unescaped inside a path segment: most servers (including Spring's default Tomcat/Jetty configuration) reject or misroute requests containing an encoded slash (`%2F`) unless the server is explicitly configured to allow it. Clients must percent-encode the value (and servers may need to enable encoded-slash handling) before using a base64 value as a path parameter. Prefer Base64URL (RFC 4648 §5, using `-`/`_` instead of `+`/`/`) or a query/body parameter to avoid this caveat entirely.", required = true, in = ParameterIn.PATH) @PathVariable("bytes") String /* base64 encoded binary */ bytes + ) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + + + String PATH_QUERY_PARAMS = "/coverage/query"; + /** + * GET /coverage/query + * + * @param plain (optional) + * @param bytes (optional) (base64 encoded) + * @return No content (status code 204) + */ + @Operation( + operationId = "queryParams", + tags = { "coverage" }, + responses = { + @ApiResponse(responseCode = "204", description = "No content") + } + ) + @RequestMapping( + method = RequestMethod.GET, + value = CoverageApi.PATH_QUERY_PARAMS + ) + default ResponseEntity queryParams( + @Parameter(name = "plain", description = "", in = ParameterIn.QUERY) @Valid @RequestParam(value = "plain", required = false) @Nullable String plain, + @Parameter(name = "bytes", description = "", in = ParameterIn.QUERY) @Valid @RequestParam(value = "bytes", required = false) @Nullable String /* base64 encoded binary */ bytes + ) { + return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); + + } + +} diff --git a/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/api/CoverageApiTestControllerImpl.java b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/api/CoverageApiTestControllerImpl.java new file mode 100644 index 000000000000..5ff04b6f516a --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/api/CoverageApiTestControllerImpl.java @@ -0,0 +1,248 @@ +// manually created counterpart to unit tests. Do not delete! +package org.openapitools.api; + +import org.openapitools.model.FormParamsRequest; +import org.openapitools.model.MultipartMixedRequestMarker; +import org.openapitools.model.MultipartMixedStatus; +import org.springframework.core.io.Resource; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.multipart.MultipartFile; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; + +@Controller +@RequestMapping("${openapi.multipartByteEdgeCaseCoverage.base-path:}") +public class CoverageApiTestControllerImpl implements CoverageApi { + + // Expected content for binary data verification - matches test constants + private static final byte[] EXPECTED_BYTES = "hello".getBytes(StandardCharsets.UTF_8); + private static final String EXPECTED_BYTES_STRING = "hello"; + + private void verifyBytesContent(byte[] actual, String fieldName) { + if (!Arrays.equals(EXPECTED_BYTES, actual)) { + String actualString = new String(actual, StandardCharsets.UTF_8); + throw new IllegalArgumentException( + fieldName + " content mismatch: expected '" + EXPECTED_BYTES_STRING + "', got '" + actualString + "'"); + } + } + + private void verifyBase64Content(String base64Value, String fieldName) { + byte[] decoded = Base64.getDecoder().decode(base64Value); + verifyBytesContent(decoded, fieldName); + } + + @Override + public ResponseEntity binaryBody(Resource body) { + if (body == null) { + throw new IllegalArgumentException("body is required"); + } + try (InputStream inputStream = body.getInputStream()) { + byte[] content = readAllBytes(inputStream); + if (content.length == 0) { + throw new IllegalArgumentException("body content is empty"); + } + verifyBytesContent(content, "body"); + } catch (IOException e) { + throw new RuntimeException("Failed to read binary body", e); + } + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + private byte[] readAllBytes(InputStream inputStream) throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + int nRead; + byte[] data = new byte[1024]; + while ((nRead = inputStream.read(data, 0, data.length)) != -1) { + buffer.write(data, 0, nRead); + } + buffer.flush(); + return buffer.toByteArray(); + } + + @Override + public ResponseEntity cookieParams(String plain, String bytes) { + if (bytes != null) { + verifyBase64Content(bytes, "bytes"); + } + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Override + public ResponseEntity formParams(String plain, String bytes) { + if (bytes != null) { + verifyBase64Content(bytes, "bytes"); + } + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Override + public ResponseEntity headerParams(String xPlain, String xByte) { + if (xByte != null) { + verifyBase64Content(xByte, "X-Byte"); + } + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Override + public ResponseEntity jsonBody(FormParamsRequest formParamsRequest) { + if (formParamsRequest == null) { + throw new IllegalArgumentException("formParamsRequest is required"); + } + byte[] bytes = formParamsRequest.getBytes(); + if (bytes != null) { + verifyBytesContent(bytes, "bytes"); + } + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Override + public ResponseEntity multipartFileArray(List files) { + // Expected content for each file in the array - matches test constants + String[] expectedContents = {"content1", "content2", "content3"}; + + if (files != null) { + for (int i = 0; i < files.size(); i++) { + MultipartFile file = files.get(i); + try { + byte[] content = file.getBytes(); + if (content.length == 0) { + throw new IllegalArgumentException("files[" + i + "] content is empty"); + } + // Verify content matches expected value for this index + if (i < expectedContents.length) { + byte[] expected = expectedContents[i].getBytes(StandardCharsets.UTF_8); + if (!Arrays.equals(expected, content)) { + String actualString = new String(content, StandardCharsets.UTF_8); + throw new IllegalArgumentException( + "files[" + i + "] content mismatch: expected '" + expectedContents[i] + "', got '" + actualString + "'"); + } + } + } catch (IOException e) { + throw new RuntimeException("Failed to read file", e); + } + } + } + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Override + public ResponseEntity multipartMixed( + MultipartMixedStatus status, + MultipartFile file, + List statusArray, + MultipartMixedRequestMarker marker, + List markerArray + ) { + if (status == null) { + throw new IllegalArgumentException("status is required"); + } + if (file == null) { + throw new IllegalArgumentException("file is required"); + } + + // Verify enum value is valid + String reconstructedStatus = status.getValue(); + if (reconstructedStatus == null || reconstructedStatus.isEmpty()) { + throw new IllegalArgumentException("status value is invalid"); + } + + // Verify file content matches expected bytes + try { + byte[] fileContent = file.getBytes(); + verifyBytesContent(fileContent, "file"); + } catch (IOException e) { + throw new RuntimeException("Failed to read file", e); + } + + // Verify enum array values + if (statusArray != null) { + for (int i = 0; i < statusArray.size(); i++) { + MultipartMixedStatus s = statusArray.get(i); + String value = s.getValue(); + if (value == null) { + throw new IllegalArgumentException("statusArray[" + i + "] contains invalid enum"); + } + } + } + + // Verify POJO fields + if (marker != null) { + String name = marker.getName(); + if (name == null) { + throw new IllegalArgumentException("marker.name is required"); + } + } + + // Verify POJO array fields + if (markerArray != null) { + for (int i = 0; i < markerArray.size(); i++) { + MultipartMixedRequestMarker m = markerArray.get(i); + String name = m.getName(); + if (name == null) { + throw new IllegalArgumentException("markerArray[" + i + "].name is required"); + } + } + } + + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Override + public ResponseEntity multipartSimple(String plain, String bytes, MultipartFile file) { + // This endpoint does NOT validate file content - allows empty files + if (bytes != null) { + verifyBase64Content(bytes, "bytes"); + } + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Override + public ResponseEntity multipartSimpleValidated(String plain, String bytes, MultipartFile file) { + // This endpoint validates file content + if (bytes != null) { + verifyBase64Content(bytes, "bytes"); + } + if (file != null) { + try { + byte[] content = file.getBytes(); + if (content.length == 0) { + throw new IllegalArgumentException("file content is empty"); + } + verifyBytesContent(content, "file"); + } catch (IOException e) { + throw new RuntimeException("Failed to read file", e); + } + } + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Override + public ResponseEntity pathParams(String plain, String bytes) { + if (plain == null) { + throw new IllegalArgumentException("plain is required"); + } + if (bytes == null) { + throw new IllegalArgumentException("bytes is required"); + } + verifyBase64Content(bytes, "bytes"); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Override + public ResponseEntity queryParams(String plain, String bytes) { + if (bytes != null) { + verifyBase64Content(bytes, "bytes"); + } + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } +} + diff --git a/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/configuration/EnumConverterConfiguration.java b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/configuration/EnumConverterConfiguration.java new file mode 100644 index 000000000000..ccbb806c1b52 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/configuration/EnumConverterConfiguration.java @@ -0,0 +1,36 @@ +package org.openapitools.configuration; + +import java.math.BigDecimal; +import java.net.URI; +import java.util.UUID; + +import org.openapitools.model.MultipartMixedStatus; + +import jakarta.annotation.Generated; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.convert.converter.Converter; + +/** + * This class provides Spring Converter beans for the enum models in the OpenAPI specification. + * + * By default, Spring only converts primitive types to enums using Enum::valueOf, which can prevent + * correct conversion if the OpenAPI specification is using an `enumPropertyNaming` other than + * `original` or the specification has an integer enum. + */ +@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", comments = "Generator version: 7.26.0-SNAPSHOT") +@Configuration(value = "org.openapitools.configuration.enumConverterConfiguration") +public class EnumConverterConfiguration { + + @Bean(name = "org.openapitools.configuration.EnumConverterConfiguration.multipartMixedStatusConverter") + Converter multipartMixedStatusConverter() { + return new Converter() { + @Override + public MultipartMixedStatus convert(String source) { + return MultipartMixedStatus.fromValue(source); + } + }; + } + +} diff --git a/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/configuration/HomeController.java b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/configuration/HomeController.java new file mode 100644 index 000000000000..9aa29284ab5f --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/configuration/HomeController.java @@ -0,0 +1,20 @@ +package org.openapitools.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.GetMapping; + +/** + * Home redirection to OpenAPI api documentation + */ +@Controller +public class HomeController { + + @RequestMapping("/") + public String index() { + return "redirect:swagger-ui.html"; + } + +} \ No newline at end of file diff --git a/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/configuration/SpringDocConfiguration.java b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/configuration/SpringDocConfiguration.java new file mode 100644 index 000000000000..3086d6c2322a --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/configuration/SpringDocConfiguration.java @@ -0,0 +1,27 @@ +package org.openapitools.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.info.Contact; +import io.swagger.v3.oas.models.info.License; +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.security.SecurityScheme; + +@Configuration +public class SpringDocConfiguration { + + @Bean(name = "org.openapitools.configuration.SpringDocConfiguration.apiInfo") + OpenAPI apiInfo() { + return new OpenAPI() + .info( + new Info() + .title("Multipart & Byte Edge Case Coverage") + .description("No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)") + .version("1.0.0") + ) + ; + } +} \ No newline at end of file diff --git a/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/model/FormParamsRequest.java b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/model/FormParamsRequest.java new file mode 100644 index 000000000000..397043b7c203 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/model/FormParamsRequest.java @@ -0,0 +1,110 @@ +package org.openapitools.model; + +import java.net.URI; +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import java.util.Arrays; +import org.springframework.lang.Nullable; +import org.openapitools.jackson.nullable.JsonNullable; +import java.time.OffsetDateTime; +import jakarta.validation.Valid; +import jakarta.validation.constraints.*; +import io.swagger.v3.oas.annotations.media.Schema; + + +import java.util.*; +import jakarta.annotation.Generated; + +/** + * FormParamsRequest + */ + +@JsonTypeName("formParams_request") +@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", comments = "Generator version: 7.26.0-SNAPSHOT") +public class FormParamsRequest { + + private @Nullable String plain; + + private @Nullable byte[] bytes; + + public FormParamsRequest plain(@Nullable String plain) { + this.plain = plain; + return this; + } + + /** + * Get plain + * @return plain + */ + + @Schema(name = "plain", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("plain") + public @Nullable String getPlain() { + return plain; + } + + @JsonProperty("plain") + public void setPlain(@Nullable String plain) { + this.plain = plain; + } + + public FormParamsRequest bytes(@Nullable byte[] bytes) { + this.bytes = bytes; + return this; + } + + /** + * Get bytes + * @return bytes + */ + + @Schema(name = "bytes", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("bytes") + public @Nullable byte[] getBytes() { + return bytes; + } + + @JsonProperty("bytes") + public void setBytes(@Nullable byte[] bytes) { + this.bytes = bytes; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + FormParamsRequest formParamsRequest = (FormParamsRequest) o; + return Objects.equals(this.plain, formParamsRequest.plain) && + Arrays.equals(this.bytes, formParamsRequest.bytes); + } + + @Override + public int hashCode() { + return Objects.hash(plain, Arrays.hashCode(bytes)); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class FormParamsRequest {\n"); + sb.append(" plain: ").append(toIndentedString(plain)).append("\n"); + sb.append(" bytes: ").append(toIndentedString(bytes)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(@Nullable Object o) { + return o == null ? "null" : o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/model/MultipartMixedRequestMarker.java b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/model/MultipartMixedRequestMarker.java new file mode 100644 index 000000000000..034d4d610e10 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/model/MultipartMixedRequestMarker.java @@ -0,0 +1,143 @@ +package org.openapitools.model; + +import java.net.URI; +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import org.springframework.lang.Nullable; +import org.openapitools.jackson.nullable.JsonNullable; +import java.time.OffsetDateTime; +import jakarta.validation.Valid; +import jakarta.validation.constraints.*; +import io.swagger.v3.oas.annotations.media.Schema; + + +import java.util.*; +import jakarta.annotation.Generated; + +/** + * MultipartMixedRequestMarker + */ + +@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", comments = "Generator version: 7.26.0-SNAPSHOT") +public class MultipartMixedRequestMarker { + + private String name; + + private @Nullable Integer priority; + + private @Nullable Boolean active; + + public MultipartMixedRequestMarker() { + super(); + } + + /** + * Constructor with only required parameters + */ + public MultipartMixedRequestMarker(String name) { + this.name = name; + } + + public MultipartMixedRequestMarker name(String name) { + this.name = name; + return this; + } + + /** + * Get name + * @return name + */ + @NotNull + @Schema(name = "name", requiredMode = Schema.RequiredMode.REQUIRED) + @JsonProperty("name") + public String getName() { + return name; + } + + @JsonProperty("name") + public void setName(String name) { + this.name = name; + } + + public MultipartMixedRequestMarker priority(@Nullable Integer priority) { + this.priority = priority; + return this; + } + + /** + * Get priority + * @return priority + */ + + @Schema(name = "priority", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("priority") + public @Nullable Integer getPriority() { + return priority; + } + + @JsonProperty("priority") + public void setPriority(@Nullable Integer priority) { + this.priority = priority; + } + + public MultipartMixedRequestMarker active(@Nullable Boolean active) { + this.active = active; + return this; + } + + /** + * Get active + * @return active + */ + + @Schema(name = "active", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @JsonProperty("active") + public @Nullable Boolean getActive() { + return active; + } + + @JsonProperty("active") + public void setActive(@Nullable Boolean active) { + this.active = active; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + MultipartMixedRequestMarker multipartMixedRequestMarker = (MultipartMixedRequestMarker) o; + return Objects.equals(this.name, multipartMixedRequestMarker.name) && + Objects.equals(this.priority, multipartMixedRequestMarker.priority) && + Objects.equals(this.active, multipartMixedRequestMarker.active); + } + + @Override + public int hashCode() { + return Objects.hash(name, priority, active); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class MultipartMixedRequestMarker {\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append(" priority: ").append(toIndentedString(priority)).append("\n"); + sb.append(" active: ").append(toIndentedString(active)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(@Nullable Object o) { + return o == null ? "null" : o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/model/MultipartMixedStatus.java b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/model/MultipartMixedStatus.java new file mode 100644 index 000000000000..987fbd5253d4 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/java/org/openapitools/model/MultipartMixedStatus.java @@ -0,0 +1,58 @@ +package org.openapitools.model; + +import java.net.URI; +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonValue; +import org.openapitools.jackson.nullable.JsonNullable; +import java.time.OffsetDateTime; +import jakarta.validation.Valid; +import jakarta.validation.constraints.*; +import io.swagger.v3.oas.annotations.media.Schema; + + +import java.util.*; +import jakarta.annotation.Generated; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Gets or Sets MultipartMixedStatus + */ + +@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", comments = "Generator version: 7.26.0-SNAPSHOT") +public enum MultipartMixedStatus { + + ALLOWED("ALLOWED"), + + IN_PROGRESS("IN_PROGRESS"), + + REJECTED("REJECTED"); + + private final String value; + + MultipartMixedStatus(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static MultipartMixedStatus fromValue(String value) { + for (MultipartMixedStatus b : MultipartMixedStatus.values()) { + if (b.value.equals(value)) { + return b; + } + } + throw new IllegalArgumentException("Unexpected value '" + value + "'"); + } +} + diff --git a/samples/server/petstore/springboot-byte-format-edge-cases/src/main/resources/application.properties b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/resources/application.properties new file mode 100644 index 000000000000..7e90813e59b2 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/resources/application.properties @@ -0,0 +1,3 @@ +server.port=8080 +spring.jackson.date-format=org.openapitools.RFC3339DateFormat +spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false diff --git a/samples/server/petstore/springboot-byte-format-edge-cases/src/main/resources/openapi.yaml b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/resources/openapi.yaml new file mode 100644 index 000000000000..0fdcb1301243 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases/src/main/resources/openapi.yaml @@ -0,0 +1,321 @@ +openapi: 3.0.3 +info: + title: Multipart & Byte Edge Case Coverage + version: 1.0.0 +servers: +- url: / +tags: +- name: coverage +paths: + /coverage/query: + get: + operationId: queryParams + parameters: + - explode: true + in: query + name: plain + required: false + schema: + type: string + style: form + - explode: true + in: query + name: bytes + required: false + schema: + format: byte + type: string + style: form + responses: + "204": + description: No content + tags: + - coverage + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/path/{plain}/{bytes}: + get: + operationId: pathParams + parameters: + - explode: false + in: path + name: plain + required: true + schema: + type: string + style: simple + - explode: false + in: path + name: bytes + required: true + schema: + format: byte + type: string + style: simple + responses: + "204": + description: No content + tags: + - coverage + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/header: + get: + operationId: headerParams + parameters: + - explode: false + in: header + name: X-Plain + required: false + schema: + type: string + style: simple + - explode: false + in: header + name: X-Byte + required: false + schema: + format: byte + type: string + style: simple + responses: + "204": + description: No content + tags: + - coverage + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/cookie: + get: + operationId: cookieParams + parameters: + - explode: true + in: cookie + name: plain + required: false + schema: + type: string + style: form + - explode: true + in: cookie + name: bytes + required: false + schema: + format: byte + type: string + style: form + responses: + "204": + description: No content + tags: + - coverage + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/form: + post: + operationId: formParams + requestBody: + content: + application/x-www-form-urlencoded: + schema: + $ref: "#/components/schemas/formParams_request" + required: true + responses: + "204": + description: No content + tags: + - coverage + x-content-type: application/x-www-form-urlencoded + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/multipart/simple: + post: + operationId: multipartSimple + requestBody: + content: + multipart/form-data: + schema: + $ref: "#/components/schemas/multipartSimple_request" + required: true + responses: + "204": + description: No content + tags: + - coverage + x-content-type: multipart/form-data + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/multipart/simple-validated: + post: + operationId: multipartSimpleValidated + requestBody: + content: + multipart/form-data: + schema: + $ref: "#/components/schemas/multipartSimple_request" + required: true + responses: + "204": + description: No content + tags: + - coverage + x-content-type: multipart/form-data + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/multipart/files: + post: + operationId: multipartFileArray + requestBody: + content: + multipart/form-data: + schema: + $ref: "#/components/schemas/multipartFileArray_request" + responses: + "204": + description: No content + tags: + - coverage + x-content-type: multipart/form-data + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/multipart/mixed: + post: + operationId: multipartMixed + requestBody: + content: + multipart/form-data: + schema: + $ref: "#/components/schemas/multipartMixed_request" + responses: + "204": + description: No content + tags: + - coverage + x-content-type: multipart/form-data + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/json: + post: + operationId: jsonBody + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/formParams_request" + required: true + responses: + "204": + description: No content + tags: + - coverage + x-content-type: application/json + x-accepts: + - application/json + x-tags: + - tag: coverage + /coverage/binary: + post: + operationId: binaryBody + requestBody: + content: + application/octet-stream: + schema: + format: binary + type: string + required: true + responses: + "204": + description: No content + tags: + - coverage + x-content-type: application/octet-stream + x-accepts: + - application/json + x-tags: + - tag: coverage +components: + schemas: + MultipartMixedStatus: + enum: + - ALLOWED + - IN_PROGRESS + - REJECTED + type: string + MultipartMixedRequestMarker: + properties: + name: + type: string + priority: + format: int32 + type: integer + active: + type: boolean + required: + - name + type: object + formParams_request: + properties: + plain: + type: string + bytes: + format: byte + type: string + type: object + multipartSimple_request: + properties: + plain: + type: string + bytes: + format: byte + type: string + file: + format: binary + type: string + type: object + multipartFileArray_request: + properties: + files: + items: + format: binary + type: string + type: array + type: object + multipartMixed_request: + properties: + status: + $ref: "#/components/schemas/MultipartMixedStatus" + statusArray: + items: + $ref: "#/components/schemas/MultipartMixedStatus" + type: array + marker: + $ref: "#/components/schemas/MultipartMixedRequestMarker" + markerArray: + items: + $ref: "#/components/schemas/MultipartMixedRequestMarker" + type: array + file: + format: binary + type: string + required: + - file + - status + type: object diff --git a/samples/server/petstore/springboot-byte-format-edge-cases/src/test/java/org/openapitools/OpenApiGeneratorApplicationTests.java b/samples/server/petstore/springboot-byte-format-edge-cases/src/test/java/org/openapitools/OpenApiGeneratorApplicationTests.java new file mode 100644 index 000000000000..3681f67e7705 --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases/src/test/java/org/openapitools/OpenApiGeneratorApplicationTests.java @@ -0,0 +1,13 @@ +package org.openapitools; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class OpenApiGeneratorApplicationTests { + + @Test + void contextLoads() { + } + +} \ No newline at end of file diff --git a/samples/server/petstore/springboot-byte-format-edge-cases/src/test/java/org/openapitools/api/CoverageApiIntegrationTest.java b/samples/server/petstore/springboot-byte-format-edge-cases/src/test/java/org/openapitools/api/CoverageApiIntegrationTest.java new file mode 100644 index 000000000000..055beca10efa --- /dev/null +++ b/samples/server/petstore/springboot-byte-format-edge-cases/src/test/java/org/openapitools/api/CoverageApiIntegrationTest.java @@ -0,0 +1,275 @@ +// manually created counterpart to unit tests. Do not delete! +package org.openapitools.api; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; +import org.openapitools.model.MultipartMixedRequestMarker; +import org.openapitools.model.MultipartMixedStatus; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.web.servlet.MockMvc; + +import jakarta.servlet.http.Cookie; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +@SpringBootTest +@AutoConfigureMockMvc +class CoverageApiIntegrationTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + private static final byte[] SAMPLE_BYTES = "hello".getBytes(StandardCharsets.UTF_8); + private static final String SAMPLE_BYTES_BASE64 = Base64.getEncoder().encodeToString(SAMPLE_BYTES); + + // ==================== multipartMixed tests ==================== + // Covers: enum @RequestParam, file @RequestPart, enum array @RequestParam, + // object @RequestPart, object array @RequestPart + + @Test + void multipartMixed_withRequiredFieldsOnly_returns204() throws Exception { + MockMultipartFile file = new MockMultipartFile( + "file", "test.bin", MediaType.APPLICATION_OCTET_STREAM_VALUE, SAMPLE_BYTES); + + mockMvc.perform(multipart(CoverageApi.PATH_MULTIPART_MIXED) + .file(file) + .param("status", MultipartMixedStatus.ALLOWED.getValue())) + .andExpect(status().isNoContent()); + } + + @Test + void multipartMixed_withAllFields_returns204() throws Exception { + MockMultipartFile file = new MockMultipartFile( + "file", "test.bin", MediaType.APPLICATION_OCTET_STREAM_VALUE, SAMPLE_BYTES); + + MultipartMixedRequestMarker marker = new MultipartMixedRequestMarker("marker1") + .priority(10) + .active(true); + + List markerArray = Arrays.asList( + new MultipartMixedRequestMarker("marker2").priority(20).active(false), + new MultipartMixedRequestMarker("marker3").priority(30).active(true) + ); + + // marker as JSON part + MockMultipartFile markerPart = new MockMultipartFile( + "marker", "", MediaType.APPLICATION_JSON_VALUE, + objectMapper.writeValueAsBytes(marker)); + + // markerArray as JSON part + MockMultipartFile markerArrayPart = new MockMultipartFile( + "markerArray", "", MediaType.APPLICATION_JSON_VALUE, + objectMapper.writeValueAsBytes(markerArray)); + + mockMvc.perform(multipart(CoverageApi.PATH_MULTIPART_MIXED) + .file(file) + .file(markerPart) + .file(markerArrayPart) + .param("status", MultipartMixedStatus.IN_PROGRESS.getValue()) + .param("statusArray", MultipartMixedStatus.ALLOWED.getValue(), + MultipartMixedStatus.REJECTED.getValue())) + .andExpect(status().isNoContent()); + } + + @Test + void multipartMixed_enumValue_deserializesCorrectly() throws Exception { + MockMultipartFile file = new MockMultipartFile( + "file", "test.bin", MediaType.APPLICATION_OCTET_STREAM_VALUE, SAMPLE_BYTES); + + // Test each enum value + for (MultipartMixedStatus status : MultipartMixedStatus.values()) { + mockMvc.perform(multipart(CoverageApi.PATH_MULTIPART_MIXED) + .file(file) + .param("status", status.getValue())) + .andExpect(status().isNoContent()); + } + } + + // ==================== multipartSimple tests ==================== + // Covers: scalar @RequestParam, base64 bytes @RequestParam, file @RequestPart + + @Test + void multipartSimple_withAllFields_returns204() throws Exception { + MockMultipartFile file = new MockMultipartFile( + "file", "test.txt", MediaType.TEXT_PLAIN_VALUE, SAMPLE_BYTES); + + mockMvc.perform(multipart(CoverageApi.PATH_MULTIPART_SIMPLE) + .file(file) + .param("plain", "plainText") + .param("bytes", SAMPLE_BYTES_BASE64)) + .andExpect(status().isNoContent()); + } + + @Test + void multipartSimple_withEmptyFilePart_returns204() throws Exception { + MockMultipartFile emptyFile = + new MockMultipartFile("file", "", MediaType.APPLICATION_OCTET_STREAM_VALUE, new byte[0]); + + mockMvc.perform(multipart(CoverageApi.PATH_MULTIPART_SIMPLE) + .file(emptyFile)) + .andExpect(status().isNoContent()); + } + + // ==================== multipartSimpleValidated tests ==================== + // Covers: validated file content deserialization + + @Test + void multipartSimpleValidated_withValidContent_returns204() throws Exception { + MockMultipartFile file = new MockMultipartFile( + "file", "test.txt", MediaType.TEXT_PLAIN_VALUE, SAMPLE_BYTES); + + mockMvc.perform(multipart(CoverageApi.PATH_MULTIPART_SIMPLE_VALIDATED) + .file(file) + .param("plain", "plainText") + .param("bytes", SAMPLE_BYTES_BASE64)) + .andExpect(status().isNoContent()); + } + + // ==================== multipartFileArray tests ==================== + // Covers: array of files @RequestPart List + + @Test + void multipartFileArray_withMultipleFiles_returns204() throws Exception { + MockMultipartFile file1 = new MockMultipartFile( + "files", "file1.bin", MediaType.APPLICATION_OCTET_STREAM_VALUE, "content1".getBytes()); + MockMultipartFile file2 = new MockMultipartFile( + "files", "file2.bin", MediaType.APPLICATION_OCTET_STREAM_VALUE, "content2".getBytes()); + MockMultipartFile file3 = new MockMultipartFile( + "files", "file3.bin", MediaType.APPLICATION_OCTET_STREAM_VALUE, "content3".getBytes()); + + mockMvc.perform(multipart(CoverageApi.PATH_MULTIPART_FILE_ARRAY) + .file(file1) + .file(file2) + .file(file3)) + .andExpect(status().isNoContent()); + } + + @Test + void multipartFileArray_withNoFiles_returns204() throws Exception { + mockMvc.perform(multipart(CoverageApi.PATH_MULTIPART_FILE_ARRAY)) + .andExpect(status().isNoContent()); + } + + // ==================== formParams tests ==================== + // Covers: application/x-www-form-urlencoded with @RequestParam + + @Test + void formParams_withAllFields_returns204() throws Exception { + mockMvc.perform(post(CoverageApi.PATH_FORM_PARAMS) + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .param("plain", "plainValue") + .param("bytes", SAMPLE_BYTES_BASE64)) + .andExpect(status().isNoContent()); + } + + @Test + void formParams_withNoFields_returns204() throws Exception { + mockMvc.perform(post(CoverageApi.PATH_FORM_PARAMS) + .contentType(MediaType.APPLICATION_FORM_URLENCODED)) + .andExpect(status().isNoContent()); + } + + // ==================== queryParams tests ==================== + // Covers: query string @RequestParam + + @Test + void queryParams_withAllParams_returns204() throws Exception { + mockMvc.perform(get(CoverageApi.PATH_QUERY_PARAMS) + .param("plain", "queryPlain") + .param("bytes", SAMPLE_BYTES_BASE64)) + .andExpect(status().isNoContent()); + } + + @Test + void queryParams_withNoParams_returns204() throws Exception { + mockMvc.perform(get(CoverageApi.PATH_QUERY_PARAMS)) + .andExpect(status().isNoContent()); + } + + // ==================== pathParams tests ==================== + // Covers: @PathVariable + + @Test + void pathParams_withBothParams_returns204() throws Exception { + mockMvc.perform(get("/coverage/path/{plain}/{bytes}", "pathPlain", SAMPLE_BYTES_BASE64)) + .andExpect(status().isNoContent()); + } + + // ==================== headerParams tests ==================== + // Covers: @RequestHeader + + @Test + void headerParams_withAllHeaders_returns204() throws Exception { + mockMvc.perform(get(CoverageApi.PATH_HEADER_PARAMS) + .header("X-Plain", "headerPlain") + .header("X-Byte", SAMPLE_BYTES_BASE64)) + .andExpect(status().isNoContent()); + } + + @Test + void headerParams_withNoHeaders_returns204() throws Exception { + mockMvc.perform(get(CoverageApi.PATH_HEADER_PARAMS)) + .andExpect(status().isNoContent()); + } + + // ==================== cookieParams tests ==================== + // Covers: @CookieValue + + @Test + void cookieParams_withAllCookies_returns204() throws Exception { + mockMvc.perform(get(CoverageApi.PATH_COOKIE_PARAMS) + .cookie(new Cookie("plain", "cookiePlain")) + .cookie(new Cookie("bytes", SAMPLE_BYTES_BASE64))) + .andExpect(status().isNoContent()); + } + + @Test + void cookieParams_withNoCookies_returns204() throws Exception { + mockMvc.perform(get(CoverageApi.PATH_COOKIE_PARAMS)) + .andExpect(status().isNoContent()); + } + + // ==================== jsonBody tests ==================== + // Covers: @RequestBody with JSON POJO + + @Test + void jsonBody_withValidBody_returns204() throws Exception { + String json = "{\"plain\": \"jsonPlain\", \"bytes\": \"" + SAMPLE_BYTES_BASE64 + "\"}"; + + mockMvc.perform(post(CoverageApi.PATH_JSON_BODY) + .contentType(MediaType.APPLICATION_JSON) + .content(json)) + .andExpect(status().isNoContent()); + } + + @Test + void jsonBody_withEmptyObject_returns204() throws Exception { + mockMvc.perform(post(CoverageApi.PATH_JSON_BODY) + .contentType(MediaType.APPLICATION_JSON) + .content("{}")) + .andExpect(status().isNoContent()); + } + + // ==================== binaryBody tests ==================== + // Covers: @RequestBody with application/octet-stream Resource + + @Test + void binaryBody_withBinaryContent_returns204() throws Exception { + mockMvc.perform(post(CoverageApi.PATH_BINARY_BODY) + .contentType(MediaType.APPLICATION_OCTET_STREAM) + .content(SAMPLE_BYTES)) + .andExpect(status().isNoContent()); + } +} + diff --git a/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/FakeApi.java b/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/FakeApi.java index 700e045b496e..95dbb0e0eca3 100644 --- a/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/FakeApi.java @@ -328,7 +328,7 @@ default ResponseEntity testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -364,7 +364,7 @@ default ResponseEntity testEndpointParameters( @Parameter(name = "number", description = "None", required = true) @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, @Parameter(name = "double", description = "None", required = true) @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, @Parameter(name = "pattern_without_delimiter", description = "None", required = true) @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) byte[] _byte, + @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, @Parameter(name = "integer", description = "None") @Min(value = 10) @Max(value = 100) @Valid @RequestParam(value = "integer", required = false) Integer integer, @Parameter(name = "int32", description = "None") @Min(value = 20) @Max(value = 200) @Valid @RequestParam(value = "int32", required = false) Integer int32, @Parameter(name = "int64", description = "None") @Valid @RequestParam(value = "int64", required = false) Long int64, @@ -418,7 +418,7 @@ default ResponseEntity testEnumParameters( @Parameter(name = "enum_query_string", description = "Query parameter enum test (string)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @Parameter(name = "enum_query_integer", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @Parameter(name = "enum_query_double", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, + @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, @Parameter(name = "enum_form_string", description = "Form parameter enum test (string)") @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString ) { return getDelegate().testEnumParameters(enumHeaderStringArray, enumHeaderString, enumQueryStringArray, enumQueryString, enumQueryInteger, enumQueryDouble, enumFormStringArray, enumFormString); diff --git a/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/FakeApiDelegate.java b/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/FakeApiDelegate.java index 5b6cdd7f828f..fc5d2b5a6d98 100644 --- a/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/FakeApiDelegate.java +++ b/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/FakeApiDelegate.java @@ -189,7 +189,7 @@ default ResponseEntity testClientModel(Client client) { * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -207,7 +207,7 @@ default ResponseEntity testClientModel(Client client) { default ResponseEntity testEndpointParameters(BigDecimal number, Double _double, String patternWithoutDelimiter, - byte[] _byte, + String /* base64 encoded binary */ _byte, Integer integer, Integer int32, Long int64, diff --git a/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/FakeApi.java b/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/FakeApi.java index 700e045b496e..95dbb0e0eca3 100644 --- a/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/FakeApi.java @@ -328,7 +328,7 @@ default ResponseEntity testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -364,7 +364,7 @@ default ResponseEntity testEndpointParameters( @Parameter(name = "number", description = "None", required = true) @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, @Parameter(name = "double", description = "None", required = true) @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, @Parameter(name = "pattern_without_delimiter", description = "None", required = true) @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) byte[] _byte, + @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, @Parameter(name = "integer", description = "None") @Min(value = 10) @Max(value = 100) @Valid @RequestParam(value = "integer", required = false) Integer integer, @Parameter(name = "int32", description = "None") @Min(value = 20) @Max(value = 200) @Valid @RequestParam(value = "int32", required = false) Integer int32, @Parameter(name = "int64", description = "None") @Valid @RequestParam(value = "int64", required = false) Long int64, @@ -418,7 +418,7 @@ default ResponseEntity testEnumParameters( @Parameter(name = "enum_query_string", description = "Query parameter enum test (string)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @Parameter(name = "enum_query_integer", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @Parameter(name = "enum_query_double", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, + @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, @Parameter(name = "enum_form_string", description = "Form parameter enum test (string)") @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString ) { return getDelegate().testEnumParameters(enumHeaderStringArray, enumHeaderString, enumQueryStringArray, enumQueryString, enumQueryInteger, enumQueryDouble, enumFormStringArray, enumFormString); diff --git a/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/FakeApiDelegate.java b/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/FakeApiDelegate.java index 5b6cdd7f828f..fc5d2b5a6d98 100644 --- a/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/FakeApiDelegate.java +++ b/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/FakeApiDelegate.java @@ -189,7 +189,7 @@ default ResponseEntity testClientModel(Client client) { * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -207,7 +207,7 @@ default ResponseEntity testClientModel(Client client) { default ResponseEntity testEndpointParameters(BigDecimal number, Double _double, String patternWithoutDelimiter, - byte[] _byte, + String /* base64 encoded binary */ _byte, Integer integer, Integer int32, Long int64, diff --git a/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/FakeApi.java b/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/FakeApi.java index e9853c88108b..8506a8104c44 100644 --- a/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/FakeApi.java @@ -368,7 +368,7 @@ default ResponseEntity testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -404,7 +404,7 @@ default ResponseEntity testEndpointParameters( @Parameter(name = "number", description = "None", required = true) @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, @Parameter(name = "double", description = "None", required = true) @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, @Parameter(name = "pattern_without_delimiter", description = "None", required = true) @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) byte[] _byte, + @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, @Parameter(name = "integer", description = "None") @Min(value = 10) @Max(value = 100) @Valid @RequestParam(value = "integer", required = false) Integer integer, @Parameter(name = "int32", description = "None") @Min(value = 20) @Max(value = 200) @Valid @RequestParam(value = "int32", required = false) Integer int32, @Parameter(name = "int64", description = "None") @Valid @RequestParam(value = "int64", required = false) Long int64, @@ -459,7 +459,7 @@ default ResponseEntity testEnumParameters( @Parameter(name = "enum_query_string", description = "Query parameter enum test (string)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @Parameter(name = "enum_query_integer", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @Parameter(name = "enum_query_double", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, + @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, @Parameter(name = "enum_form_string", description = "Form parameter enum test (string)") @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString ) { return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); diff --git a/samples/server/petstore/springboot-include-http-request-context/src/main/java/org/openapitools/api/FakeApi.java b/samples/server/petstore/springboot-include-http-request-context/src/main/java/org/openapitools/api/FakeApi.java index 3252e7aef472..312d85379313 100644 --- a/samples/server/petstore/springboot-include-http-request-context/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/server/petstore/springboot-include-http-request-context/src/main/java/org/openapitools/api/FakeApi.java @@ -378,7 +378,7 @@ default ResponseEntity testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -414,7 +414,7 @@ default ResponseEntity testEndpointParameters( @Parameter(name = "number", description = "None", required = true) @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, @Parameter(name = "double", description = "None", required = true) @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, @Parameter(name = "pattern_without_delimiter", description = "None", required = true) @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) byte[] _byte, + @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, @Parameter(name = "integer", description = "None") @Min(value = 10) @Max(value = 100) @Valid @RequestParam(value = "integer", required = false) Integer integer, @Parameter(name = "int32", description = "None") @Min(value = 20) @Max(value = 200) @Valid @RequestParam(value = "int32", required = false) Integer int32, @Parameter(name = "int64", description = "None") @Valid @RequestParam(value = "int64", required = false) Long int64, @@ -470,7 +470,7 @@ default ResponseEntity testEnumParameters( @Parameter(name = "enum_query_string", description = "Query parameter enum test (string)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @Parameter(name = "enum_query_integer", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @Parameter(name = "enum_query_double", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, + @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, @Parameter(name = "enum_form_string", description = "Form parameter enum test (string)") @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString, @Parameter(hidden = true) final HttpServletRequest servletRequest ) { diff --git a/samples/server/petstore/springboot-reactive-noResponseEntity/src/main/java/org/openapitools/api/FakeApi.java b/samples/server/petstore/springboot-reactive-noResponseEntity/src/main/java/org/openapitools/api/FakeApi.java index 49b4c7a1f45d..bbe3229b31a0 100644 --- a/samples/server/petstore/springboot-reactive-noResponseEntity/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/server/petstore/springboot-reactive-noResponseEntity/src/main/java/org/openapitools/api/FakeApi.java @@ -340,7 +340,7 @@ default Mono testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -374,20 +374,20 @@ default Mono testClientModel( ) @ResponseStatus(HttpStatus.BAD_REQUEST) default Mono testEndpointParameters( - @Parameter(name = "number", description = "None", required = true) @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestPart(value = "number", required = true) BigDecimal number, - @Parameter(name = "double", description = "None", required = true) @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestPart(value = "double", required = true) Double _double, - @Parameter(name = "pattern_without_delimiter", description = "None", required = true) @Pattern(regexp = "^[A-Z].*") @Valid @RequestPart(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Parameter(name = "byte", description = "None", required = true) @Valid @RequestPart(value = "byte", required = true) byte[] _byte, - @Parameter(name = "integer", description = "None") @Min(value = 10) @Max(value = 100) @Valid @RequestPart(value = "integer", required = false) Integer integer, - @Parameter(name = "int32", description = "None") @Min(value = 20) @Max(value = 200) @Valid @RequestPart(value = "int32", required = false) Integer int32, - @Parameter(name = "int64", description = "None") @Valid @RequestPart(value = "int64", required = false) Long int64, - @Parameter(name = "float", description = "None") @DecimalMax(value = "987.6") @Valid @RequestPart(value = "float", required = false) Float _float, - @Parameter(name = "string", description = "None") @Pattern(regexp = "[a-zA-Z]") @Valid @RequestPart(value = "string", required = false) String string, + @Parameter(name = "number", description = "None", required = true) @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, + @Parameter(name = "double", description = "None", required = true) @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, + @Parameter(name = "pattern_without_delimiter", description = "None", required = true) @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, + @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, + @Parameter(name = "integer", description = "None") @Min(value = 10) @Max(value = 100) @Valid @RequestParam(value = "integer", required = false) Integer integer, + @Parameter(name = "int32", description = "None") @Min(value = 20) @Max(value = 200) @Valid @RequestParam(value = "int32", required = false) Integer int32, + @Parameter(name = "int64", description = "None") @Valid @RequestParam(value = "int64", required = false) Long int64, + @Parameter(name = "float", description = "None") @DecimalMax(value = "987.6") @Valid @RequestParam(value = "float", required = false) Float _float, + @Parameter(name = "string", description = "None") @Pattern(regexp = "[a-zA-Z]") @Valid @RequestParam(value = "string", required = false) String string, @Parameter(name = "binary", description = "None") @RequestPart(value = "binary", required = false) Part binary, - @Parameter(name = "date", description = "None") @Valid @RequestPart(value = "date", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date, - @Parameter(name = "dateTime", description = "None") @Valid @RequestPart(value = "dateTime", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) OffsetDateTime dateTime, - @Parameter(name = "password", description = "None") @Size(min = 10, max = 64) @Valid @RequestPart(value = "password", required = false) String password, - @Parameter(name = "callback", description = "None") @Valid @RequestPart(value = "callback", required = false) String paramCallback + @Parameter(name = "date", description = "None") @Valid @RequestParam(value = "date", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date, + @Parameter(name = "dateTime", description = "None") @Valid @RequestParam(value = "dateTime", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) OffsetDateTime dateTime, + @Parameter(name = "password", description = "None") @Size(min = 10, max = 64) @Valid @RequestParam(value = "password", required = false) String password, + @Parameter(name = "callback", description = "None") @Valid @RequestParam(value = "callback", required = false) String paramCallback ) { return getDelegate().testEndpointParameters(number, _double, patternWithoutDelimiter, _byte, integer, int32, int64, _float, string, binary, date, dateTime, password, paramCallback); } @@ -432,8 +432,8 @@ default Mono testEnumParameters( @Parameter(name = "enum_query_string", description = "Query parameter enum test (string)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @Parameter(name = "enum_query_integer", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @Parameter(name = "enum_query_double", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, - @Parameter(name = "enum_form_string", description = "Form parameter enum test (string)") @Valid @RequestPart(value = "enum_form_string", required = false) String enumFormString + @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, + @Parameter(name = "enum_form_string", description = "Form parameter enum test (string)") @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString ) { return getDelegate().testEnumParameters(enumHeaderStringArray, enumHeaderString, enumQueryStringArray, enumQueryString, enumQueryInteger, enumQueryDouble, enumFormStringArray, enumFormString); } @@ -533,8 +533,8 @@ default Mono testInlineAdditionalProperties( ) @ResponseStatus(HttpStatus.OK) default Mono testJsonFormData( - @Parameter(name = "param", description = "field1", required = true) @Valid @RequestPart(value = "param", required = true) String param, - @Parameter(name = "param2", description = "field2", required = true) @Valid @RequestPart(value = "param2", required = true) String param2 + @Parameter(name = "param", description = "field1", required = true) @Valid @RequestParam(value = "param", required = true) String param, + @Parameter(name = "param2", description = "field2", required = true) @Valid @RequestParam(value = "param2", required = true) String param2 ) { return getDelegate().testJsonFormData(param, param2); } diff --git a/samples/server/petstore/springboot-reactive-noResponseEntity/src/main/java/org/openapitools/api/FakeApiDelegate.java b/samples/server/petstore/springboot-reactive-noResponseEntity/src/main/java/org/openapitools/api/FakeApiDelegate.java index 6e86c59c7b1f..9991aba5753e 100644 --- a/samples/server/petstore/springboot-reactive-noResponseEntity/src/main/java/org/openapitools/api/FakeApiDelegate.java +++ b/samples/server/petstore/springboot-reactive-noResponseEntity/src/main/java/org/openapitools/api/FakeApiDelegate.java @@ -191,7 +191,7 @@ default Mono testClientModel(Mono client) { * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -209,7 +209,7 @@ default Mono testClientModel(Mono client) { default Mono testEndpointParameters(BigDecimal number, Double _double, String patternWithoutDelimiter, - byte[] _byte, + String /* base64 encoded binary */ _byte, Integer integer, Integer int32, Long int64, diff --git a/samples/server/petstore/springboot-reactive-noResponseEntity/src/main/java/org/openapitools/api/PetApi.java b/samples/server/petstore/springboot-reactive-noResponseEntity/src/main/java/org/openapitools/api/PetApi.java index db31a4242ba5..1b9b9b6c4ae0 100644 --- a/samples/server/petstore/springboot-reactive-noResponseEntity/src/main/java/org/openapitools/api/PetApi.java +++ b/samples/server/petstore/springboot-reactive-noResponseEntity/src/main/java/org/openapitools/api/PetApi.java @@ -303,8 +303,8 @@ default Mono updatePet( @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED) default Mono updatePetWithForm( @Parameter(name = "petId", description = "ID of pet that needs to be updated", required = true, in = ParameterIn.PATH) @PathVariable("petId") Long petId, - @Parameter(name = "name", description = "Updated name of the pet") @Valid @RequestPart(value = "name", required = false) String name, - @Parameter(name = "status", description = "Updated status of the pet") @Valid @RequestPart(value = "status", required = false) String status + @Parameter(name = "name", description = "Updated name of the pet") @Valid @RequestParam(value = "name", required = false) String name, + @Parameter(name = "status", description = "Updated status of the pet") @Valid @RequestParam(value = "status", required = false) String status ) { return getDelegate().updatePetWithForm(petId, name, status); } diff --git a/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/FakeApi.java b/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/FakeApi.java index fab0f1c75273..9ab3e80b84b9 100644 --- a/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/FakeApi.java @@ -341,7 +341,7 @@ default Mono> testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -374,20 +374,20 @@ default Mono> testClientModel( consumes = { "application/x-www-form-urlencoded" } ) default Mono> testEndpointParameters( - @Parameter(name = "number", description = "None", required = true) @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestPart(value = "number", required = true) BigDecimal number, - @Parameter(name = "double", description = "None", required = true) @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestPart(value = "double", required = true) Double _double, - @Parameter(name = "pattern_without_delimiter", description = "None", required = true) @Pattern(regexp = "^[A-Z].*") @Valid @RequestPart(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Parameter(name = "byte", description = "None", required = true) @Valid @RequestPart(value = "byte", required = true) byte[] _byte, - @Parameter(name = "integer", description = "None") @Min(value = 10) @Max(value = 100) @Valid @RequestPart(value = "integer", required = false) Integer integer, - @Parameter(name = "int32", description = "None") @Min(value = 20) @Max(value = 200) @Valid @RequestPart(value = "int32", required = false) Integer int32, - @Parameter(name = "int64", description = "None") @Valid @RequestPart(value = "int64", required = false) Long int64, - @Parameter(name = "float", description = "None") @DecimalMax(value = "987.6") @Valid @RequestPart(value = "float", required = false) Float _float, - @Parameter(name = "string", description = "None") @Pattern(regexp = "[a-zA-Z]") @Valid @RequestPart(value = "string", required = false) String string, + @Parameter(name = "number", description = "None", required = true) @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, + @Parameter(name = "double", description = "None", required = true) @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, + @Parameter(name = "pattern_without_delimiter", description = "None", required = true) @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, + @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, + @Parameter(name = "integer", description = "None") @Min(value = 10) @Max(value = 100) @Valid @RequestParam(value = "integer", required = false) Integer integer, + @Parameter(name = "int32", description = "None") @Min(value = 20) @Max(value = 200) @Valid @RequestParam(value = "int32", required = false) Integer int32, + @Parameter(name = "int64", description = "None") @Valid @RequestParam(value = "int64", required = false) Long int64, + @Parameter(name = "float", description = "None") @DecimalMax(value = "987.6") @Valid @RequestParam(value = "float", required = false) Float _float, + @Parameter(name = "string", description = "None") @Pattern(regexp = "[a-zA-Z]") @Valid @RequestParam(value = "string", required = false) String string, @Parameter(name = "binary", description = "None") @RequestPart(value = "binary", required = false) Part binary, - @Parameter(name = "date", description = "None") @Valid @RequestPart(value = "date", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date, - @Parameter(name = "dateTime", description = "None") @Valid @RequestPart(value = "dateTime", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) OffsetDateTime dateTime, - @Parameter(name = "password", description = "None") @Size(min = 10, max = 64) @Valid @RequestPart(value = "password", required = false) String password, - @Parameter(name = "callback", description = "None") @Valid @RequestPart(value = "callback", required = false) String paramCallback, + @Parameter(name = "date", description = "None") @Valid @RequestParam(value = "date", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date, + @Parameter(name = "dateTime", description = "None") @Valid @RequestParam(value = "dateTime", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) OffsetDateTime dateTime, + @Parameter(name = "password", description = "None") @Size(min = 10, max = 64) @Valid @RequestParam(value = "password", required = false) String password, + @Parameter(name = "callback", description = "None") @Valid @RequestParam(value = "callback", required = false) String paramCallback, @Parameter(hidden = true) final ServerWebExchange exchange ) { return getDelegate().testEndpointParameters(number, _double, patternWithoutDelimiter, _byte, integer, int32, int64, _float, string, binary, date, dateTime, password, paramCallback, exchange); @@ -432,8 +432,8 @@ default Mono> testEnumParameters( @Parameter(name = "enum_query_string", description = "Query parameter enum test (string)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @Parameter(name = "enum_query_integer", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @Parameter(name = "enum_query_double", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, - @Parameter(name = "enum_form_string", description = "Form parameter enum test (string)") @Valid @RequestPart(value = "enum_form_string", required = false) String enumFormString, + @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, + @Parameter(name = "enum_form_string", description = "Form parameter enum test (string)") @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString, @Parameter(hidden = true) final ServerWebExchange exchange ) { return getDelegate().testEnumParameters(enumHeaderStringArray, enumHeaderString, enumQueryStringArray, enumQueryString, enumQueryInteger, enumQueryDouble, enumFormStringArray, enumFormString, exchange); @@ -533,8 +533,8 @@ default Mono> testInlineAdditionalProperties( consumes = { "application/x-www-form-urlencoded" } ) default Mono> testJsonFormData( - @Parameter(name = "param", description = "field1", required = true) @Valid @RequestPart(value = "param", required = true) String param, - @Parameter(name = "param2", description = "field2", required = true) @Valid @RequestPart(value = "param2", required = true) String param2, + @Parameter(name = "param", description = "field1", required = true) @Valid @RequestParam(value = "param", required = true) String param, + @Parameter(name = "param2", description = "field2", required = true) @Valid @RequestParam(value = "param2", required = true) String param2, @Parameter(hidden = true) final ServerWebExchange exchange ) { return getDelegate().testJsonFormData(param, param2, exchange); diff --git a/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/FakeApiDelegate.java b/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/FakeApiDelegate.java index 030b302bfc28..8ecebc0f9e0b 100644 --- a/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/FakeApiDelegate.java +++ b/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/FakeApiDelegate.java @@ -241,7 +241,7 @@ default Mono> testClientModel(Mono client, * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -259,7 +259,7 @@ default Mono> testClientModel(Mono client, default Mono> testEndpointParameters(BigDecimal number, Double _double, String patternWithoutDelimiter, - byte[] _byte, + String /* base64 encoded binary */ _byte, Integer integer, Integer int32, Long int64, diff --git a/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/PetApi.java b/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/PetApi.java index b3ab6be11be1..ae1014d31d79 100644 --- a/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/PetApi.java +++ b/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/PetApi.java @@ -303,8 +303,8 @@ default Mono> updatePet( ) default Mono> updatePetWithForm( @Parameter(name = "petId", description = "ID of pet that needs to be updated", required = true, in = ParameterIn.PATH) @PathVariable("petId") Long petId, - @Parameter(name = "name", description = "Updated name of the pet") @Valid @RequestPart(value = "name", required = false) String name, - @Parameter(name = "status", description = "Updated status of the pet") @Valid @RequestPart(value = "status", required = false) String status, + @Parameter(name = "name", description = "Updated name of the pet") @Valid @RequestParam(value = "name", required = false) String name, + @Parameter(name = "status", description = "Updated status of the pet") @Valid @RequestParam(value = "status", required = false) String status, @Parameter(hidden = true) final ServerWebExchange exchange ) { return getDelegate().updatePetWithForm(petId, name, status, exchange); diff --git a/samples/server/petstore/springboot-spring-pageable-delegatePattern-without-j8/src/main/java/org/openapitools/api/FakeApi.java b/samples/server/petstore/springboot-spring-pageable-delegatePattern-without-j8/src/main/java/org/openapitools/api/FakeApi.java index ec48cd909bef..cbe5b27202a3 100644 --- a/samples/server/petstore/springboot-spring-pageable-delegatePattern-without-j8/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/server/petstore/springboot-spring-pageable-delegatePattern-without-j8/src/main/java/org/openapitools/api/FakeApi.java @@ -294,7 +294,7 @@ default ResponseEntity testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -330,7 +330,7 @@ default ResponseEntity testEndpointParameters( @Parameter(name = "number", description = "None", required = true) @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, @Parameter(name = "double", description = "None", required = true) @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, @Parameter(name = "pattern_without_delimiter", description = "None", required = true) @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) byte[] _byte, + @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, @Parameter(name = "integer", description = "None") @Min(value = 10) @Max(value = 100) @Valid @RequestParam(value = "integer", required = false) Integer integer, @Parameter(name = "int32", description = "None") @Min(value = 20) @Max(value = 200) @Valid @RequestParam(value = "int32", required = false) Integer int32, @Parameter(name = "int64", description = "None") @Valid @RequestParam(value = "int64", required = false) Long int64, @@ -384,7 +384,7 @@ default ResponseEntity testEnumParameters( @Parameter(name = "enum_query_string", description = "Query parameter enum test (string)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @Parameter(name = "enum_query_integer", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @Parameter(name = "enum_query_double", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, + @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, @Parameter(name = "enum_form_string", description = "Form parameter enum test (string)") @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString ) { return getDelegate().testEnumParameters(enumHeaderStringArray, enumHeaderString, enumQueryStringArray, enumQueryString, enumQueryInteger, enumQueryDouble, enumFormStringArray, enumFormString); diff --git a/samples/server/petstore/springboot-spring-pageable-delegatePattern-without-j8/src/main/java/org/openapitools/api/FakeApiDelegate.java b/samples/server/petstore/springboot-spring-pageable-delegatePattern-without-j8/src/main/java/org/openapitools/api/FakeApiDelegate.java index fea3cd713cc0..974a7e58b8af 100644 --- a/samples/server/petstore/springboot-spring-pageable-delegatePattern-without-j8/src/main/java/org/openapitools/api/FakeApiDelegate.java +++ b/samples/server/petstore/springboot-spring-pageable-delegatePattern-without-j8/src/main/java/org/openapitools/api/FakeApiDelegate.java @@ -166,7 +166,7 @@ default ResponseEntity testClientModel(Client body) { * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -184,7 +184,7 @@ default ResponseEntity testClientModel(Client body) { default ResponseEntity testEndpointParameters(BigDecimal number, Double _double, String patternWithoutDelimiter, - byte[] _byte, + String /* base64 encoded binary */ _byte, Integer integer, Integer int32, Long int64, diff --git a/samples/server/petstore/springboot-spring-pageable-delegatePattern/src/main/java/org/openapitools/api/FakeApi.java b/samples/server/petstore/springboot-spring-pageable-delegatePattern/src/main/java/org/openapitools/api/FakeApi.java index ec48cd909bef..cbe5b27202a3 100644 --- a/samples/server/petstore/springboot-spring-pageable-delegatePattern/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/server/petstore/springboot-spring-pageable-delegatePattern/src/main/java/org/openapitools/api/FakeApi.java @@ -294,7 +294,7 @@ default ResponseEntity testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -330,7 +330,7 @@ default ResponseEntity testEndpointParameters( @Parameter(name = "number", description = "None", required = true) @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, @Parameter(name = "double", description = "None", required = true) @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, @Parameter(name = "pattern_without_delimiter", description = "None", required = true) @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) byte[] _byte, + @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, @Parameter(name = "integer", description = "None") @Min(value = 10) @Max(value = 100) @Valid @RequestParam(value = "integer", required = false) Integer integer, @Parameter(name = "int32", description = "None") @Min(value = 20) @Max(value = 200) @Valid @RequestParam(value = "int32", required = false) Integer int32, @Parameter(name = "int64", description = "None") @Valid @RequestParam(value = "int64", required = false) Long int64, @@ -384,7 +384,7 @@ default ResponseEntity testEnumParameters( @Parameter(name = "enum_query_string", description = "Query parameter enum test (string)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @Parameter(name = "enum_query_integer", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @Parameter(name = "enum_query_double", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, + @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, @Parameter(name = "enum_form_string", description = "Form parameter enum test (string)") @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString ) { return getDelegate().testEnumParameters(enumHeaderStringArray, enumHeaderString, enumQueryStringArray, enumQueryString, enumQueryInteger, enumQueryDouble, enumFormStringArray, enumFormString); diff --git a/samples/server/petstore/springboot-spring-pageable-delegatePattern/src/main/java/org/openapitools/api/FakeApiDelegate.java b/samples/server/petstore/springboot-spring-pageable-delegatePattern/src/main/java/org/openapitools/api/FakeApiDelegate.java index fea3cd713cc0..974a7e58b8af 100644 --- a/samples/server/petstore/springboot-spring-pageable-delegatePattern/src/main/java/org/openapitools/api/FakeApiDelegate.java +++ b/samples/server/petstore/springboot-spring-pageable-delegatePattern/src/main/java/org/openapitools/api/FakeApiDelegate.java @@ -166,7 +166,7 @@ default ResponseEntity testClientModel(Client body) { * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -184,7 +184,7 @@ default ResponseEntity testClientModel(Client body) { default ResponseEntity testEndpointParameters(BigDecimal number, Double _double, String patternWithoutDelimiter, - byte[] _byte, + String /* base64 encoded binary */ _byte, Integer integer, Integer int32, Long int64, diff --git a/samples/server/petstore/springboot-spring-pageable-without-j8/src/main/java/org/openapitools/api/FakeApi.java b/samples/server/petstore/springboot-spring-pageable-without-j8/src/main/java/org/openapitools/api/FakeApi.java index 454545ee1b41..b7cafa5ef940 100644 --- a/samples/server/petstore/springboot-spring-pageable-without-j8/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/server/petstore/springboot-spring-pageable-without-j8/src/main/java/org/openapitools/api/FakeApi.java @@ -324,7 +324,7 @@ default ResponseEntity testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -360,7 +360,7 @@ default ResponseEntity testEndpointParameters( @Parameter(name = "number", description = "None", required = true) @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, @Parameter(name = "double", description = "None", required = true) @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, @Parameter(name = "pattern_without_delimiter", description = "None", required = true) @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) byte[] _byte, + @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, @Parameter(name = "integer", description = "None") @Min(value = 10) @Max(value = 100) @Valid @RequestParam(value = "integer", required = false) Integer integer, @Parameter(name = "int32", description = "None") @Min(value = 20) @Max(value = 200) @Valid @RequestParam(value = "int32", required = false) Integer int32, @Parameter(name = "int64", description = "None") @Valid @RequestParam(value = "int64", required = false) Long int64, @@ -415,7 +415,7 @@ default ResponseEntity testEnumParameters( @Parameter(name = "enum_query_string", description = "Query parameter enum test (string)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @Parameter(name = "enum_query_integer", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @Parameter(name = "enum_query_double", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, + @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, @Parameter(name = "enum_form_string", description = "Form parameter enum test (string)") @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString ) { return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); diff --git a/samples/server/petstore/springboot-spring-pageable/src/main/java/org/openapitools/api/FakeApi.java b/samples/server/petstore/springboot-spring-pageable/src/main/java/org/openapitools/api/FakeApi.java index 454545ee1b41..b7cafa5ef940 100644 --- a/samples/server/petstore/springboot-spring-pageable/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/server/petstore/springboot-spring-pageable/src/main/java/org/openapitools/api/FakeApi.java @@ -324,7 +324,7 @@ default ResponseEntity testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -360,7 +360,7 @@ default ResponseEntity testEndpointParameters( @Parameter(name = "number", description = "None", required = true) @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, @Parameter(name = "double", description = "None", required = true) @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, @Parameter(name = "pattern_without_delimiter", description = "None", required = true) @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) byte[] _byte, + @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, @Parameter(name = "integer", description = "None") @Min(value = 10) @Max(value = 100) @Valid @RequestParam(value = "integer", required = false) Integer integer, @Parameter(name = "int32", description = "None") @Min(value = 20) @Max(value = 200) @Valid @RequestParam(value = "int32", required = false) Integer int32, @Parameter(name = "int64", description = "None") @Valid @RequestParam(value = "int64", required = false) Long int64, @@ -415,7 +415,7 @@ default ResponseEntity testEnumParameters( @Parameter(name = "enum_query_string", description = "Query parameter enum test (string)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @Parameter(name = "enum_query_integer", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @Parameter(name = "enum_query_double", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, + @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, @Parameter(name = "enum_form_string", description = "Form parameter enum test (string)") @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString ) { return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); diff --git a/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/FakeApi.java b/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/FakeApi.java index 281d87c7a317..ee02e94590ae 100644 --- a/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/FakeApi.java @@ -368,7 +368,7 @@ default ResponseEntity testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -404,7 +404,7 @@ default ResponseEntity testEndpointParameters( @Parameter(name = "number", description = "None", required = true) @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, @Parameter(name = "double", description = "None", required = true) @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, @Parameter(name = "pattern_without_delimiter", description = "None", required = true) @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) byte[] _byte, + @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, @Parameter(name = "integer", description = "None") @RequestParam(value = "integer", required = false) Optional integer, @Parameter(name = "int32", description = "None") @RequestParam(value = "int32", required = false) Optional int32, @Parameter(name = "int64", description = "None") @RequestParam(value = "int64", required = false) Optional int64, @@ -459,7 +459,7 @@ default ResponseEntity testEnumParameters( @Parameter(name = "enum_query_string", description = "Query parameter enum test (string)", in = ParameterIn.QUERY) @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") Optional enumQueryString, @Parameter(name = "enum_query_integer", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @RequestParam(value = "enum_query_integer", required = false) Optional enumQueryInteger, @Parameter(name = "enum_query_double", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @RequestParam(value = "enum_query_double", required = false) Optional enumQueryDouble, - @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestPart(value = "enum_form_string_array", required = false) Optional> enumFormStringArray, + @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestParam(value = "enum_form_string_array", required = false) Optional> enumFormStringArray, @Parameter(name = "enum_form_string", description = "Form parameter enum test (string)") @RequestParam(value = "enum_form_string", required = false) Optional enumFormString ) { return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); diff --git a/samples/server/petstore/springboot-virtualan/src/main/java/org/openapitools/virtualan/api/FakeApi.java b/samples/server/petstore/springboot-virtualan/src/main/java/org/openapitools/virtualan/api/FakeApi.java index 96482045f99a..208a79c0c86e 100644 --- a/samples/server/petstore/springboot-virtualan/src/main/java/org/openapitools/virtualan/api/FakeApi.java +++ b/samples/server/petstore/springboot-virtualan/src/main/java/org/openapitools/virtualan/api/FakeApi.java @@ -380,7 +380,7 @@ default ResponseEntity testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -417,7 +417,7 @@ default ResponseEntity testEndpointParameters( @Parameter(name = "number", description = "None", required = true) @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, @Parameter(name = "double", description = "None", required = true) @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, @Parameter(name = "pattern_without_delimiter", description = "None", required = true) @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) byte[] _byte, + @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, @Parameter(name = "integer", description = "None") @Min(value = 10) @Max(value = 100) @Valid @RequestParam(value = "integer", required = false) Integer integer, @Parameter(name = "int32", description = "None") @Min(value = 20) @Max(value = 200) @Valid @RequestParam(value = "int32", required = false) Integer int32, @Parameter(name = "int64", description = "None") @Valid @RequestParam(value = "int64", required = false) Long int64, @@ -473,7 +473,7 @@ default ResponseEntity testEnumParameters( @Parameter(name = "enum_query_string", description = "Query parameter enum test (string)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @Parameter(name = "enum_query_integer", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @Parameter(name = "enum_query_double", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, + @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, @Parameter(name = "enum_form_string", description = "Form parameter enum test (string)") @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString ) { return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); diff --git a/samples/server/petstore/springboot-x-implements-skip/src/main/java/org/openapitools/api/FakeApi.java b/samples/server/petstore/springboot-x-implements-skip/src/main/java/org/openapitools/api/FakeApi.java index 78ff6c36ed97..8d9d0fd1f3fe 100644 --- a/samples/server/petstore/springboot-x-implements-skip/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/server/petstore/springboot-x-implements-skip/src/main/java/org/openapitools/api/FakeApi.java @@ -516,7 +516,7 @@ default ResponseEntity testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -552,7 +552,7 @@ default ResponseEntity testEndpointParameters( @Parameter(name = "number", description = "None", required = true) @NotNull @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, @Parameter(name = "double", description = "None", required = true) @NotNull @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, @Parameter(name = "pattern_without_delimiter", description = "None", required = true) @NotNull @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Parameter(name = "byte", description = "None", required = true) @NotNull @Valid @RequestParam(value = "byte", required = true) byte[] _byte, + @Parameter(name = "byte", description = "None", required = true) @NotNull @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, @Parameter(name = "integer", description = "None") @Min(value = 10) @Max(value = 100) @Valid @RequestParam(value = "integer", required = false) Integer integer, @Parameter(name = "int32", description = "None") @Min(value = 20) @Max(value = 200) @Valid @RequestParam(value = "int32", required = false) Integer int32, @Parameter(name = "int64", description = "None") @Valid @RequestParam(value = "int64", required = false) Long int64, @@ -609,7 +609,7 @@ default ResponseEntity testEnumParameters( @Parameter(name = "enum_query_integer", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @Parameter(name = "enum_query_double", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, @Parameter(name = "enum_query_model_array", description = "", in = ParameterIn.QUERY) @RequestParam(value = "enum_query_model_array", required = false) @Nullable List enumQueryModelArray, - @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, + @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, @Parameter(name = "enum_form_string", description = "Form parameter enum test (string)") @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString ) { return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); diff --git a/samples/server/petstore/springboot/src/main/java/org/openapitools/api/FakeApi.java b/samples/server/petstore/springboot/src/main/java/org/openapitools/api/FakeApi.java index 847703b53f8f..1c155bcb769c 100644 --- a/samples/server/petstore/springboot/src/main/java/org/openapitools/api/FakeApi.java +++ b/samples/server/petstore/springboot/src/main/java/org/openapitools/api/FakeApi.java @@ -368,7 +368,7 @@ default ResponseEntity testClientModel( * @param number None (required) * @param _double None (required) * @param patternWithoutDelimiter None (required) - * @param _byte None (required) + * @param _byte None (required) (base64 encoded) * @param integer None (optional) * @param int32 None (optional) * @param int64 None (optional) @@ -404,7 +404,7 @@ default ResponseEntity testEndpointParameters( @Parameter(name = "number", description = "None", required = true) @DecimalMin(value = "32.1") @DecimalMax(value = "543.2") @Valid @RequestParam(value = "number", required = true) BigDecimal number, @Parameter(name = "double", description = "None", required = true) @DecimalMin(value = "67.8") @DecimalMax(value = "123.4") @Valid @RequestParam(value = "double", required = true) Double _double, @Parameter(name = "pattern_without_delimiter", description = "None", required = true) @Pattern(regexp = "^[A-Z].*") @Valid @RequestParam(value = "pattern_without_delimiter", required = true) String patternWithoutDelimiter, - @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) byte[] _byte, + @Parameter(name = "byte", description = "None", required = true) @Valid @RequestParam(value = "byte", required = true) String _byte /* base64 encoded binary */, @Parameter(name = "integer", description = "None") @Min(value = 10) @Max(value = 100) @Valid @RequestParam(value = "integer", required = false) Integer integer, @Parameter(name = "int32", description = "None") @Min(value = 20) @Max(value = 200) @Valid @RequestParam(value = "int32", required = false) Integer int32, @Parameter(name = "int64", description = "None") @Valid @RequestParam(value = "int64", required = false) Long int64, @@ -459,7 +459,7 @@ default ResponseEntity testEnumParameters( @Parameter(name = "enum_query_string", description = "Query parameter enum test (string)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_string", required = false, defaultValue = "-efg") String enumQueryString, @Parameter(name = "enum_query_integer", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_integer", required = false) @Nullable Integer enumQueryInteger, @Parameter(name = "enum_query_double", description = "Query parameter enum test (double)", in = ParameterIn.QUERY) @Valid @RequestParam(value = "enum_query_double", required = false) @Nullable Double enumQueryDouble, - @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestPart(value = "enum_form_string_array", required = false) List enumFormStringArray, + @Parameter(name = "enum_form_string_array", description = "Form parameter enum test (string array)") @RequestParam(value = "enum_form_string_array", required = false) List enumFormStringArray, @Parameter(name = "enum_form_string", description = "Form parameter enum test (string)") @Valid @RequestParam(value = "enum_form_string", required = false) String enumFormString ) { return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);