feat(cache): add 30-day browser cache for uploaded images (middleware + S3 CacheControl)

This commit is contained in:
earthjasonlin committed 2026-07-18 08:23:13 +08:00
1 parent 54d778971d
commit 2dc68ff408
3 files changed
+16 -2

No files matched your search

+1 -1
View File
@@ -1,5 +1,5 @@
@echo off @echo off
cd /d "%~dp0" cd /d "%~dp0"
call .venv\Scripts\activate.bat call .venv\Scripts\activate.bat
python -m uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload @rem python -m uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
pause pause
+14 -1
View File
@@ -1,7 +1,8 @@
from pathlib import Path from pathlib import Path
from fastapi import FastAPI from fastapi import FastAPI, Request, Response
from fastapi.staticfiles import StaticFiles from fastapi.staticfiles import StaticFiles
from starlette.middleware.base import BaseHTTPMiddleware
from app.config import UPLOAD_DIR from app.config import UPLOAD_DIR
from app.database import init_db from app.database import init_db
@@ -13,6 +14,18 @@ UPLOAD_DIR.mkdir(exist_ok=True)
app.mount("/static", StaticFiles(directory=str(Path(__file__).resolve().parent / "static")), name="static") app.mount("/static", StaticFiles(directory=str(Path(__file__).resolve().parent / "static")), name="static")
app.mount("/uploads", StaticFiles(directory=str(UPLOAD_DIR)), name="uploads") app.mount("/uploads", StaticFiles(directory=str(UPLOAD_DIR)), name="uploads")
# Browser cache: 30 days for uploaded images (they never change)
class CacheControlMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next):
response: Response = await call_next(request)
if request.url.path.startswith("/uploads/"):
response.headers["Cache-Control"] = "public, max-age=2592000, immutable"
return response
app.add_middleware(CacheControlMiddleware)
app.include_router(web.router) app.include_router(web.router)
app.include_router(api.router) app.include_router(api.router)
+1
View File
@@ -103,6 +103,7 @@ class S3Storage:
def put(self, key: str, data: bytes, content_type: str = "image/jpeg") -> str: def put(self, key: str, data: bytes, content_type: str = "image/jpeg") -> str:
self._client.put_object( self._client.put_object(
Bucket=self.bucket, Key=key, Body=data, ContentType=content_type, Bucket=self.bucket, Key=key, Body=data, ContentType=content_type,
CacheControl="public, max-age=2592000, immutable",
) )
return key return key
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.