swagger-api / swagger-api/swagger-codegen
[Python] generator mishandles parameters having non-uniform 'in' attribute values
Nobody has claimed this yet.
- Dominant language
- Mustache
- Stars
- 17.8k
- Forks
- 6k
- PR merge metrics
- No merged PRs in 30d
Description
Problem description
When specifying a resource endpoint having multiple parameters, if the in attribute is heterogeneous within that set -- e.g., if some parameters are query params, others are present in form/body data -- the code generation is woefully broken. In some cases, it duplicates parameters, in others eliminates them entirely, and in all cases the positional parameter ordering is scrambled.
The example case included here to illustrate the problem has been vastly simplified. In a nutshell, it consists of a single POST /login endpoint with two parameters: 1. username (in=query) and 2. password (in=formData) (ordering significant).
Expected/correct method generation should be (Python syntax):
def login(self, username, password, **kwargs):
When it fails by omission, the faulty method signature is:
def login(self, username, **kwargs): # missing password
And when it fails by duplication, the faulty method signature is:
def login(self, password2, password, username, **kwargs): # extra password2, params reordered
I can, by hackery, correct the duplication problem (see below), but even in that case, so corrected, the faulty method signature is:
def login(self, password, username, **kwargs): # params reordered
In the failing cases, I haven't evaluated whether the actual code being generated by the Python template functions correctly, as the method signature is wrong so it doesn't really matter if the code is functional.
Reordering is not a problem that can be dismissed because Swagger (a.k.a. OpenAPI) pages are intended as API documentation. As such, when an end-user sees required parameters listed in a particular order, they can count on this always matching the parameter order specified to a generated SDK method. That is, except in this failure case, where the parameter ordering is scrambled, and a user would not know this.
Swagger-codegen version
I have done some investigation of what swagger-codegen versions misbehave in which ways, and here are my rough findings:
- 2.x -- actually generates correct parameter ordering and no duplication/omission, but we want to use the v3.x feature set/structure
- 3.0.0 -3.0.1 -- generator won't even parse the input OpenAPI spec
- 3.0.4 -- fails by omission
- 3.0.5 ... -- fails by duplication/reordering
I also cloned the source tip of the 3.0.0 branch, and npm-built a 3.0.36-SNAPSHOT version, but it unsurprisingly failed the same way as 3.0.35.
Swagger declaration file content or url
minimal.json:
{
"swagger": "2.0",
"paths": {
"/login": {
"post": {
"parameters": [
{
"name": "username",
"in": "query",
"type": "string",
"required": true,
},
{
"name": "password",
"in": "formData",
"type": "string",
"format": "password",
"required": true,
}
],
"consumes": [
"application/x-www-form-urlencoded",
"multipart/form-data"
]
}
}
}
}
Command line used for generation
$ swagger-codegen-cli generate --lang python -DprojectName="example" -DpackageName="sdk" --api-package "example" -i minimal.json -o example $@
Steps to reproduce
That's it. Run the above and observe the generated example/sdk/example/default_api.py file.
As alluded to above, the "duplication" part of the problem can be eliminated by reducing the consumes list to one element. However, this necessity/effect is semantically wrong, as the OpenAPI 2.0 spec describes "consumes" clauses as: "A list of MIME types the APIs can consume", so this should be a set of possibilities presented for accepted formatting of the HTTP transport layer, not in any way a definition of the multiplicity of parameters. However, as stated previously, even modifying this to a single MIME type in the list still results in parameter reordering.
Related issues/PRs
This issue does appear to resemble #10830 -- not necessarily with the problem reported there, but with the problem reported there by commenter frague59. That user is also plagued with 2 suffixes on parameters and duplication. Nothing suggests that this is a Python-only problem, but I'm reporting it as such, and did not search all the many other non-Python language-specific reports to see if it's been reported similarly in those contexts.
Suggest a fix/enhancement
Being unfamiliar with the code structure and design, I couldn't make heads or tails of where to find the parameter iteration as to see if crafting an ordering-invariant patch was feasible -- it's definitely not immediately apparent where this would be. So I'm submitting this bug report instead. The problem is clearly in the generator itself, though, as the Mustache/Handlebar templates for Python are very simple for api.py, and have no nuance as to parameter ordering.
Significance
I'm a team lead and architect for a large telecom, and have been a strong advocate of using swagger-codegen for nearly all of our many services/microservices we deploy. It is (was?) particularly appealing because of the wide variety of language bindings supported, which made for great bullet items in presentations.
However, this is a problem that has plagued us for the last three years now -- and which I bug-reported to this site back then -- and it still isn't fixed, or even acknowledged. Please don't answer with "well then don't specify parameters that way", because this is a supported use case (it worked in v2.0) and is a desired feature for our purposes. There is nothing suggesting anywhere that parameter sourcing locations for a given endpoint need to be homogeneous.
We have come to the end of our workaround alternatives to bypass this deficiency, and need this capability to function correctly moving forward. Creating a "custom generator" is not an option we'd want embark on, as this is a broken core feature, and we have enough code to maintain. Barring some solution forthcoming in the near future -- or at least an acknowledgment -- we will probably abandon swagger-codegen to the "almost works" bin of software littering the byways of history. (Three software years is a long time.)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Run the supplied swagger-codegen-cli command with minimal.json and inspect the generated example/sdk/example/default_api.py signature. Start by tracing parameter handling in the generator rather than the simple Python api.py templates; done means the mixed query and formData endpoint generates def login(self, username, password, **kwargs) without omission, duplication, or reordering.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100