-
1.1. What the bug is
-
2.1. What should be changed to fix bug
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 π
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.
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:
Here, everything looks just like we expected. 204
and 400
have no response body. Good! There is however a different case.
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:
Although specified without response bodies, 204
and 400
now have a response body, coming from the previous response.
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:
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 : )
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
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
Although this may seem a bit redundant, it does deal with the bug and doesn't provide that much of clutter and difference.
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:
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 π