BaseHTTPMiddleware là lớp tiện dụng của Starlette với API dispatch(request, call_next); pure ASGI middleware là một ứng dụng ASGI bọc ứng dụng khác, thao tác trực tiếp trên scope / receive / send.
Toàn bộ middleware dựng sẵn của Starlette được viết theo kiểu pure ASGI.
class RequestIdMiddleware: # pure ASGI
def __init__(self, app): self.app = app
async def __call__(self, scope, receive, send):
if scope["type"] != "http":
return await self.app(scope, receive, send)
request_id = str(uuid4())
async def send_wrapper(message):
if message["type"] == "http.response.start":
message["headers"].append((b"x-request-id", request_id.encode()))
await send(message)
await self.app(scope, receive, send_wrapper)Các giới hạn đã được ghi nhận của BaseHTTPMiddleware:
- contextvars đặt trong endpoint không truyền ngược ra ngoài middleware — mẫu "gắn request id vào contextvar để log" hay hỏng vì lý do này.
- Background task và StreamingResponse hoạt động không đúng, streaming body lớn bị giữ trong bộ nhớ.
- request.is_disconnected() không phản ánh đúng trạng thái khi có BaseHTTPMiddleware phía trên.
- Chi phí cố định mỗi request: nó dựng thêm task group, memory channel và bọc lại response thành streaming response.
Chốt: dùng BaseHTTPMiddleware cho việc đơn giản (đo thời gian, thêm header) trên app không streaming. Chuyển sang pure ASGI khi cần contextvars, streaming, background task hoặc khi middleware nằm trên đường đi của mọi request và chi phí đó có ý nghĩa.