Skip to content

This repository is created to showcase a bug in the OpenAPI generator for Spring. The bug appears when using multiple HTTP response codes, of which not all are with response bodies. Response codes that were specified in the OpenAPI spec to not have any response body will still have response bodies from previous HTTP responses in Swagger UI

Notifications You must be signed in to change notification settings

GlobeDaBoarder/openapi-generator-wrong-response-body-bug-demo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

5 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Response bodies bug in OpenAPI Spring generator

Table of contents:

  1. Bug Decription

    1.1. What the bug is

    1.2. Why this is happening

  2. Proposed solution: bugfix

    2.1. What should be changed to fix bug

    2.2. Results of the changes in Swagger Annotations

    2.3. Results of the changes in SwaggerUI: bug fixed

Bug Decription

❗ To reproduce, checkout the bug-showcase branch

It's as simple as:

  •  git clone https://github.com/GlobeDaBoarder/openapi-generator-wrong-response-body-bug-demo.git
  • make sure you are on the bug-showcase branch

  •  mvn clean compile
  • run

  • go to http://localhost:8080

    That's it! Made it simple for y'all πŸ˜‰

What the bug is

The bug is in how OpenAPI Spring generator generates Swagger annotation in api.nustache

Let's say we have a simple Dog API defined in this OpenAPI spec file:

openapi: 3.0.3
info:
  title: Simple test API
  description: Simple test API
  version: 1.0.0
  contact:
    name: Gleb Ivashyn
    url: https://github.com/GlobeDaBoarder?tab=repositories
    email: glebivashyn@gmail.com
servers:
  - url: 'https://localhost:8080'
paths:
  /dogs/ok-endpoints/:
    get:
      summary: Get all dogs
      operationId: getAllDogs
      tags:
        - dogs
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Dog'
  /dogs/ok-endpoints/{id}:
    delete:
      summary: Delete dog by id
      operationId: deleteDogById
      tags:
        - dogs
      parameters:
        - name: id
          in: path
          description: Dog id
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '204':
          description: No Content
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '400':
          description: Bad Request
  /dogs/broken-endpoint/:
    get:
      summary: Broken
      operationId: broken
      deprecated: true # Done purely for visibility purposes in Swagger UI
      tags:
        - dogs
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Dog'
        '204':
          description: No Content
        '400':
          description: Bad Request
components:
  schemas:
    ....

Notice how in our delete methods we have status codes 204 and 400 and how they only have a description without a response body:

... 
responses:
  '204':
    description: No Content
  '404':
    description: Not Found
    content:
      application/json:
        schema:
          $ref: '#/components/schemas/Error'
  '400':
    description: Bad Request
...

and

...
responses:
  '200':
    description: OK
    content:
      application/json:
        schema:
          type: array
          items:
            $ref: '#/components/schemas/Dog'
  '204':
    description: No Content
  '400':
    description: Bad Request
...

Logically, we would expect it to be this way in our Swagger UI as well, but surprisingly it isn't that simple. In one case it is like that, but in another one responses 204 and 400 have a response body that we did not specify.

Case 1: proper response codes with no response bodies:

If we launch the application and go to localhost to view Swagger UI, we will be met with three endpoints. Let's take a look at the /dogs/ok-endpoints/ DELETE endpoint: image

Here, everything looks just like we expected. 204 and 400 have no response body. Good! There is however a different case.

Case 2: 204 and 400 have a response body for some reason...

Now, if we take a look at a different endpoint, which is under 'http://localhost:8090 GET and is deprecated (for visibility purposes). The picture is completely different here:

image

Although specified without response bodies, 204 and 400 now have a response body, coming from the previous response.

Why this is happening

It is hard for me to pinpoint exactly what the reason for this strange behavior is. If we take a look at the generated Swagger UI annotation on controllers, those look fairly normal: image image

In both cases, Swagger annotation does not have any data or schema references that were not defined in OpenAPI spec.

This leads me to believe that the underlying issue is how SpringDoc interprets those annotations. It seems like because the status code 200 comes earlier than codes 204 and 404, SpringDoc for some reason applies this schema even to responses with no schema defined.

Even though this technically seems like more of a SpringDoc issue, It is extremely easy to fix by just slightly adjusting one line in the api.mustache template file of the OpenAPI Spring generator. It's a simple approach and as a result, SpringDoc doesn't get confused : )

Proposed solution: bugfix

❗ To view the proposed bugfix solution, checkout the bugfix-proposal branch

The main and only change that has to be made to the api.mustache file is on the line 176 of the api mustache file from the official OpenAPi Generator GitHub repo

What should be changed

In the default template, this line looks like this:

...
            }{{/baseType}}){{^-last}},{{/-last}}
...

To fix not needed response body generation, all change it to this, as made in the bugfix branch:

            }{{/baseType}}{{^baseType}}, content = @Content{{/baseType}}){{^-last}},{{/-last}}

What this results in, is instead of having to @Content annotation, when no content is specified, it will generate a @Content annotation, BUT EMPTY ONE

See commit info of the fix here

Results of the changes in Swagger Annotation

Before: image

After: image

Although this may seem a bit redundant, it does deal with the bug and doesn't provide that much of clutter and difference.

Results of the changes in SwaggerUI: bug fixed

As a result, our "broken" endpoint (or to be more accurate, an incorrectly displayed API documentation of an endpoint), now looks just like we would expect:

image

That's It!

Thanks for reading through and feel free to ask any questions, open issues, or reach out to me directly. I hope this was an informative and needed contribution πŸ™

About

This repository is created to showcase a bug in the OpenAPI generator for Spring. The bug appears when using multiple HTTP response codes, of which not all are with response bodies. Response codes that were specified in the OpenAPI spec to not have any response body will still have response bodies from previous HTTP responses in Swagger UI

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published