swagger-api / swagger-api/swagger-codegen

[Python] auto generated python-flask server fails to map in-body parameter name

Open
#6,257 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

help wanted Issue: Bug Server: Python
Dominant language
Mustache
Stars
17.8k
Forks
6k
PR merge metrics
No merged PRs in 30d

Description

Preface

When using a body parameter, the name is only used for documentation purposes OpenAPI 2.0 specification:

[...] The name of the body parameter has no effect on the parameter itself and is used for documentation purposes only. [...]

According to the Connexion documentatoin it makes a name sanitation for parameter names:

The names of query and form parameters, as well as the name of the body parameter are sanitized by removing characters that are not allowed in Python symbols.

With the following command:

re.sub('^[^a-zA-Z_]+', '', re.sub('[^0-9a-zA-Z_]', '', PARAMETER_NAME))
Description

Swagger converts underscored in-body property name, when generating python-flask server, to the CamelCase, so connexion can not map it.
(The simple swagger.yaml to reproduce the issue is in this Gist)

So the following definition

 parameters:
      - in: body
        name: test_object
        description: object that fails to map
        schema:
          $ref: '#/definitions/TestObject'

Will lead to the following code:

def endpoint_post(testObject = None) -> str:
    return 'do some magic! '

As you can see it turns test_object to testObject.
But when mapping the parameters, connexion would expect test_object, since it is a result of

re.sub('^[^a-zA-Z_]+', '', re.sub('[^0-9a-zA-Z_]', '', 'test_object'))

As the result the server accepts the correct request, but fails to map it because of the bad variable name.

Swagger-codegen version

The online version of the swagger editor, and generator (through the editor menu) on https://app.swaggerhub.com

Swagger declaration file content or url

this yaml is a simple reproduction example

Command line used for generation

none - generated via swaggerhub

Steps to reproduce

Tested with Python 3.5.2, Flask 0.12.2 and connexion 1.1.13 on Ubuntu 16.04

  1. generate online the python-flask server using this yaml
  2. Edit default_controller.py in ./controllers to display the output of the request (for the debug purposes) e.g. like this:
def endpoint_post(testObject = None) -> str:
    return 'do some magic! ' + str(testObject)
  1. run it with: $> python app.py
  2. Get sure the request validation works by sending from another terminal a bad request (property_six instead of property_one) via curl:
$> curl -X POST -H "Content-Type: application/json" --data '{"property_six":"ONE", "property_two":"TWO", "property_three":"THREE"}' http://127.0.0.1:8080/endpoint

validation works:

{
  "detail": "'property_one' is a required property",
  "status": 400,
  "title": "Bad Request",
  "type": "about:blank"
}
  1. Send now the correct request via curl:
$> curl -X POST -H "Content-Type: application/json" --data '{"property_one":"ONE", "property_two":"TWO", "property_three":"THREE"}' http://127.0.0.1:8080/endpoint

The request was accepted, but not mapped to testObject – it is None (default value)

"do some magic! None"
  1. Rename auto generated testObject in the default_controller.py to test_object to get sure, it's a name issue.
def endpoint_post(test_object = None) -> str:
    return 'do some magic! ' + str(test_object)
  1. Send again the correct request via curl:
$> curl -X POST -H "Content-Type: application/json" --data '{"property_one":"ONE", "property_two":"TWO", "property_three":"THREE"}' http://127.0.0.1:8080/endpoint

et voila: the mapping works like it should:

"do some magic! {'property_one': 'ONE', 'property_two': 'TWO', 'property_three': 'THREE'}"
Related issues/PRs

not seen before

Suggest a fix/enhancement

The problem is caused trhough the name conversion. Maybe when generating this part of the code the name conversion should be similar to

re.sub('^[^a-zA-Z_]+', '', re.sub('[^0-9a-zA-Z_]', '', PARAMETER_NAME))

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the generated Python-Flask server from the linked YAML, then inspect the generated default_controller.py and app.py alongside the parameter-name sanitation behavior described in the issue. The fix is complete when an underscored body parameter such as test_object is mapped correctly without manually renaming the generated controller argument, and the documented curl request returns the request body rather than None.

Written by the indexing model from the issue text.

Assessment

Tech stack
flask, python
Domain
api, backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.