-
-
Notifications
You must be signed in to change notification settings - Fork 753
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add middleware documentation (#1706)
Contributes towards #1531 This PR adds a documentation page on middleware.
- Loading branch information
1 parent
a34da31
commit fcd4e66
Showing
3 changed files
with
260 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -63,6 +63,7 @@ Documentation | |
:maxdepth: 2 | ||
|
||
quickstart | ||
middleware | ||
cli | ||
routing | ||
request | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
Middleware | ||
========== | ||
|
||
Connexion is built as an ASGI middleware stack wrapping an application. It includes several | ||
middlewares by default that add functionality based on the OpenAPI specification, in the | ||
following order: | ||
|
||
.. csv-table:: | ||
:widths: 30, 70 | ||
|
||
**ExceptionMiddleware**, Handles exceptions raised by the middleware stack or application | ||
**SwaggerUIMiddleware**, Adds a Swagger UI to your application | ||
**RoutingMiddleware**, "Routes incoming requests to the right operation defined in the | ||
specification" | ||
**SecurityMiddleware**, "Checks incoming requests against the security defined in the | ||
specification" | ||
**RequestValidationMiddleware**, Validates the incoming requests against the spec | ||
**ResponseValidationMiddleware**, "Validates the returned responses against the spec, if | ||
activated" | ||
**LifespanMiddleware**, "Allows registration of code to run before application start-up or | ||
after shut-down" | ||
**ContextMiddleware**, "Makes several request scoped context variables available to the | ||
application" | ||
|
||
Adding middleware | ||
----------------- | ||
|
||
You can easily add additional ASGI middleware to the middleware stack with the | ||
:code:`add_middleware` method: | ||
|
||
.. tab-set:: | ||
|
||
.. tab-item:: AsyncApp | ||
:sync: AsyncApp | ||
|
||
.. code-block:: python | ||
from connexion import AsyncApp | ||
app = AsyncApp(__name__) | ||
app.add_middleware(MiddlewareClass, **options) | ||
.. dropdown:: View a detailed reference of the :code:`add_middleware` method | ||
:icon: eye | ||
|
||
.. automethod:: connexion.AsyncApp.add_middleware | ||
:noindex: | ||
|
||
.. tab-item:: FlaskApp | ||
:sync: FlaskApp | ||
|
||
.. code-block:: python | ||
from connexion import FlaskApp | ||
app = FlaskApp(__name__) | ||
app.add_middleware(MiddlewareClass, **options) | ||
.. dropdown:: View a detailed reference of the :code:`add_middleware` method | ||
:icon: eye | ||
|
||
.. automethod:: connexion.FlaskApp.add_middleware | ||
:noindex: | ||
|
||
.. tab-item:: ConnexionMiddleware | ||
:sync: ConnexionMiddleware | ||
|
||
.. code-block:: python | ||
from asgi_framework import App | ||
from connexion import ConnexionMiddleware | ||
app = App(__name__) | ||
app = ConnexionMiddleware(app) | ||
app.add_middleware(MiddlewareClass, **options) | ||
.. dropdown:: View a detailed reference of the :code:`add_middleware` method | ||
:icon: eye | ||
|
||
.. automethod:: connexion.ConnexionMiddleware.add_middleware | ||
:noindex: | ||
|
||
Middleware order | ||
**************** | ||
|
||
The :code:`add_middleware` method takes a :code:`position` argument to define where in the | ||
middleware stack it should be inserted, which should be an instance of the | ||
:class:`~connexion.middleware.MiddlewarePosition` Enum. The positions below are ordered from | ||
outer to inner, in the order they are hit by incoming requests. Note that responses hit the | ||
middlewares in reversed order. | ||
|
||
.. autoclass:: connexion.middleware.MiddlewarePosition | ||
:members: | ||
:member-order: bysource | ||
|
||
Customizing the middleware stack | ||
-------------------------------- | ||
|
||
If you need more flexibility, or want to modify or delete any of the default middlewares, you can | ||
also pass in a customized middleware stack when instantiating your application. | ||
|
||
For example, if you would like to remove the :class:`SecurityMiddleware` since you are handling | ||
Security through an API Gateway in front of your application, you can do: | ||
|
||
.. tab-set:: | ||
|
||
.. tab-item:: AsyncApp | ||
:sync: AsyncApp | ||
|
||
.. code-block:: python | ||
from connexion import AsyncApp, ConnexionMiddleware | ||
middlewares = [middleware for middleware in ConnexionMiddleware.default_middlewares | ||
if not isinstance(middleware, SecurityMiddleware)] | ||
app = AsyncApp(__name__, middlewares=middlewares) | ||
.. dropdown:: View a detailed reference of the :class:`~connexion.AsyncApp` | ||
:code:`__init__` method | ||
:icon: eye | ||
|
||
.. autoclass:: connexion.AsyncApp | ||
:noindex: | ||
|
||
.. tab-item:: FlaskApp | ||
:sync: FlaskApp | ||
|
||
.. code-block:: python | ||
from connexion import FlaskApp, ConnexionMiddleware | ||
middlewares = [middleware for middleware in ConnexionMiddleware.default_middlewares | ||
if not isinstance(middleware, SecurityMiddleware)] | ||
app = FlaskApp(__name__, middlewares=middlewares) | ||
.. dropdown:: View a detailed reference of the :class:`~connexion.FlaskApp` | ||
:code:`__init__` method | ||
:icon: eye | ||
|
||
.. autoclass:: connexion.FlaskApp | ||
:noindex: | ||
|
||
|
||
.. tab-item:: ConnexionMiddleware | ||
:sync: ConnexionMiddleware | ||
|
||
.. code-block:: python | ||
from asgi_framework import App | ||
from connexion import ConnexionMiddleware | ||
middlewares = [middleware for middleware in ConnexionMiddleware.default_middlewares | ||
if not isinstance(middleware, SecurityMiddleware)] | ||
app = App(__name__) | ||
app = ConnexionMiddleware(app, middlewares=middlewares) | ||
.. dropdown:: View a detailed reference of the :class:`~connexion.ConnexionMiddleware` | ||
:code:`__init__` method | ||
:icon: eye | ||
|
||
.. autoclass:: connexion.ConnexionMiddleware | ||
:noindex: | ||
|
||
|
||
Writing custom middleware | ||
------------------------- | ||
|
||
You can add any custom middleware as long as it implements the ASGI interface. To learn how to | ||
write pure ASGI middleware, please refer to the `documentation of starlette`_. | ||
|
||
List of useful middleware | ||
------------------------- | ||
|
||
Starlette provides a bunch of useful middleware such as: | ||
|
||
* `CORSMiddleware`_ | ||
* `SessionMiddleware`_ | ||
* `HTTPSRedirectMiddleware`_ | ||
* `TrustedHostMiddleware`_ | ||
* `GZipMiddleware`_ | ||
|
||
Other useful middleware: | ||
|
||
* `ProxyHeadersMiddleware`_ by Uvicorn | ||
* `SentryASGIMiddleware`_ by Sentry | ||
* `MetricsMiddleware`_ by Prometheus | ||
|
||
For more, check the `asgi-middleware topic`_ on github. | ||
|
||
.. _documentation of starlette: https://www.starlette.io/middleware/#writing-pure-asgi-middleware | ||
.. _CORSMiddleware: https://www.starlette.io/middleware/#corsmiddleware | ||
.. _SessionMiddleware: https://www.starlette.io/middleware/#sessionmiddleware | ||
.. _HTTPSRedirectMiddleware: https://www.starlette.io/middleware/#httpsredirectmiddleware | ||
.. _TrustedHostMiddleware: https://www.starlette.io/middleware/#trustedhostmiddleware | ||
.. _GZipMiddleware: https://www.starlette.io/middleware/#gzipmiddleware | ||
.. _ProxyHeadersMiddleware: https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/proxy_headers.py | ||
.. _SentryASGIMiddleware: https://docs.sentry.io/platforms/python/configuration/integrations/asgi/ | ||
.. _MetricsMiddleware: https://github.com/claws/aioprometheus/blob/master/src/aioprometheus/asgi/middleware.py | ||
.. _asgi-middleware topic: https://github.com/topics/asgi-middleware |