Files
Aislo/common_util/common_util_http_cache.py
T
eomsangdon c970812cf3 feat(3D): 휠 방향 반전·회전점 표시 + 3D/등고선 브라우저 보관함
- 휠 위 = 축소로 반전, 커서 지점을 축으로 한 dolly를 공용 유틸에서 직접 처리
- 회전 중심을 작은 구로 표시(돌리는 동안만, 화면상 크기 일정, 항상 위에 그림)
- 등고선 렌더 비용 감소: 폴리라인을 주곡선·보조곡선 2덩어리로 병합(드로우콜 424 → 2),
  라벨은 카메라가 움직였을 때만 재배치
- common_util_http_cache: 파일 mtime+크기 ETag, If-None-Match 일치 시 304
  (preview·contour 적용, 파일이 바뀌면 자동 무효화)
- A00_Common/b_asset_cache: IndexedDB 보관함(키 = projectId|url, 값 = 바이트+ETag).
  보관본 즉시 사용 후 백그라운드 재검증, 3D는 보관 바이트를 직접 파싱
- 프로젝트 전환 시 타 프로젝트 보관분 삭제, 대시보드→B그룹 이동 시 확정 모델의
  3D 프리뷰·등고선(1.0m) 미리 받기(포인트클라우드 제외)
2026-08-01 09:58:44 +09:00

40 lines
1.6 KiB
Python

"""파일 응답에 브라우저 캐시 검증(ETag)을 붙이는 공통 유틸.
3D 프리뷰·등고선처럼 한 번 만들면 잘 바뀌지 않는 파일은, 브라우저가 이미 받아 둔 것을
그대로 쓰게 해야 새로고침이 빠르다. 그렇다고 무조건 캐시를 믿게 두면 모델을 다시 만들었을 때
옛 파일이 계속 보인다.
그래서 파일의 수정시각·크기로 ETag를 만들어 보내고, 브라우저가 같은 ETag를 들고 오면
본문 없이 304만 돌려준다. 파일이 바뀌면 ETag가 저절로 달라져 새 파일을 받는다.
"""
from __future__ import annotations
from pathlib import Path
from fastapi import Request
from fastapi.responses import FileResponse, Response
# 항상 서버에 물어보되(변경 감지), 안 바뀌었으면 본문을 다시 받지 않는다.
CACHE_CONTROL = "private, max-age=0, must-revalidate"
def file_etag(path: Path) -> str:
"""파일 수정시각·크기로 만든 ETag. 파일이 바뀌면 값이 달라진다."""
stat = path.stat()
return f'"{int(stat.st_mtime)}-{stat.st_size}"'
def cached_file_response(
request: Request,
path: Path,
media_type: str,
filename: str | None = None,
) -> Response:
"""ETag를 붙인 파일 응답. 브라우저가 가진 것과 같으면 304만 돌려준다."""
etag = file_etag(path)
headers = {"ETag": etag, "Cache-Control": CACHE_CONTROL}
if request.headers.get("if-none-match") == etag:
return Response(status_code=304, headers=headers)
return FileResponse(path, media_type=media_type, filename=filename, headers=headers)