Skip to content

blackbull.middleware.cache

blackbull.middleware.cache

Response caching middleware (RFC 9111 — HTTP Caching).

Caches successful GET/HEAD responses in a per-worker, in-memory LRU. Subsequent matching requests are served directly from the cache without running the handler. Supports:

  • TTL — server-side max_age (default 300 s), overridable by the response's Cache-Control: max-age=… directive (or, when present, s-maxage=… which takes precedence for shared caches).
  • ETag — auto-generated as W/"<sha256-prefix>" over the response body when the application does not supply one. The client's If-None-Match header is honoured: a match yields a 304 Not Modified with no body, regardless of the cached entry's TTL.
  • Cache-Control respect — responses carrying no-store, private, or no-cache are passed through and not stored. Requests carrying no-store skip the cache lookup too.
  • Authorization header — by default, requests with an Authorization header are NOT served from cache and their responses are NOT stored (RFC 9111 §3.5). Override with cache_authenticated=True.

What it doesn't do (yet):

  • No Vary header support beyond identity matching. A request that differs only by Accept-Encoding or Accept-Language will get the first variant cached.
  • No server-side invalidation API. Restart the worker (or wait for TTL) to clear.
  • No cross-worker sharing. The cache is per-process — each worker has its own. Documented limitation.

The cache key is (method, path, query_string).

Usage::

from blackbull.middleware import Cache

app.use(Cache(max_age=600))     # 10-minute TTL

@app.route(path='/feed')
async def feed(scope, receive, send):
    ...   # served from cache for 10 min after first hit

Cache

Per-worker in-memory response cache.