perf: stop recomputing static work in per-response ASGI middlewares (#27229)

SecurityHeadersMiddleware called set_security_headers() on every
response — 14 os.environ.get lookups plus a regex validation per
configured header, for values that are static for the process
lifetime. Compute the header list once at construction; when no
security env vars are set, skip wrapping send entirely.

RedirectMiddleware decoded and parse_qs'd the query string of every
GET, though it only acts on /watch?v= and ?shared= URLs. Add a cheap
path/substring precheck first; a false positive just falls through to
the previous full parse, so no redirect behavior changes.

Verified byte-identical responses (status, Location, header values)
against the previous implementations across redirect, passthrough,
and no-env cases.


Claude-Session: https://claude.ai/code/session_01MHg5zs1VBjvRWQ54qHpfYD

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Classic298
2026-07-23 12:29:01 -04:00
committed by GitHub
co-authored by Claude
parent 1513ddaf58
commit 8ace4f0a8a
2 changed files with 14 additions and 3 deletions
+9 -1
View File
@@ -227,7 +227,15 @@ class RedirectMiddleware:
return
path = scope.get('path', '')
query_string = scope.get('query_string', b'').decode('latin-1', errors='replace')
raw_query = scope.get('query_string', b'')
# This middleware only acts on /watch?v= and ?shared= URLs; skip the
# decode + parse_qs work for every other GET. (A false positive on the
# substring check just falls through to the full parse below.)
if not (path.endswith('/watch') or b'shared' in raw_query):
await self.app(scope, receive, send)
return
query_string = raw_query.decode('latin-1', errors='replace')
query_params = parse_qs(query_string)
redirect_params: dict[str, str] = {}
+5 -2
View File
@@ -15,16 +15,19 @@ class SecurityHeadersMiddleware:
def __init__(self, app: ASGIApp) -> None:
self.app = app
# Headers derive only from env vars, which are static for the process
# lifetime — compute them once instead of per response.
self._headers = list(set_security_headers().items())
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
if scope['type'] != 'http':
if scope['type'] != 'http' or not self._headers:
await self.app(scope, receive, send)
return
async def send_with_security_headers(message: Message) -> None:
if message['type'] == 'http.response.start':
headers = MutableHeaders(scope=message)
for key, value in set_security_headers().items():
for key, value in self._headers:
headers[key] = value
await send(message)