File size: 1,632 Bytes
f2fecbd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
"""Map exceptions to consistent JSON error responses."""
from __future__ import annotations

import logging

from flask import Flask, current_app, jsonify
from werkzeug.exceptions import HTTPException, RequestEntityTooLarge

from ..exceptions import AppError

logger = logging.getLogger(__name__)


def _error_body(message: str, status: int, detail: str = "", project_id: str = ""):
    body = {"message": message, "isError": True}
    # Internal details go to clients only for client errors, or when DEBUG is on.
    if detail and (status < 500 or current_app.config["SETTINGS"].debug):
        body["error"] = detail
    if project_id:
        body["project_id"] = project_id  # lets support correlate with the server logs
    return jsonify(body), status


def register_error_handlers(app: Flask) -> None:
    @app.errorhandler(AppError)
    def handle_app_error(e: AppError):
        if e.status_code >= 500:
            logger.error("Project %s failed: %s", e.project_id or "-", e.detail or e)
        return _error_body(e.public_message, e.status_code, e.detail, e.project_id)

    @app.errorhandler(RequestEntityTooLarge)
    def handle_too_large(e):
        limit = current_app.config["SETTINGS"].max_upload_mb
        return _error_body(f"❌ File too large (max {limit} MB)", 413)

    @app.errorhandler(Exception)
    def handle_unexpected(e: Exception):
        if isinstance(e, HTTPException):  # 404/405 etc. keep their normal status
            return _error_body(e.description or e.name, e.code or 500)
        logger.exception("Unhandled error")
        return _error_body("❌ Internal server error", 500, str(e))