Open bonii-xx opened 4 years ago
Not just for requestBodies, also for reponse: http://spec.openapis.org/oas/v3.0.3#response-object
I'd like to push this :slightly_smiling_face:
Not just for requestBodies, also for reponse: http://spec.openapis.org/oas/v3.0.3#response-object
jup we just ran into that too. IMO this is even the more urgent gap here b/c typically u might want to add some structured error responses for a 5xx (see also https://datatracker.ietf.org/doc/rfc7807/).
Moreover, when declaring diff. responses per code then u dont even get a warning.
Suggestion: can we adapt the title to "Endpoints don't support different schema per status code and/or content-type" Maybe there is some bug around for this, but if found none.
Question: Are there some workarounds available ?
Sorry, can't remember what I did exactly on the project I needed it for (contract finished) but I believe it's a show stopper when sticking to a single endpoint. So, you'll have to either multiplex at the response object type level (with client-side demultiplexing, i.e. type-switching, Yuck!!) or define separate endpoints (again typr-switching at the client-side).
In other words you're forced to introduce a client-side design stink!!
If I remember correctly from looking at the source, the issue is hard to fix because there is a fundamental design decision at the heart of the issue based on a bad assumption about the spec, probably by reading too much into the example without properly reading the spec itself (the type of the 'content' field is quite explicitly a Map["String", Media Type Object]). That, or pointlessly assuming nobody would need it anyway.
API endpoints are not RPCs and hence are not uniquely valued mathematical functions!
At the very least, it should be mentioned under Limitations or Errata!
I haven't checked newer versions but if there is still no traction at all, this is yet another dead open source project. This is a fundamental implementation flaw, regardless of theoretical discussions about the necessity of multi-typed response bodies.
Oh man this is major bummer. Any other openapi generators that support this feature that you know of?
Heads up; our java layer was missing this needed request body content type information. I will add it in this PR: https://github.com/OpenAPITools/openapi-generator/pull/10973 After that lands any generator can use that information to include multiple content types in request bodies
Once it lands I will work on implementing it in python-experimental: https://github.com/OpenAPITools/openapi-generator/pull/8325
Not just for requestBodies, also for reponse...
@gbormann Response content and header parameters were also added in https://github.com/OpenAPITools/openapi-generator/pull/11046 so all generators now have this data available and can use it to support schema per body content type serialization and deserialization.
For python-experimental I am using #10973 in this PR: https://github.com/OpenAPITools/openapi-generator/pull/8325 to allow users to send request bodies with different body content types supported. One can see it working here: https://github.com/OpenAPITools/openapi-generator/blob/master/samples/openapi3/client/petstore/python-experimental/petstore_api/api/pet_api_endpoints/add_pet.py#L78
pet_parameter = api_client.RequestBody(
content={
'application/json': api_client.MediaType(schema=SchemaForRequestBodyApplicationJson),
'application/xml': api_client.MediaType(schema=SchemaForRequestBodyApplicationXml),
},
required=True,
)
Java and other generators could do something similar
Another push more here. I found this issue when I tried to return two different response, each of them with a different content type, on the same endpoint. Following as it is described here
This yaml code
/pet/{petId}:
get:
description: Get pet
operationId: getPet
tags:
- REST
parameters:
- in: path
name: petId
schema:
type: string
format: uuid
required: true
responses:
200:
description: Returns PDF
content:
application/json:
schema:
$ref: '#/components/schemas/pet'
application/pdf:
schema:
type: string
format: binary
headers:
Content-Disposition:
schema:
type: string
description: Used only with `application/pdf` responses
example: attachment; filename="name.pdf"
'404':
description: Pet not found for the petId
content:
application/json:
schema:
$ref: '#/components/schemas/error-response'
Generate the following code:
/**
* GET /pet/{petId}
* Get pet
*
* @param petId (required)
* @return Returns PDF (status code 200)
* or Pet not found for the petId (status code 404)
*/
@Operation(
operationId = "getPet",
tags = { "REST" },
responses = {
@ApiResponse(responseCode = "200", description = "Returns PDF", content = {
@Content(mediaType = "application/json", schema = @Schema(implementation = PetDTO.class)),
@Content(mediaType = "application/pdf", schema = @Schema(implementation = PetDTO.class))
}),
@ApiResponse(responseCode = "404", description = "Pet not found for the petId", content = {
@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponseDTO.class)),
@Content(mediaType = "application/pdf", schema = @Schema(implementation = ErrorResponseDTO.class))
})
},
security = {
@SecurityRequirement(name = "bearer-key")
}
)
@RequestMapping(
method = RequestMethod.GET,
value = "/pet/{petId}",
produces = { "application/json", "application/pdf" }
)
default ResponseEntity<PetDTO> getPet(
@Parameter(name = "petId", description = "", required = true) @PathVariable("petId") UUID petId
) {
getRequest().ifPresent(request -> {
for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
String exampleString = "{ \"name\" : \"Toby\", \"id\" : \"046b6c7f-0b8a-43b9-b35d-6489e6daee91\" }";
ApiUtil.setExampleResponse(request, "application/json", exampleString);
break;
}
if (mediaType.isCompatibleWith(MediaType.valueOf("application/pdf"))) {
String exampleString = "Custom MIME type example not yet supported: application/pdf";
ApiUtil.setExampleResponse(request, "application/pdf", exampleString);
break;
}
}
});
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
Due the method on the interface generated is defined to return a ResponseEntity<PetDTO>
, you cannot implement a method that return something else depending of the Accept
header.
This should be addressed with somewhat higher prio - it's opened almost four years ago, and is a showstopper in many cases. The example @pedrograu provided above perfectly illustrates the problem. Unless you under-specify your API endpoints, i.e. leave out the schema for the returned values and just specify them as object
, you can only return one single type for all mime types. This is obviously not convenient. A simple solution would be to simply generate handler methods to return ResponseEntity<?>
when there are multiple return types possible, maybe controlled by a config parameter for the generator.
How is this an open issue for 4 years ? that means there is a work around for this ? would love to know . The solution suggested by @Anonymous-Coward seems like a viable option 🤔
Bug Report Checklist
Description
We want to support multiple schema for a single endpoint, depending on content-types. According to https://swagger.io/docs/specification/describing-request-body/ this is exactly what the OpenAPI spec should support:
However the generator always combines the different content-types into a single endpoint, only using the first content-type, with the following output:
openapi-generator version
openapi-generator-maven-plugin 4.3.1
OpenAPI declaration file content or url
https://gist.github.com/bonii-xx/1d48dd6d8e624aa3689cbb062ac2a7d2
Command line used for generation
Via openapi-generator-maven-plugin.
Steps to reproduce
Paste file above into https://editor.swagger.io/ Click on
Generate Server
->spring
Check code of generated FoobarApi Expect 2 endpoints with different RequestBodies, but only one is present handling both. The second request body schema for the second content type is not accepted.Related issues/PRs
https://github.com/OpenAPITools/openapi-generator/issues/144 https://github.com/OpenAPITools/openapi-generator/issues/3990 https://github.com/OpenAPITools/openapi-generator/pull/3991