|
8 | 8 | from fastapi import Request, Response |
9 | 9 | from redis.asyncio import Redis, ConnectionPool |
10 | 10 | from sqlalchemy.orm import class_mapper, DeclarativeBase |
| 11 | +from fastapi import FastAPI |
| 12 | +from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint |
11 | 13 |
|
12 | 14 | from app.core.exceptions import CacheIdentificationInferenceError, InvalidRequestError |
13 | 15 |
|
| 16 | +# --------------- server side caching --------------- |
| 17 | + |
14 | 18 | pool: ConnectionPool | None = None |
15 | 19 | client: Redis | None = None |
16 | 20 |
|
@@ -285,3 +289,59 @@ async def inner(request: Request, *args, **kwargs) -> Response: |
285 | 289 | return inner |
286 | 290 |
|
287 | 291 | return wrapper |
| 292 | + |
| 293 | +# --------------- client side caching --------------- |
| 294 | + |
| 295 | +class ClientCacheMiddleware(BaseHTTPMiddleware): |
| 296 | + """ |
| 297 | + Middleware to set the `Cache-Control` header for client-side caching on all responses. |
| 298 | + |
| 299 | + Parameters |
| 300 | + ---------- |
| 301 | + app: FastAPI |
| 302 | + The FastAPI application instance. |
| 303 | + max_age: int, optional |
| 304 | + Duration (in seconds) for which the response should be cached. Defaults to 60 seconds. |
| 305 | +
|
| 306 | + Attributes |
| 307 | + ---------- |
| 308 | + max_age: int |
| 309 | + Duration (in seconds) for which the response should be cached. |
| 310 | +
|
| 311 | + Methods |
| 312 | + ------- |
| 313 | + async def dispatch(self, request: Request, call_next: RequestResponseEndpoint) -> Response: |
| 314 | + Process the request and set the `Cache-Control` header in the response. |
| 315 | +
|
| 316 | + Note |
| 317 | + ---- |
| 318 | + - The `Cache-Control` header instructs clients (e.g., browsers) to cache the response for the specified duration. |
| 319 | + """ |
| 320 | + |
| 321 | + def __init__(self, app: FastAPI, max_age: int = 60) -> None: |
| 322 | + super().__init__(app) |
| 323 | + self.max_age = max_age |
| 324 | + |
| 325 | + async def dispatch(self, request: Request, call_next: RequestResponseEndpoint) -> Response: |
| 326 | + """ |
| 327 | + Process the request and set the `Cache-Control` header in the response. |
| 328 | + |
| 329 | + Parameters |
| 330 | + ---------- |
| 331 | + request: Request |
| 332 | + The incoming request. |
| 333 | + call_next: RequestResponseEndpoint |
| 334 | + The next middleware or route handler in the processing chain. |
| 335 | + |
| 336 | + Returns |
| 337 | + ------- |
| 338 | + Response |
| 339 | + The response object with the `Cache-Control` header set. |
| 340 | +
|
| 341 | + Note |
| 342 | + ---- |
| 343 | + - This method is automatically called by Starlette for processing the request-response cycle. |
| 344 | + """ |
| 345 | + response: Response = await call_next(request) |
| 346 | + response.headers['Cache-Control'] = f"public, max-age={self.max_age}" |
| 347 | + return response |
0 commit comments