connexion
connexion copied to clipboard
anyOf does not work when used in additionalProperties
Description
The combination of anyOf and additionalProperties breaks connexion.
Expected behaviour
Multiple data types should be usable for additionProperties, as far as I can see, anyOf is the way to do this with openapi.
Actual behaviour
The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.",\n "status": 500,\n
Steps to reproduce
I constructed a minimal example. Using this api.yaml
:
"openapi": "3.0.0"
info:
title: Debug
version: 1.0.0
servers:
- url: 'http://127.0.0.1:9191'
paths:
/debug:
post:
operationId: debug.debug
responses:
'200':
description: OK
requestBody:
content:
application/json:
schema:
x-body-name: order_list
$ref: '#/components/schemas/OrderList'
components:
schemas:
OrderListConnexionBugWorkaround:
allOf:
- $ref: '#/components/schemas/OrderList'
OrderList:
type: object
additionalProperties:
anyOf:
- type: number
- type: string
which is being run by
import connexion
app = connexion.FlaskApp(__name__, specification_dir='.', port=9191)
app.add_api('api.yaml')
app.run()
and this request:
import requests
r = requests.post("http://localhost:9191/debug", json={'A': 1})
The server will return a 500 error code and the console will show:
ERROR in app: Exception on /debug [POST]
Traceback (most recent call last):
File "/home/anonymous/anaconda3/lib/python3.7/site-packages/connexion/operations/openapi.py", line 322, in _get_typed_body_values
prop_defn = body_props[key]
KeyError: 'A'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/anonymous/anaconda3/lib/python3.7/site-packages/flask/app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "/home/anonymous/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/anonymous/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/anonymous/anaconda3/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/home/anonymous/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "/home/anonymous/anaconda3/lib/python3.7/site-packages/flask/app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/anonymous/anaconda3/lib/python3.7/site-packages/connexion/decorators/decorator.py", line 68, in wrapper
response = function(request)
File "/home/anonymous/anaconda3/lib/python3.7/site-packages/connexion/decorators/uri_parsing.py", line 149, in wrapper
response = function(request)
File "/home/anonymous/anaconda3/lib/python3.7/site-packages/connexion/decorators/validation.py", line 193, in wrapper
response = function(request)
File "/home/anonymous/anaconda3/lib/python3.7/site-packages/connexion/decorators/parameter.py", line 97, in wrapper
request.files, arguments, has_kwargs, sanitize)
File "/home/anonymous/anaconda3/lib/python3.7/site-packages/connexion/operations/abstract.py", line 282, in get_arguments
has_kwargs, sanitize))
File "/home/anonymous/anaconda3/lib/python3.7/site-packages/connexion/operations/openapi.py", line 300, in _get_body_argument
res = self._get_typed_body_values(body_arg, body_props, additional_props)
File "/home/anonymous/anaconda3/lib/python3.7/site-packages/connexion/operations/openapi.py", line 329, in _get_typed_body_values
value = self._get_val_from_param(value, additional_props_defn)
File "/home/anonymous/anaconda3/lib/python3.7/site-packages/connexion/operations/openapi.py", line 381, in _get_val_from_param
if query_schema["type"] == "array":
KeyError: 'type'
Additional info:
What really boggles my mind is that the above example runs flawlessly when replacing $ref: '#/components/schemas/OrderList'
with $ref: '#/components/schemas/OrderListConnexionBugWorkaround'
, also with more complex data types (I am actually using any of [arrays of strings, arrays of ints, ...]). I stumbled by accident upon that workaround.
Output of the commands:
-
python --version
-> Python 3.7.4 -
pip show connexion | grep "^Version\:"
-> 2.9.0 (has also been tested with 2.8.0)
Closing in favor of #1569.