connexion icon indicating copy to clipboard operation
connexion copied to clipboard

anyOf does not work when used in additionalProperties

Open heinen opened this issue 3 years ago • 0 comments

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)

heinen avatar Jul 30 '21 13:07 heinen

Closing in favor of #1569.

RobbeSneyders avatar Aug 23 '22 07:08 RobbeSneyders