Spaces:
Running
Running
| """ | |
| Standardized Error Response Models | |
| ν΅μΌλ μλ¬ μλ΅ νμ | |
| λͺ¨λ API μλν¬μΈνΈμμ μΌκ΄λ μλ¬ μλ΅ μ 곡 | |
| """ | |
| from typing import Optional, Any, Dict | |
| from fastapi import HTTPException, status | |
| from pydantic import BaseModel | |
| class ErrorDetail(BaseModel): | |
| """ | |
| μλ¬ μμΈ μ 보 | |
| Attributes: | |
| code: μλ¬ μ½λ (μ: "TOKEN_001", "VALIDATION_ERROR") | |
| message: μ¬μ©μ μΉνμ μλ¬ λ©μμ§ | |
| field: μλ¬κ° λ°μν νλ (μ ν) | |
| details: μΆκ° μ 보 (μ ν) | |
| """ | |
| code: str | |
| message: str | |
| field: Optional[str] = None | |
| details: Optional[Dict[str, Any]] = None | |
| class ErrorResponse(BaseModel): | |
| """ | |
| νμ€ μλ¬ μλ΅ | |
| Attributes: | |
| success: νμ False | |
| error: μλ¬ μμΈ μ 보 | |
| """ | |
| success: bool = False | |
| error: ErrorDetail | |
| def create_error_response( | |
| code: str, | |
| message: str, | |
| status_code: int = status.HTTP_400_BAD_REQUEST, | |
| field: Optional[str] = None, | |
| details: Optional[Dict[str, Any]] = None | |
| ) -> HTTPException: | |
| """ | |
| νμ€ μλ¬ μλ΅ μμ± | |
| Args: | |
| code: μλ¬ μ½λ | |
| message: μλ¬ λ©μμ§ | |
| status_code: HTTP μν μ½λ | |
| field: μλ¬ νλ (μ ν) | |
| details: μΆκ° μ 보 (μ ν) | |
| Returns: | |
| HTTPException | |
| """ | |
| return HTTPException( | |
| status_code=status_code, | |
| detail=ErrorResponse( | |
| error=ErrorDetail( | |
| code=code, | |
| message=message, | |
| field=field, | |
| details=details | |
| ) | |
| ).model_dump() | |
| ) | |
| # μ¬μ μ μλ μλ¬ μμ± ν¨μ | |
| def bad_request_error( | |
| message: str, | |
| code: str = "BAD_REQUEST", | |
| field: Optional[str] = None | |
| ) -> HTTPException: | |
| """400 Bad Request μλ¬""" | |
| return create_error_response( | |
| code=code, | |
| message=message, | |
| status_code=status.HTTP_400_BAD_REQUEST, | |
| field=field | |
| ) | |
| def unauthorized_error( | |
| message: str = "μΈμ¦μ΄ νμν©λλ€", | |
| code: str = "UNAUTHORIZED" | |
| ) -> HTTPException: | |
| """401 Unauthorized μλ¬""" | |
| return create_error_response( | |
| code=code, | |
| message=message, | |
| status_code=status.HTTP_401_UNAUTHORIZED | |
| ) | |
| def forbidden_error( | |
| message: str = "μ κ·Ό κΆνμ΄ μμ΅λλ€", | |
| code: str = "FORBIDDEN" | |
| ) -> HTTPException: | |
| """403 Forbidden μλ¬""" | |
| return create_error_response( | |
| code=code, | |
| message=message, | |
| status_code=status.HTTP_403_FORBIDDEN | |
| ) | |
| def not_found_error( | |
| resource: str = "리μμ€", | |
| code: str = "NOT_FOUND" | |
| ) -> HTTPException: | |
| """404 Not Found μλ¬""" | |
| return create_error_response( | |
| code=code, | |
| message=f"{resource}λ₯Ό μ°Ύμ μ μμ΅λλ€", | |
| status_code=status.HTTP_404_NOT_FOUND | |
| ) | |
| def conflict_error( | |
| message: str, | |
| code: str = "CONFLICT" | |
| ) -> HTTPException: | |
| """409 Conflict μλ¬""" | |
| return create_error_response( | |
| code=code, | |
| message=message, | |
| status_code=status.HTTP_409_CONFLICT | |
| ) | |
| def rate_limit_error( | |
| retry_after: int = 60, | |
| code: str = "RATE_LIMIT_EXCEEDED" | |
| ) -> HTTPException: | |
| """429 Too Many Requests μλ¬""" | |
| return create_error_response( | |
| code=code, | |
| message="μμ² νλλ₯Ό μ΄κ³Όνμ΅λλ€. μ μ ν λ€μ μλν΄μ£ΌμΈμ.", | |
| status_code=status.HTTP_429_TOO_MANY_REQUESTS, | |
| details={"retry_after": retry_after} | |
| ) | |
| def internal_server_error( | |
| message: str = "μλ² λ΄λΆ μ€λ₯κ° λ°μνμ΅λλ€", | |
| code: str = "INTERNAL_ERROR", | |
| details: Optional[Dict[str, Any]] = None | |
| ) -> HTTPException: | |
| """500 Internal Server Error""" | |
| return create_error_response( | |
| code=code, | |
| message=message, | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| details=details | |
| ) | |
| def service_unavailable_error( | |
| message: str = "μλΉμ€λ₯Ό μΌμμ μΌλ‘ μ¬μ©ν μ μμ΅λλ€", | |
| code: str = "SERVICE_UNAVAILABLE" | |
| ) -> HTTPException: | |
| """503 Service Unavailable μλ¬""" | |
| return create_error_response( | |
| code=code, | |
| message=message, | |
| status_code=status.HTTP_503_SERVICE_UNAVAILABLE | |
| ) | |
| # λλ©μΈλ³ μλ¬ μ½λ | |
| class ErrorCodes: | |
| """μλ¬ μ½λ μμ""" | |
| # μΈμ¦/κΆν | |
| UNAUTHORIZED = "UNAUTHORIZED" | |
| FORBIDDEN = "FORBIDDEN" | |
| TOKEN_EXPIRED = "TOKEN_EXPIRED" | |
| # ν ν° κ΄λ ¨ | |
| TOKEN_BALANCE_FAILED = "TOKEN_001" | |
| TOKEN_PRODUCT_NOT_FOUND = "TOKEN_002" | |
| TOKEN_INSUFFICIENT = "TOKEN_003" | |
| TOKEN_CHARGE_FAILED = "TOKEN_004" | |
| TOKEN_BONUS_FAILED = "TOKEN_005" | |
| PAYMENT_RECORD_FAILED = "TOKEN_006" | |
| # μ€ν 리 κ΄λ ¨ | |
| STORY_NOT_FOUND = "STORY_001" | |
| STORY_CREATE_FAILED = "STORY_002" | |
| STORY_UPDATE_FAILED = "STORY_003" | |
| # μ½μ€ κ΄λ ¨ | |
| COURSE_NOT_FOUND = "COURSE_001" | |
| COURSE_CREATE_FAILED = "COURSE_002" | |
| COURSE_GENERATION_FAILED = "COURSE_003" | |
| # μμ κ΄λ ¨ | |
| LIKE_FAILED = "SOCIAL_001" | |
| REVIEW_CREATE_FAILED = "SOCIAL_002" | |
| REVIEW_DELETE_FAILED = "SOCIAL_003" | |
| # λ°μ΄ν° κ²μ¦ | |
| VALIDATION_ERROR = "VALIDATION_ERROR" | |
| INVALID_UUID = "INVALID_UUID" | |
| INVALID_COORDINATES = "INVALID_COORDINATES" | |
| # μΌλ° | |
| NOT_FOUND = "NOT_FOUND" | |
| CONFLICT = "CONFLICT" | |
| BAD_REQUEST = "BAD_REQUEST" | |
| RATE_LIMIT_EXCEEDED = "RATE_LIMIT_EXCEEDED" | |
| INTERNAL_ERROR = "INTERNAL_ERROR" | |
| SERVICE_UNAVAILABLE = "SERVICE_UNAVAILABLE" | |