django/django
Middleware
django/middleware/ ships the built-in middleware classes. Per-app middleware lives alongside the contrib apps that own it (django/contrib/auth/middleware.py, django/contrib/sessions/middleware.py, etc.). The middleware mechanism itself — middleware compilation and dispatch — lives in django/core/handlers/base.py.
Purpose
Provide composable hooks that wrap every request and response. Middleware can short-circuit a request (return early), enrich the request (add request.user, request.session), transform a response (gzip, set CSP headers), or react to exceptions.
Middleware architecture
Since 1.10, middleware is "factory style":
def middleware(get_response):
# one-time setup
def _inner(request):
# before
response = get_response(request)
# after
return response
return _innerOr as a class:
class MyMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
return response
def process_view(self, request, view_func, view_args, view_kwargs):
...
def process_exception(self, request, exception):
...
def process_template_response(self, request, response):
...get_response is the next middleware down the chain (or the URL resolver + view at the bottom). The compilation in BaseHandler.load_middleware() walks MIDDLEWARE in reverse, threading each instance with the next-up callable.
The legacy four-method protocol (process_request, process_view, process_response, process_exception) is still supported via django.utils.deprecation.MiddlewareMixin for backwards compatibility.
Async-capable middleware
A middleware class can declare itself sync-, async-, or both-capable:
class MyMiddleware:
sync_capable = True
async_capable = TrueWhen the middleware chain is being built for an ASGI handler, BaseHandler checks each middleware's capability and bridges via asgiref.sync.sync_to_async / async_to_sync where necessary. A pure-async chain runs without bridging; a pure-sync chain runs without bridging; a mixed chain has bridges inserted at the boundaries.
The sync_and_async_middleware decorator on a class indicates dual capability.
Built-in middleware
django/middleware/
├── cache.py # CacheMiddleware, UpdateCacheMiddleware, FetchFromCacheMiddleware
├── clickjacking.py # XFrameOptionsMiddleware
├── common.py # CommonMiddleware (APPEND_SLASH, PREPEND_WWW, ETag, Content-Length)
├── csp.py # ContentSecurityPolicyMiddleware
├── csrf.py # CsrfViewMiddleware (~19 KB)
├── gzip.py # GZipMiddleware
├── http.py # ConditionalGetMiddleware (If-Modified-Since, If-None-Match)
├── locale.py # LocaleMiddleware (sets request.LANGUAGE_CODE, prefixes URLs)
└── security.py # SecurityMiddleware (HSTS, content-type sniff, referrer policy, …)Plus, in contrib apps:
django/contrib/auth/middleware.py—AuthenticationMiddleware,LoginRequiredMiddleware,PersistentRemoteUserMiddleware.django/contrib/sessions/middleware.py—SessionMiddleware.django/contrib/messages/middleware.py—MessageMiddleware.django/contrib/sites/middleware.py—CurrentSiteMiddleware.django/contrib/redirects/middleware.py—RedirectFallbackMiddleware.django/contrib/flatpages/middleware.py—FlatpageFallbackMiddleware.
Default ordering
The recommended default order from the docs (and the startproject template):
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]Order matters: SessionMiddleware must come before AuthenticationMiddleware (auth needs session). CsrfViewMiddleware must come before any view that uses CSRF tokens. LocaleMiddleware should come after SessionMiddleware so the locale can be read from the session.
Notable middleware
CsrfViewMiddleware
django/middleware/csrf.py is the largest middleware (~19 KB). It:
- Sets a CSRF cookie on safe responses.
- Validates the CSRF token on unsafe methods (POST, PUT, PATCH, DELETE).
- Handles the
Origin/Refererchecks. - Supports the
@csrf_exemptand@csrf_protectdecorators.
CSRF tokens are masked at the wire level to prevent BREACH-style attacks; the unmask happens in middleware.
SecurityMiddleware
Sets a bundle of HTTP security headers from settings:
Strict-Transport-Security(SECURE_HSTS_SECONDS,SECURE_HSTS_INCLUDE_SUBDOMAINS,SECURE_HSTS_PRELOAD).X-Content-Type-Options: nosniff(SECURE_CONTENT_TYPE_NOSNIFF).Referrer-Policy(SECURE_REFERRER_POLICY).Cross-Origin-Opener-Policy(SECURE_CROSS_ORIGIN_OPENER_POLICY).- HTTPS redirect (
SECURE_SSL_REDIRECT,SECURE_SSL_HOST).
CommonMiddleware
Catches a few cross-cutting concerns:
APPEND_SLASH: redirects/footo/foo/if/foodoesn't exist but/foo/does.PREPEND_WWW: redirects bare host towww.host.- ETag generation: hashes responses for
If-None-Matchchecks. DISALLOWED_USER_AGENTS: rejects requests from blocklisted UAs.
CacheMiddleware
UpdateCacheMiddleware and FetchFromCacheMiddleware together implement full-page caching keyed on URL + Vary headers. They're typically wrapped in the per-view @cache_page decorator rather than installed globally.
LocaleMiddleware
Sets request.LANGUAGE_CODE and applies translations to the response. Also supports the i18n_patterns URL prefix mechanism — a request to /fr/articles/ is internally routed to /articles/ with French language activated.
GZipMiddleware
Compresses responses with gzip when the client supports it. Skips already-compressed responses. Implements the BREACH mitigation: never gzip responses that contain CSRF tokens, by default.
XFrameOptionsMiddleware
Sets the X-Frame-Options header (DENY, SAMEORIGIN, or unset). Per-view overrides via @xframe_options_exempt and friends.
ContentSecurityPolicyMiddleware
Added in 6.0. Sets Content-Security-Policy and Content-Security-Policy-Report-Only headers from SECURE_CSP and SECURE_CSP_REPORT_ONLY settings. The CSP utility class lives at django/utils/csp.py.
Integration points
- Handlers (http) — compile and call middleware.
- URL routing (urls) —
process_viewruns after URL resolution, before the view. - Sessions, auth, messages (
contrib/) — each ships its own middleware. - Caching (core utilities) —
cache_pagedecorator wraps cache middleware. - i18n —
LocaleMiddlewareties translation into the request cycle.
Entry points for modification
- Custom middleware: define a callable factory or class with
__init__(get_response)and__call__(request). Optionally implementprocess_view,process_exception,process_template_response. - Async support: declare
sync_capable/async_capableand provide anasync def __call__ifasync_capable. - Settings-driven: read from
django.conf.settingsrather than constructor args.
Key source files
| File | Purpose |
|---|---|
django/core/handlers/base.py |
Middleware compilation, get_response dispatch |
django/middleware/csrf.py |
CSRF protection (~19 KB) |
django/middleware/common.py |
APPEND_SLASH, ETag, content-length |
django/middleware/security.py |
Security headers, HSTS, HTTPS redirect |
django/middleware/cache.py |
Full-page caching |
django/middleware/locale.py |
i18n integration |
django/middleware/gzip.py |
gzip compression |
django/middleware/clickjacking.py |
X-Frame-Options |
django/middleware/csp.py |
CSP headers |
django/middleware/http.py |
Conditional GET |
django/utils/deprecation.py |
MiddlewareMixin (legacy) |
django/utils/csp.py |
CSP value builder |
Where to read tests
tests/middleware/— built-in middleware behaviour.tests/csrf_tests/—CsrfViewMiddlewareexhaustive coverage.tests/middleware_exceptions/—process_exceptionpaths.tests/cache/—CacheMiddleware,cache_page.tests/csp_tests/— CSP middleware.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.