mirror of
https://github.com/LukeHagar/connexion.git
synced 2025-12-06 12:27:45 +00:00
Add lifespan documentation (#1759)
Contributes towards https://github.com/spec-first/connexion/issues/1531
This commit is contained in:
@@ -112,6 +112,4 @@ class ExceptionMiddleware(StarletteExceptionMiddleware):
|
|||||||
)
|
)
|
||||||
|
|
||||||
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
|
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
|
||||||
# Needs to be set so starlette router throws exceptions instead of returning error responses
|
|
||||||
scope["app"] = "connexion"
|
|
||||||
await super().__call__(scope, receive, send)
|
await super().__call__(scope, receive, send)
|
||||||
|
|||||||
@@ -477,4 +477,7 @@ class ConnexionMiddleware:
|
|||||||
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
|
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
|
||||||
if self.middleware_stack is None:
|
if self.middleware_stack is None:
|
||||||
self.app, self.middleware_stack = self._build_middleware_stack()
|
self.app, self.middleware_stack = self._build_middleware_stack()
|
||||||
|
# Set so starlette router throws exceptions instead of returning error responses
|
||||||
|
# This instance is also passed to any lifespan handler
|
||||||
|
scope["app"] = self
|
||||||
await self.app(scope, receive, send)
|
await self.app(scope, receive, send)
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ Documentation
|
|||||||
validation
|
validation
|
||||||
security
|
security
|
||||||
context
|
context
|
||||||
|
lifespan
|
||||||
cookbook
|
cookbook
|
||||||
exceptions
|
exceptions
|
||||||
cli
|
cli
|
||||||
|
|||||||
109
docs/lifespan.rst
Normal file
109
docs/lifespan.rst
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
Lifespan
|
||||||
|
========
|
||||||
|
|
||||||
|
You can register lifespan handlers to run code before the app starts, or after it shuts down.
|
||||||
|
This ideal for setting up and tearing down database connections or machine learning models for
|
||||||
|
instance.
|
||||||
|
|
||||||
|
.. tab-set::
|
||||||
|
|
||||||
|
.. tab-item:: AsyncApp
|
||||||
|
:sync: AsyncApp
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import contextlib
|
||||||
|
import typing
|
||||||
|
|
||||||
|
from connexion import AsyncApp, ConnexionMiddleware, request
|
||||||
|
|
||||||
|
@contextlib.asynccontextmanager
|
||||||
|
def lifespan_handler(app: ConnexionMiddleware) -> typing.AsyncIterator:
|
||||||
|
"""Called at startup and shutdown, can yield state which will be available on the
|
||||||
|
request."""
|
||||||
|
client = Client()
|
||||||
|
yield {"client": client}
|
||||||
|
client.close()
|
||||||
|
|
||||||
|
def route():
|
||||||
|
"""Endpoint function called when receiving a request, you can access the state
|
||||||
|
on the request here."""
|
||||||
|
client = request.state.client
|
||||||
|
client.call()
|
||||||
|
|
||||||
|
app = AsyncApp(__name__, lifespan=lifespan_handler)
|
||||||
|
|
||||||
|
.. tab-item:: FlaskApp
|
||||||
|
:sync: FlaskApp
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import contextlib
|
||||||
|
import typing
|
||||||
|
|
||||||
|
from connexion import FlaskApp, ConnexionMiddleware, request
|
||||||
|
|
||||||
|
@contextlib.asynccontextmanager
|
||||||
|
def lifespan_handler(app: ConnexionMiddleware) -> typing.AsyncIterator:
|
||||||
|
"""Called at startup and shutdown, can yield state which will be available on the
|
||||||
|
request."""
|
||||||
|
client = Client()
|
||||||
|
yield {"client": client}
|
||||||
|
client.close()
|
||||||
|
|
||||||
|
def route():
|
||||||
|
"""Endpoint function called when receiving a request, you can access the state
|
||||||
|
on the request here."""
|
||||||
|
client = request.state.client
|
||||||
|
client.call()
|
||||||
|
|
||||||
|
app = FlaskApp(__name__, lifespan=lifespan_handler)
|
||||||
|
|
||||||
|
.. tab-item:: ConnexionMiddleware
|
||||||
|
:sync: ConnexionMiddleware
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import contextlib
|
||||||
|
import typing
|
||||||
|
|
||||||
|
from asgi_framework import App
|
||||||
|
from connexion import ConnexionMiddleware, request
|
||||||
|
|
||||||
|
@contextlib.asynccontextmanager
|
||||||
|
def lifespan_handler(app: ConnexionMiddleware) -> typing.AsyncIterator:
|
||||||
|
"""Called at startup and shutdown, can yield state which will be available on the
|
||||||
|
request."""
|
||||||
|
client = Client()
|
||||||
|
yield {"client": client}
|
||||||
|
client.close()
|
||||||
|
|
||||||
|
def endpoint():
|
||||||
|
"""Endpoint function called when receiving a request, you can access the state
|
||||||
|
on the request here."""
|
||||||
|
client = request.state.client
|
||||||
|
client.call()
|
||||||
|
|
||||||
|
app = App(__name__)
|
||||||
|
app = ConnexionMiddleware(app, lifespan=lifespan_handler)
|
||||||
|
|
||||||
|
Running lifespan in tests
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
If you want lifespan handlers to be called during tests, you can use the ``test_client`` as a
|
||||||
|
context manager.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def test_homepage():
|
||||||
|
app = ... # Set up app
|
||||||
|
with app.test_client() as client:
|
||||||
|
# Application's lifespan is called on entering the block.
|
||||||
|
response = client.get("/")
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
# And the lifespan's teardown is run when exiting the block.
|
||||||
|
|
||||||
|
For more information, please refer to the `Starlette documentation`_.
|
||||||
|
|
||||||
|
.. _Starlette documentation: https://www.starlette.io/lifespan/
|
||||||
Reference in New Issue
Block a user