Tested with `swagger-ui-bundle==1.1.0` from Test PyPI.
Opening this as a draft PR, since I didn't publish `swagger-ui-bundle`
to the main PyPI yet, which I would like to do shortly before we release
Connexion 3.
Before Connexion 2.8, the `swagger_ui_bundle` version didn't have an
upper bound. So if anyone runs into any issues because of this update,
I'd rather have them come look for answers when Connexion 3 is out.
Fixes#1152.
Currently, when a request body is empty, the JSON request validator
would parse it into None, which is later passed down to the JSON Schema
validator. However, jsonschema's validation error message for this case
(when nullable is false) "None is not of type 'object'" is not
particularly friendly to either the API user, nor the website developer.
This change adds a specific check before the None value is passed to
jsonschema to emit a better error message directly.
I also added some drive-by improvements on function argument typing
since _validate in validators don't seem to expect receiving None, but
_parse (the result of which is passed to _validate) is totally allowed
to return None (or anything really). This does not seem to reflect the
logic well.
I’m not exactly sure if this is the best way to do this in Connexion
3.x. [We do have a patch in Connexion 2.x to achieve a similar
effect](e89a7eeea6)
so if anyone understands how the two implementations correspond please
tell me whether the two do the same thing 🙂
---------
Co-authored-by: Robbe Sneyders <robbe.sneyders@ml6.eu>
This PR adds a copyright notice for the new authors / maintainers of
connexion. It also reformats the license / notice files as prescribed by
the license.
I was writing the documentation on exception handling, and I noticed
that it was very hard to explain our current behavior.
Error handlers can be registered either on the internal Flask app (not
the Starlette one) or on the Connexion app, which leads to some
undefined (actually just really hard to explain) behavior. Eg.
- Registering error handlers on a status code would capture
`starlette.HTTPException` errors on the Connexion app, and
`werkzeug.HTTPException` errors on the Flask App, which means that
registering an error handler on a status code doesn't catch all the
errors with that status code.
- Flask does some default error handling which leads to some exceptions
never reaching the error handlers registered on the Connexion app.
So I made the following changes:
- Replaced the default error handlers we registered on the Flask app
with a default handler on the `ExceptionMiddleware` that takes into
account other handlers registered on status codes.
- Configured Flask to propagate exceptions instead of catching them.
- Abstracted away the Starlette `Request` and `Response` types, so users
can and must now use `ConnexionRequest`
and `ConnexionResponse` types in error handlers.
- Renamed the `ASGIRequest` class to `ConnexionRequest` since it is the
only Request class part of the high level
Connexion interface.
We could also rename `ConnexionRequest` and `ConnexionResponse` to just
`Request` and `Response`. Wdyt?
Python 3.7 is end of life. We should support the newer versions instead.
I also changed tox to only run against the minimum dependency versions
on the lowest Python version, since this should lead to the lowest
versions over all Python versions, and hopefully helps speed up our
pipelines :)
Fixes#1689
Changes proposed in this pull request:
- Pass through request body in case of `GET` and `DELETE` requests
---------
Co-authored-by: Robbe Sneyders <robbe.sneyders@gmail.com>
Working towards #1709
I think we're almost there, some tests I did are now working properly.
Would love to get some feedback/ideas on the implementation and the
tests :)
Follow-up on #1708
([comment](https://github.com/spec-first/connexion/pull/1708#issuecomment-1581196226))
As mentioned there, there is a `__repr__` but not a `__str__`, leading
to an empty log message (for HTTPExceptions).
An example when running the dev server (previously the first line would
just be an empty line):
```
HTTPException(status_code=404, detail='Not Found')
INFO: 127.0.0.1:33538 - "GET /swaggers/ui/ HTTP/1.1" 404 Not Found
```
However, I would also be fine with just removing the logging here as
`HTTPException`s can be part of the normal flow, without indicating an
actual application error (case in point: raising a `Not Found`
exception)
When an internal server error
occurs, the logged error is not really useful for the user.
For example, a `KeyError` will only print the missing key instead of the
full stacktrace and error.
Adding it to the common error handler as that one is meant to catch all
remaining errors, `HTTPException`s are handled by another error handler.
Fixes # .
I want to use connexion with newer Starlette
Changes proposed in this pull request:
- Loosen requirements on starlette version
---------
Co-authored-by: Robbe Sneyders <robbe.sneyders@ml6.eu>
Fixes#1697
Because of a wrong comparison against the position `Enum`, middleware
was not actually being added to the stack via `add_middleware`. This PR
fixes this, adds a warning when the middleware position cannot be found,
and adds a test.
Fixes the `Nonetype: None` issue that shows up in the logging.
It is caused by using `logging.exception` while not in an exception
handler.
I don't know whether including the full traceback makes sense in the
logging, but that could also be possible by adding `exc_info=exc`
Registering error handlers on the async app leads to an error on 3.0.0a5
because the error handlers are not unpacked correctly when being
registered internally.
Follow-up on #1671
Since the request context is available globally, we can remove this
complexity from the security handlers ("There should be one-- and
preferably only one --obvious way to do it.")
In addition it seems like there weren't any tests for the context in
security handler functions, and I don't think there's a lot of value in
a test for checking the context in security functions specifically.
Fixes#1682
This PR inspects the parameters of a Middleware class before passing in
the `lifespan` keyword argument. I was doubting to check the class
instead (`isinstance(LifespanMiddleware)`), but that's less flexible if
users want to write custom middleware to handle the lifespan.
This PR adds an `add_middleware` method to the apps and
`ConnexionMiddleware` to easily add middleware to the stack. Before, the
only way to do this was to pass in a complete middleware stack.
The default position to add the new middleware is right before the
`ContextMiddleware`, which is the final middleware in the stack. Another
position can be selected by passing in a `MiddlewarePosition` enum,
which defines some positions which make sense.
Since we can no longer assume that the whole middleware stack is defined
when initializing the `ConnexionMiddleware`, we need to delay building
the middleware stack until the `ConnexionMiddleware` is actually called.
This also means we need to delay registering the APIs and error
handlers. This is now all done in the `_build_middleware_stack` method.
Continues on the work of #1077 by moving the test fixtures into the
`secure_endpoint` fixture and adding a test for it in
`test_secure_api.py`.
The test will check whether an api key in the query will not lead to an
error when `strict_validation` is enabled.