connexion
connexion copied to clipboard
Malformed path parameter returns 404 instead of 400
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
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>
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.
Just a little push since the bug is still present in version 2.9.0. It's not breaking but the wrong error message and status code is very confusing for users of an API.
Hi @D3nn3, I'm afraid this issue is not at the top of our priority list at the moment. We currently match Flask behavior and while I agree that a 400
error would be better, I don't think a 404
error is completely wrong either. We would definitely welcome a PR though.
Note that this is not related to strict_validation
, which applies strict parameter validation for query and form data parameters, but to malformed path parameters. I updated the title of the issue to reflect this. I think @dtkav was correct in his assessment of the underlying issue.
@jrheling routing with number
s is better supported since version 2.9.
Closing this as a wontfix since routing needs to happen before validation, so a 404 error is thrown before reaching validation.