Connexion: strict_validation returning 404 instead of 400 as described in documentation

Created on 9 Nov 2018  路  2Comments  路  Source: zalando/connexion

Description

The documentation says that strict_validation should return a 400, however it appears to be returning a 404 instead

Per the documentation at https://connexion.readthedocs.io/en/latest/request.html#parameter-validation

Connexion can apply strict parameter validation for query and form data parameters. When this is enabled, requests that include parameters not defined in the swagger spec return a 400 error.

Expected behaviour

Connexion returns a 400 Bad Request when a parameter does not match the schema

Actual behaviour

Connexion returns a 404 Not Found when a parameter does not match the schema

Steps to reproduce

Sample Curl Results

connexion issue> curl -i localhost:5000/has-param/1
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 2
Server: Werkzeug/0.14.1 Python/3.6.4
Date: Fri, 09 Nov 2018 19:31:03 GMT

1
connexion issue> curl -i localhost:5000/has-param/a
HTTP/1.0 404 NOT FOUND
Content-Type: application/problem+json
Content-Length: 206
Server: Werkzeug/0.14.1 Python/3.6.4
Date: Fri, 09 Nov 2018 19:30:55 GMT

{
  "detail": "The requested URL was not found on the server.  If you entered the URL manually please check your spelling and try again.",
  "status": 404,
  "title": "Not Found",
  "type": "about:blank"
}

Sample Code

```main.py
import connexion
from connexion.resolver import RestyResolver

def get_has_param(demoId):
return demoId

if __name__ == '__main__':
app = connexion.FlaskApp(__name__)
app.add_api(
'request-validation-demo.yaml',
validate_responses=True,
strict_validation=True,
)
app.run()


#### Sample OpenAPI v3 Document

openapi: 3.0.0
info:
title: This should be returning a 400 on an invalid parameter
version: '0'
paths:
/has-param/{demoId}:
get:
summary: This should be returning a 400 when it gets an invalid parameter, not a 404
operationId: main.get_has_param
parameters:
- name: demoId
in: path
required: true
description: This should be a 400 when invalid
schema:
type: integer
responses:
200:
description: Demo Result
content:
application/json:
schema:
type: integer
400:
description: Demo 400
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
404:
description: Demo 404
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
schemas:
Error:
required:
- code
- message
properties:
code:
type: integer
message:
type: string


### Additional info:

Output of the commands:

connexion issue> python3 --version
Python 3.6.4
connexion issue> pip3 show connexion | grep "^Version\:"
Version: 2.0.1
connexion issue>
```

bug

Most helpful comment

I think what's happening is that the path parameters generate routes for Flask.
The route that's being generated here is something like: /has-param/<demoId:int>: and so Flask is unable to match /has-param/a to this pattern, and returns a 404.

We could drop all types from Flask routes to ensure that parameters make it through to validation - I'm not sure yet what the full implications of that would be. I'll try to play around with it today.

All 2 comments

I think what's happening is that the path parameters generate routes for Flask.
The route that's being generated here is something like: /has-param/<demoId:int>: and so Flask is unable to match /has-param/a to this pattern, and returns a 404.

We could drop all types from Flask routes to ensure that parameters make it through to validation - I'm not sure yet what the full implications of that would be. I'll try to play around with it today.

I just worked through an issue with similar symptoms (I'm guessing it's the same core issue, but someone with a deeper knowledge of connexion may know better).

I added a new path to an existing (and working) project, but was getting 404s in all cases while testing. I narrowed it down to this trivial reproduction case:

Openapi spec:

...
  /games/{game_id}:
    get:
      summary: Game_GET
      description: blah testing
      operationId: main.foo
      parameters:
        - name: game_id
          in: path
          description: ID of the game being played
          required: true
          schema:
            type: number
...

With the corresponding handler:

def foo(game_id):
    return {'hi': game_id}, 200

All calls to .../games/<n> would return a 404. Reading this bug led me to noticed I'd inadvertently specified the parameter type as number rather than integer - when I changed it back to integer all was well.

In my case, I intended the parameter to be an int, so number in the spec was just a mistake. But since number is the way to specify a float per the openapi spec, though, I wonder how one would get connexion routing to work with a float parameter.

Was this page helpful?
0 / 5 - 0 ratings