resolve the leaked Query default so media Cache-Control max-age is always a valid int (#23553)
Some checks failed
CI / AMD64 Build (push) Has been cancelled
CI / ARM Build (push) Has been cancelled
CI / Jetson Jetpack 6 (push) Has been cancelled
CI / AMD64 Extra Build (push) Has been cancelled
CI / ARM Extra Build (push) Has been cancelled
CI / Synaptics Build (push) Has been cancelled
CI / Assemble and push default build (push) Has been cancelled

This commit is contained in:
Josh Hawkins 2026-06-24 07:57:46 -05:00 committed by GitHub
parent 4e5e8e3c59
commit 933a7f1a3f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -59,6 +59,19 @@ logger = logging.getLogger(__name__)
router = APIRouter(tags=[Tags.media]) router = APIRouter(tags=[Tags.media])
def _resolve_cache_age(max_cache_age: int) -> int:
"""Return max_cache_age as an int.
When a media handler is invoked directly by another handler instead of
through its route, FastAPI doesn't resolve the Query() default and
max_cache_age arrives as the Query object; fall back to its int default.
"""
if isinstance(max_cache_age, int):
return max_cache_age
return max_cache_age.default
@router.get("/{camera_name}", dependencies=[Depends(require_camera_access)]) @router.get("/{camera_name}", dependencies=[Depends(require_camera_access)])
async def mjpeg_feed( async def mjpeg_feed(
request: Request, request: Request,
@ -1215,7 +1228,7 @@ async def event_thumbnail(
thumbnail_bytes, thumbnail_bytes,
media_type=extension.get_mime_type(), media_type=extension.get_mime_type(),
headers={ headers={
"Cache-Control": f"private, max-age={max_cache_age}" "Cache-Control": f"private, max-age={_resolve_cache_age(max_cache_age)}"
if event_complete if event_complete
else "no-store", else "no-store",
}, },
@ -1677,7 +1690,7 @@ async def preview_gif(
gif_bytes, gif_bytes,
media_type="image/gif", media_type="image/gif",
headers={ headers={
"Cache-Control": f"private, max-age={max_cache_age}", "Cache-Control": f"private, max-age={_resolve_cache_age(max_cache_age)}",
"Content-Type": "image/gif", "Content-Type": "image/gif",
}, },
) )
@ -1848,7 +1861,7 @@ async def preview_mp4(
headers = { headers = {
"Content-Description": "File Transfer", "Content-Description": "File Transfer",
"Cache-Control": f"private, max-age={max_cache_age}", "Cache-Control": f"private, max-age={_resolve_cache_age(max_cache_age)}",
"Content-Type": "video/mp4", "Content-Type": "video/mp4",
"Content-Length": str(os.path.getsize(path)), "Content-Length": str(os.path.getsize(path)),
# nginx: https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ignore_headers # nginx: https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ignore_headers