Connexion: Connexion claims extra formData parameters that are in the spec

Created on 16 Aug 2019  路  10Comments  路  Source: zalando/connexion

Description

I have a simple service that expects a POST to a certain endpoint. There's 1 parameter in the requestBody of the POST ("customerId"), and also a header parameter ("Authorization").

If I turn on strict_validation=True and I send a valid request to the endpoint, I get: Extra formData parameter(s) customerId not in spec.

Expected behaviour

The customerId parameter _is_ in the spec, so Connexion should accept the post and call the endpoint's business logic, rather than returning a 400.

Actual behaviour

Returns:

{
    "detail": "Extra formData parameter(s) customerId not in spec",
    "status": 400,
    "title": null,
    "type": "about:blank"
}

Steps to reproduce

I'm using this spec.yaml:

openapi: "3.0.0"

info:
  title: Hello World
  version: "2"
servers:
  - url: /v1.0

paths:
  /test:
    post:
      operationId: hello.test
      summary: A test endpoint.
      parameters:
        # If this header param is here and `strict_validation` is enabled, Connexion gives a 400 error,
        # even if you DO send `customerId`.
        - name: Authorization
          in: header
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                customerId:
                  type: string
              required:
                - customerId
      responses:
        "200":
          description: OK.
        "401":
          description: Unauthorized.

And this app.py:

import connexion


def create_app():
    cxn = connexion.FlaskApp(__name__.split('.')[0], specification_dir='.')
    cxn.add_api('spec.yaml', strict_validation=True, arguments={'title': 'Hello World Example'})
    return cxn.app

And hello.py is just:

def test(body) -> str:
    return f"customerId is {body['customerId']}"

Then, send a (valid) request to the endpoint. I'm using the httpie utility, although you can exercise the bug with the SwaggerUI too.

http -v -f POST http://localhost:8000/v1.0/test "Authorization: Bearer abcd" "customerId=4"

You will see the 400 response mentioned above.

Additional info:

It seems like having the header in the spec is necessary to make the bug happen. If you take out the parameters: block, it works.

Output of the commands:

  • python --version:
    Python 3.6.6

  • pip show connexion | grep "^Version\:"
    Version: 2.3.0

bug

Most helpful comment

Please note that strict mode for connexion was intended to fix a shortcoming of the openapi2.0 spec, but the openapi3.0 spec has a built in notion of strict called additionalProperties.
The OAS3 way to do this is to add additionalProperties: false in the schema.

All 10 comments

Ping...

To add on this:
I've been digging in the source code a bit and it seems that it is running a ParameterValidator instead of a RequestBodyValidator when there are any parameters.

I think the bug is in this function but I'm not sure how it is supposed to work properly:
https://github.com/zalando/connexion/blob/c8d8973c7e390a5e2071c7b494dd7bd52bd55ff1/connexion/operations/abstract.py#L415-L429

@jmdejong Did you make any headway on this?

I see this error in 2.5.1 but not in 2.3.0.

~I think this might be fixed by #1110
There was a regression in 2.5.1 that propagated default values from any parameter type to all other parameters type (like query -> form)~

I was able to reproduce the bug on master.
I think the problem is here: https://github.com/zalando/connexion/blob/master/connexion/decorators/validation.py#L303
it seems to be looking for a key (formData) that is unique to openapi 2.0.

Please note that strict mode for connexion was intended to fix a shortcoming of the openapi2.0 spec, but the openapi3.0 spec has a built in notion of strict called additionalProperties.
The OAS3 way to do this is to add additionalProperties: false in the schema.

Thank you, @jmdejong, @dtkav and @hjacobs ! I'm hoping to try the new version of Connexion out soon, to confirm the fix in my codebase.

Just to clarify: I'm not a Connexion dev. I just encountered this bug too and dug into the codebase in order to try to make it easier for the developers to fix this.

There is still an instance of this line

spec_params = [x['name'] for x in self.parameters['formData']] in
the file

https://github.com/zalando/connexion/blob/master/connexion/decorators/validation.py

The problem still occurs. @hjacobs @dtkav

Are you running into the bug on the latest release?
that line should only apply to swagger2.

Was this page helpful?
0 / 5 - 0 ratings