BlackSheep Integration
Hishel provides seamless integration with BlackSheep through ASGI middleware. You can use BlackSheep's built-in cache_control
decorator to set Cache-Control headers, and combine it with Hishel's ASGI middleware for local server-side caching.
Two approaches
- Use BlackSheep's
@cache_control()
decorator to send Cache-Control headers to clients (browsers, CDNs, proxies) - Add Hishel's ASGI middleware to also cache responses locally based on those Cache-Control headers
Installation
pip install hishel blacksheep
Quick Start
Cache-Control Headers Only
Use BlackSheep's built-in cache_control
decorator:
from blacksheep import Application, get
from blacksheep.server.headers.cache import cache_control
app = Application()
@get("/api/data")
@cache_control(max_age=300, public=True)
async def get_data():
# Cache-Control: public, max-age=300
return {"data": "Clients will cache this for 5 minutes"}
With Local Server Caching
Combine BlackSheep's cache_control
decorator with Hishel's ASGI middleware:
from blacksheep import Application, get
from blacksheep.server.headers.cache import cache_control
from hishel.asgi import ASGICacheMiddleware
from hishel import AsyncSqliteStorage
app = Application()
@get("/api/data")
@cache_control(max_age=300, public=True)
async def get_data():
# Cached locally AND by clients/CDNs
return {"data": "Expensive operation result"}
# Wrap with Hishel's ASGI middleware for local caching
app = ASGICacheMiddleware(
app,
storage=AsyncSqliteStorage(),
)
Common Examples
Static Assets
Cache static files for a long time:
@get("/static/logo.png")
@cache_control(max_age=31536000, public=True, immutable=True)
async def get_logo():
return {"file": "logo.png"}
Public API Data
Cache public API responses:
@get("/api/articles")
@cache_control(max_age=300, public=True)
async def get_articles():
return {"articles": ["Article 1", "Article 2"]}
Private User Data
Cache user-specific data (browsers only):
@get("/api/user/profile")
@cache_control(max_age=300, private=True)
async def get_profile():
return {"user": "john_doe"}
CDN Optimization
Different cache times for browsers vs CDNs:
@get("/api/data")
@cache_control(max_age=60, s_maxage=3600, public=True)
async def get_data():
# Browsers: 1 minute, CDN: 1 hour
return {"data": "..."}
No Caching
Prevent caching of sensitive data:
@get("/api/secrets")
@cache_control(no_cache=True, no_store=True)
async def get_secrets():
# Cache-Control: no-cache, no-store
return {"secret": "This response should not be cached or stored!"}
How It Works
- BlackSheep's
@cache_control()
decorator adds Cache-Control headers to responses - Hishel's ASGI middleware reads those headers and caches responses locally according to RFC 9111
- Subsequent requests are served from the local cache when valid, or forwarded to your handlers when cache is stale/missing
This gives you the best of both worlds: - ✅ Client-side caching (browsers, CDNs) via Cache-Control headers - ✅ Server-side caching to reduce load on your application - ✅ RFC 9111 compliant caching behavior - ✅ Simple, declarative API using BlackSheep's native decorators
Notes
Use BlackSheep's native decorator
BlackSheep has excellent built-in cache control support. Use @cache_control()
from BlackSheep rather than creating custom headers.
no_store is strongest
no_store
prevents all caching regardless of other directives.
See Also
- ASGI Integration - General ASGI middleware documentation
- FastAPI Integration - Similar integration with FastAPI
- Storage Backends - Configure cache storage
- BlackSheep Documentation
- RFC 9111: HTTP Caching