- 라우터가 B03~B09 · 준비 화면 진입 전 현재 프로젝트를 한 번 확인 — 404 · 403 이면 기억을 비우고 「프로젝트가 없어졌습니다」 안내 + [대시보드로] - workflow-state 는 지워진 프로젝트에 404(전: 200 빈 단계) - 저장 경로 조회 실패는 ProjectNotFoundError(LookupError 하위) — 잡지 않은 자리도 앱 처리기가 404(전: 노선 API 등 500) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016PSXsvyDxjNmufteN5bqmt
38 lines
1.7 KiB
Python
38 lines
1.7 KiB
Python
"""B03 라우터 공통 오류 응답 — 조회 실패와 코드 버그를 갈라 준다.
|
|
|
|
`LookupError`를 통째로 404로 돌리면 `KeyError`·`IndexError` 같은 **코드 버그까지 404로
|
|
조용히 덮인다**. 실제로 업로드 finalize에서 `KeyError('role')`이 404 `{"message": "'role'"}`
|
|
로 나가 로그도 안 남고, 마지막 파일 업로드가 매번 실패로 보이던 사고가 있었다
|
|
(2026-08-08 E2E 점검). 조회 실패(레코드 없음)만 404로 두고 버그는 500 + 로그로 보낸다.
|
|
"""
|
|
|
|
import logging
|
|
from typing import Any
|
|
|
|
from fastapi import Request
|
|
from fastapi.responses import JSONResponse
|
|
|
|
|
|
def lookup_error_response(
|
|
exc: LookupError,
|
|
logger: logging.Logger,
|
|
*,
|
|
context: str,
|
|
fallback_message: str = "요청을 처리하지 못했습니다.",
|
|
**log_fields: Any,
|
|
) -> JSONResponse:
|
|
"""조회 실패면 404, 코드 버그(`KeyError`·`IndexError`)면 500 + 예외 로그."""
|
|
if isinstance(exc, (KeyError, IndexError)):
|
|
detail = " ".join(f"{key}=%s" for key in log_fields)
|
|
logger.exception(f"{context} 처리 중 내부 오류 {detail}".strip(), *log_fields.values())
|
|
return JSONResponse(
|
|
status_code=500,
|
|
content={"status": "error", "message": fallback_message},
|
|
)
|
|
return JSONResponse(status_code=404, content={"status": "error", "message": str(exc)})
|
|
|
|
|
|
async def project_not_found_response(_request: Request, exc: Exception) -> JSONResponse:
|
|
"""`ProjectNotFoundError` 앱 처리기(`main.py` 가 닮) — 잡지 않은 자리도 500 이 아닌 404."""
|
|
return JSONResponse(status_code=404, content={"status": "error", "message": str(exc)})
|