OpenAPITools / openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
https://openapi-generator.tech
Apache License 2.0
21.58k stars 6.52k forks source link

[BUG][Java & Kotlin][Spring][Feign] Incorrect generated code when use application/x-www-form-urlencoded for POST methods #17080

Open bhfinapi opened 11 months ago

bhfinapi commented 11 months ago

Bug Report Checklist

Description

The code generators for Spring cloud (both for Java & Kotlin) generate the same code for GET & POST endpoints using "application/x-www-form-urlencoded" payload. As a consequence, for both GET and POST the payload is sent as query parameters in the URL, while a POST call should add the parameters (formencoded) to the body of the request.

We are facing this problem when generating code for a classic OAUTH endpoint

 @RequestMapping(
        method = [RequestMethod.POST],
        value = ["/oauth/token"],
        produces = ["application/json"],
        consumes = ["application/x-www-form-urlencoded"]
    )

This leads to the logging of client ID & secret in all cloud infrastructure logs.

Below I will refer to "Petstore" examples in the project itself, as they contain the same issue, thus it can be reproduced directly there.

openapi-generator version

7.0.1

OpenAPI declaration file content or url

from "Petstore" example:

...
    post:
      description: ""
      operationId: updatePetWithForm
      parameters:
      - description: ID of pet that needs to be updated
        explode: false
        in: path
        name: petId
        required: true
        schema:
          format: int64
          type: integer
        style: simple
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/updatePetWithForm_request'

... 
    updatePetWithForm_request:
      properties:
        name:
          description: Updated name of the pet
          type: string
        status:
          description: Updated status of the pet
          type: string
      type: object

....
Generation Details

Server side generated code:

@RequestMapping(
        method = [RequestMethod.POST],
        value = ["/pet/{petId}"],
        consumes = ["application/x-www-form-urlencoded"]
    )
    fun updatePetWithForm(
@Parameter(description = "ID of pet that needs to be updated", required = true) @PathVariable("petId") petId: kotlin.Long,
@Parameter(description = "Updated name of the pet") @RequestParam(value = "name", required = false) name: kotlin.String? ,
@Parameter(description = "Updated status of the pet") @RequestParam(value = "status", required = false) status: kotlin.String? ): ResponseEntity<Unit> {
        return ResponseEntity(HttpStatus.NOT_IMPLEMENTED)
    }

Correct would be:

@RequestMapping(
        method = [RequestMethod.POST],
        value = ["/pet/{petId}"],
        consumes = ["application/x-www-form-urlencoded"]
    )
    fun updatePetWithForm(
@Parameter(description = "ID of pet that needs to be updated", required = true) @PathVariable("petId") petId: kotlin.Long,
@Parameter(??)  requestForm: UpdatePetWithFormRequest
 ): ResponseEntity<Unit> {
        return ResponseEntity(HttpStatus.NOT_IMPLEMENTED)
    }

...

data class UpdatePetWithFormRequest {
name: String?,
status: String
}

Client side generated code:

@RequestMapping(
            method = [RequestMethod.POST],
            value = ["/pet/{petId}"],
            consumes = ["application/x-www-form-urlencoded"]
    )
    fun updatePetWithForm( 
@PathVariable("petId") petId: kotlin.Long, 
@RequestParam(value = "name", required = false) name: kotlin.String? , 
@RequestParam(value = "status", required = false) status: kotlin.String? 
): ResponseEntity<Unit> {
        return ResponseEntity(HttpStatus.NOT_IMPLEMENTED)
    }

but should be

@RequestMapping(
            method = [RequestMethod.POST],
            value = ["/pet/{petId}"],
            consumes = ["application/x-www-form-urlencoded"]
    )
    fun updatePetWithForm( 
@PathVariable("petId") petId: kotlin.Long, 
requestForm: UpdatePetWithFormRequest
): ResponseEntity<Unit> {
        return ResponseEntity(HttpStatus.NOT_IMPLEMENTED)
    }
Steps to reproduce

just generate any Petstore example for Spring Kotlin or

Related issues/PRs

https://github.com/OpenAPITools/openapi-generator/issues/14967 describes a similar thing in slightly different context.

Suggest a fix

Out initial guess is, that the Mustache templates do not support GET/POST separation.

Ragin-LundF commented 11 months ago

I have the same problem. The Spring clients (Java + Kotlin) cannot process x-www-form-urlencoded correctly and have to be rewritten by hand each time.

ALEXB6924 commented 6 months ago

Version 7.4.0 still has this issue..