FEAT: Modernized to support latest Pythons and DRF JSONAPI
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
"""Safe, JSON:API-compatible exception handling."""
|
||||
|
||||
import logging
|
||||
import uuid
|
||||
|
||||
from rest_framework.exceptions import APIException
|
||||
from rest_framework_json_api.exceptions import exception_handler as jsonapi_exception_handler
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
ERROR_ID_HEADER = "X-Error-ID"
|
||||
|
||||
|
||||
class APIConflictException(APIException):
|
||||
"""A deliberately raised, non-sensitive resource conflict."""
|
||||
|
||||
status_code = 409
|
||||
default_detail = "The request conflicts with the current resource state."
|
||||
default_code = "conflict"
|
||||
|
||||
|
||||
class InternalServerError(APIException):
|
||||
"""Sanitized representation of an unexpected server exception."""
|
||||
|
||||
status_code = 500
|
||||
default_detail = "An unexpected server error occurred."
|
||||
default_code = "internal_error"
|
||||
|
||||
|
||||
def hardened_exception_handler(exc, context):
|
||||
"""Render expected errors normally and sanitize unexpected exceptions.
|
||||
|
||||
Unexpected exception details and tracebacks are logged server-side under a
|
||||
generated error identifier. Only that opaque identifier is returned to the
|
||||
client, in a response header, so operators can correlate a report safely.
|
||||
"""
|
||||
|
||||
response = jsonapi_exception_handler(exc, context)
|
||||
if response is not None:
|
||||
return response
|
||||
|
||||
error_id = uuid.uuid4().hex
|
||||
logger.error(
|
||||
"Unhandled API exception; error_id=%s",
|
||||
error_id,
|
||||
exc_info=exc,
|
||||
)
|
||||
|
||||
response = jsonapi_exception_handler(InternalServerError(), context)
|
||||
response[ERROR_ID_HEADER] = error_id
|
||||
return response
|
||||
|
||||
|
||||
class HardenedExceptionHandlingMixin:
|
||||
"""Opt a DRF view into :func:`hardened_exception_handler`."""
|
||||
|
||||
def get_exception_handler(self):
|
||||
return hardened_exception_handler
|
||||
Reference in New Issue
Block a user