Factory.ai

Open-Source Wikis

/

FastAPI

/

Systems

/

Middleware

fastapi/fastapi

Middleware

Purpose

fastapi/middleware/ is a thin layer over Starlette's middleware ecosystem plus one piece of original code. It exists so user code can write from fastapi.middleware.cors import CORSMiddleware rather than reaching into Starlette directly.

Directory layout

fastapi/middleware/
├── __init__.py             # empty
├── asyncexitstack.py       # AsyncExitStackMiddleware (the only original code here)
├── cors.py                 # re-export of starlette.middleware.cors
├── gzip.py                 # re-export of starlette.middleware.gzip
├── httpsredirect.py        # re-export of starlette.middleware.httpsredirect
├── trustedhost.py          # re-export of starlette.middleware.trustedhost
└── wsgi.py                 # re-export of starlette.middleware.wsgi

Each re-export module is a single line:

from starlette.middleware.cors import CORSMiddleware as CORSMiddleware  # noqa

AsyncExitStackMiddleware

The only piece of FastAPI-original middleware. From fastapi/middleware/asyncexitstack.py:

class AsyncExitStackMiddleware:
    def __init__(self, app, context_name="fastapi_middleware_astack"):
        self.app = app
        self.context_name = context_name

    async def __call__(self, scope, receive, send):
        async with AsyncExitStack() as stack:
            scope[self.context_name] = stack
            await self.app(scope, receive, send)

The middleware creates an outer AsyncExitStack per request and stores it on the ASGI scope under fastapi_middleware_astack. Anything that needs to clean up after the response is fully sent (e.g. UploadFile.close()) registers itself on this stack. The framework adds it as the outermost FastAPI-owned middleware in FastAPI.__init__, so user middleware sits inside it.

The two inner stacks (fastapi_inner_astack, fastapi_function_astack) are created in request_response() in fastapi/routing.py — they own dependency cleanup (Depends(...) callables that yield) and run before the outer middleware unwinds.

Adding middleware

User code uses Starlette's app.add_middleware(...):

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

add_middleware is inherited from Starlette. The middleware stack is built lazily on first request (Starlette's behaviour), so middlewares can be added at any point during configuration.

Integration points

  • Up to user code — re-export modules are the documented import paths.
  • Down to Starlette — every implementation except AsyncExitStackMiddleware lives in Starlette.
  • Cross to dependency cleanupAsyncExitStackMiddleware cooperates with the per-request stacks set up in fastapi/routing.py.

Entry points for modification

  • New middleware re-export: copy cors.py, change the import. Keep the as Name rebinding so ruff does not strip it as unused.
  • New original middleware: add a class to fastapi/middleware/ mirroring AsyncExitStackMiddleware. If it should be installed by default, register it in FastAPI.__init__.

See Routing for how the per-request AsyncExitStacks drive dependency cleanup.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Middleware – FastAPI wiki | Factory