Browse Source

💡 Update comment explaining AsyncExitStack middleware

pull/14099/head
Sebastián Ramírez 2 days ago
parent
commit
cbee872fd4
  1. 34
      fastapi/applications.py

34
fastapi/applications.py

@ -1013,26 +1013,28 @@ class FastAPI(Starlette):
Middleware( Middleware(
ExceptionMiddleware, handlers=exception_handlers, debug=debug ExceptionMiddleware, handlers=exception_handlers, debug=debug
), ),
# Add FastAPI-specific AsyncExitStackMiddleware for dependencies with # Add FastAPI-specific AsyncExitStackMiddleware for closing files.
# contextvars. # Before this was also used for closing dependencies with yield but
# those now have their own AsyncExitStack, to properly support
# streaming responses while keeping compatibility with the previous
# versions (as of writing 0.117.1) that allowed doing
# except HTTPException inside a dependency with yield.
# This needs to happen after user middlewares because those create a # This needs to happen after user middlewares because those create a
# new contextvars context copy by using a new AnyIO task group. # new contextvars context copy by using a new AnyIO task group.
# The initial part of dependencies with 'yield' is executed in the
# FastAPI code, inside all the middlewares. However, the teardown part # This AsyncExitStack preserves the context for contextvars, not
# (after 'yield') is executed in the AsyncExitStack in this middleware. # strictly necessary for closing files but it was one of the original
# intentions.
# If the AsyncExitStack lived outside of the custom middlewares and # If the AsyncExitStack lived outside of the custom middlewares and
# contextvars were set in a dependency with 'yield' in that internal # contextvars were set, for example in a dependency with 'yield'
# contextvars context, the values would not be available in the # in that internal contextvars context, the values would not be
# outer context of the AsyncExitStack. # available in the outer context of the AsyncExitStack.
# By placing the middleware and the AsyncExitStack here, inside all # By placing the middleware and the AsyncExitStack here, inside all
# user middlewares, the code before and after 'yield' in dependencies # user middlewares, the same context is used.
# with 'yield' is executed in the same contextvars context. Thus, all values # This is currently not needed, only for closing files, but used to be
# set in contextvars before 'yield' are still available after 'yield,' as # important when dependencies with yield were closed here.
# expected.
# Additionally, by having this AsyncExitStack here, after the
# ExceptionMiddleware, dependencies can now catch handled exceptions,
# e.g. HTTPException, to customize the teardown code (e.g. DB session
# rollback).
Middleware(AsyncExitStackMiddleware), Middleware(AsyncExitStackMiddleware),
] ]
) )

Loading…
Cancel
Save