[kotlin][jvm-retrofit2] Use @HTTP with hasBody for DELETE operations with a request body
Fixes #25454
With library = jvm-retrofit2, a DELETE operation with a requestBody was generated as @DELETE("path") plus an @Body parameter. Retrofit rejects that on the first call with "Non-body HTTP method cannot contain @Body". A DELETE with a form body fails the same way: "FormUrlEncoded can only be specified on HTTP methods with request body".
The template now emits @HTTP(method = "DELETE", path = "...", hasBody = true) only when the HTTP method does not allow a body (isBodyAllowed is false) and the operation has body or form params (hasBodyOrFormParams). Every other operation keeps the short annotation. The line is shared by the Call, coroutines and Rx variants.
I kept the scope narrow on purpose. #19056 changed every Java retrofit2 operation to @HTTP and was reverted in #19100 because it broke multipart and PUT. With this change, POST, PUT, PATCH and body-less operations generate the same output as before.
Changed files:
modules/openapi-generator/src/main/resources/kotlin-client/libraries/jvm-retrofit2/api.mustachemodules/openapi-generator/src/test/java/org/openapitools/codegen/kotlin/KotlinClientCodegenApiTest.java(new test)modules/openapi-generator/src/test/resources/3_0/kotlin/issue25454-delete-with-body.yaml(the issue spec plus a form-body DELETE, a POST with a body and a DELETE without a body)
Testing:
- The new test fails on master (
@HTTP(method = "DELETE", path = "items", hasBody = true)not found) and passes with the change.KotlinClientCodegenApiTestandKotlinClientCodegenModelTest: 101 tests, 0 failures. - I regenerated the 14 sample configs that use
jvm-retrofit2. No sample file changed, so this PR has no sample updates. - I generated a client from the test spec with
serializationLibrary=kotlinx_serializationanduseCoroutines=true, compiled it with Retrofit 3.0.0, and called each method against OkHttp MockWebServer. On master,deleteItemsanddeleteItemsFormthrowIllegalArgumentException. With the change, the server receivesDELETE /itemswith body{"ids":["a","b"]}andDELETE /items/formwith bodyid=x. The POST and the body-less DELETE behave as before.
The Java retrofit2 template has the same problem. I left it out of this PR.
PR checklist
- Read the contribution guidelines.
- Run the following to build the project and update samples:
(For Windows users, please run the script in WSL)./mvnw clean package || exit ./bin/generate-samples.sh ./bin/configs/*.yaml || exit ./bin/utils/export_docs_generators.sh || exit
Commit all changed files.
This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
These must match the expectations made by your contribution.
You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example./bin/generate-samples.sh bin/configs/java*.
IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed. - If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.
cc @karismann @Zomzog @andrewemery @4brunu @yutaka0m @stefankoppier @e5l
Summary by cubic
Fixes DELETE operations with a request body in the Kotlin jvm-retrofit2 client, which previously generated @DELETE annotations that Retrofit rejects at runtime with "Non-body HTTP method cannot contain @Body" (or the equivalent error for form bodies).
The template now emits @HTTP(method = "DELETE", path = "...", hasBody = true) only when the HTTP method does not allow a body and the operation has body or form parameters. All other operations keep their short annotation, so POST, PUT, PATCH, and body-less operations generate the same output as before.
- Adds a regression test with a JSON-body DELETE, a form-body DELETE, a body-less DELETE, and a POST to verify the annotations.