[Python] auto generated python-flask server fails to map in-body parameter name
#6257 opened on Aug 7, 2017
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
- generate online the python-flask server using this yaml
- Edit
default_controller.pyin./controllersto 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)
- run it with:
$> python app.py - Get sure the request validation works by sending from another terminal a bad request (
property_sixinstead ofproperty_one) viacurl:
$> 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"
}
- 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"
- Rename auto generated
testObjectin thedefault_controller.pytotest_objectto get sure, it's a name issue.
def endpoint_post(test_object = None) -> str:
return 'do some magic! ' + str(test_object)
- 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))