javaspring-bootswaggeropenapi-generatorresponse-headers

Open Api generator doesn't add any information about response headers to generated code


I have following open api specification description:

openapi: 3.0.3
...
  /foo:
    get:
      operationId: foo
      parameters:
        - name: bar
          in: query
          required: true
          schema:
            type: string
      responses:
        200:
          description: description
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
          headers:
            myheader1:
              description: myheader1 desc
              schema:
                type: string
            myheader2:
              description: myheader2 desc
              schema:
                type: integer
        401:
          description: "Unauthorized"
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

The generated code is:

@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "2024-01-24T14:16:01.056664+03:00[Europe/London]")
@Validated
@Tag(name = "Default", description = "the Default API")
@RequestMapping("${openapi.directoryServiceManager.base-path:/api/v1}")
public interface DefaultApi {

    /**
     * GET /foo
     *
     * @param bar  (required)
     * @return description (status code 200)
     *         or Unauthorized (status code 401)
     */
    @Operation(
        operationId = "foo",
        responses = {
            @ApiResponse(responseCode = "200", description = "description", content = {
                @Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = String.class)))
            }),
            @ApiResponse(responseCode = "401", description = "Unauthorized", content = {
                @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorDto.class))
            })
        }
    )
    @RequestMapping(
        method = RequestMethod.GET,
        value = "/foo",
        produces = { "application/json" }
    )
    ResponseEntity<List<String>> foo(
        @NotNull 
@Parameter(name = "bar", description = "", required = true, in = ParameterIn.QUERY) @Valid @RequestParam(value = "bar", required = true) String bar
    );

}

As you can see there is no information about response headers(myheader1 and myheader2)

I would expect that

ApiResponse should have headers argument added

Is there way to fix it ?

More information about environment:

buildscript {
    dependencies {
        classpath("org.openapitools:openapi-generator-gradle-plugin:5.0.0")
    }
}

plugins {
    java
    kotlin("jvm")
    kotlin("plugin.spring") version "1.8.21"  
    id("org.springframework.boot") version "3.1.4"
    id("org.openapi.generator") version "6.3.0"
}

UPDATE

Based on advise in comment I tried to update versions:

buildscript {
    dependencies {
        classpath("org.openapitools:openapi-generator-gradle-plugin:7.2.0")
    }
}

plugins {
    java
    kotlin("jvm")
    kotlin("plugin.spring") version "1.8.21"
    id("io.spring.dependency-management") version "1.1.0"
    id("org.springframework.boot") version "3.1.4"
    id("org.openapi.generator") version "6.5.0"
    id("org.jlleitschuh.gradle.ktlint") version "11.5.0"
    jacoco
}

Generated code still doesn't contain any information about response headers:

@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "2024-01-24T16:42:30.088851100+03:00[Europe/Moscow]")
@Validated
@Tag(name = "Default", description = "the Default API")
@RequestMapping("${openapi.directoryServiceManager.base-path:/api/v1}")
public interface DefaultApi {

    /**
     * GET /foo
     *
     * @param bar  (required)
     * @return description (status code 200)
     *         or Unauthorized (status code 401)
     */
    @Operation(
        operationId = "foo",
        responses = {
            @ApiResponse(responseCode = "200", description = "description", content = {
                @Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = String.class)))
            }),
            @ApiResponse(responseCode = "401", description = "Unauthorized", content = {
                @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorDto.class))
            })
        }
    )
    @RequestMapping(
        method = RequestMethod.GET,
        value = "/foo",
        produces = { "application/json" }
    )
    
    ResponseEntity<List<String>> foo(
        @NotNull 
@Parameter(name = "bar", description = "", required = true, in = ParameterIn.QUERY) @Valid @RequestParam(value = "bar", required = true) String bar
    );

}

Solution

  • Well, it looks like the problem you are facing doesn't have any simple solution this far. As it comes from the answer to this question: openapi-generator doesn't generate response headers for Java client using Spring Webclient

    spring-based templates for openapi-generator do not mention response headers

    Here's the template for JavaSpring: JavaSpring/api.mustache

    And this one is for scala-akka-client: scala-akka-client/api.mustache

    As you see, unlike the second one, the first doesn't declare any reference to {{#responseHeaders}}:

    responses = {
                {{#responses}}
                @ApiResponse(responseCode = {{#isDefault}}"default"{{/isDefault}}{{^isDefault}}"{{{code}}}"{{/isDefault}}, description = "{{{message}}}"{{#baseType}}, content = {
                    {{#produces}}
                    @Content(mediaType = "{{{mediaType}}}", {{#isArray}}array = @ArraySchema({{/isArray}}schema = @Schema(implementation = {{{baseType}}}.class){{#isArray}}){{/isArray}}){{^-last}},{{/-last}}
                    {{/produces}}
                }{{/baseType}}){{^-last}},{{/-last}}
                {{/responses}}
    

    Moreover, there is an issue filed, describing similar problem: https://github.com/OpenAPITools/openapi-generator/issues/11061 and it's not fixed AFAIK.

    In theory you could try to use your custom template for code generation, but as it comes from the response mentioned above, you'll have the same headers for all responses and this contradicts your schema (custom headers are applied only to 200).