Found on the live server (3 MB JSON to /api/auth/login answered 500). Django raises RequestDataTooBig for bodies over DATA_UPLOAD_MAX_MEMORY_SIZE and would answer 400, but our DRF exception handler turned every unknown exception into 500 + logger.exception, so each large request also wrote a full ERROR traceback. Other SuspiciousOperation subclasses now get Django's 400 as well. Tested: 2 tests (the 413 one fails without the change). Verified on the server after deploy. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
45 lines
2.3 KiB
Python
45 lines
2.3 KiB
Python
"""
|
||
هندلرِ سفارشیِ exception برای DRF: هندلرِ پیشفرض فقط APIException/Http404/
|
||
PermissionDenied رو میشناسه؛ برای بقیه None برمیگردونه و exception خام تا
|
||
مدیریتِ خطای جنگو بالا میره که (DEBUG=False) یه صفحهی HTML عمومی میده، نه
|
||
JSON. این هندلر اون حالت رو با traceback کامل لاگ میکنه و یه پاسخِ JSON
|
||
ژنریکِ ۵۰۰ برمیگردونه.
|
||
"""
|
||
import logging
|
||
|
||
from django.core.exceptions import RequestDataTooBig, SuspiciousOperation
|
||
from rest_framework.response import Response
|
||
from rest_framework.views import exception_handler as drf_exception_handler
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
def custom_exception_handler(exc, context):
|
||
response = drf_exception_handler(exc, context)
|
||
if response is not None:
|
||
return response
|
||
|
||
request = context.get('request')
|
||
path = getattr(request, 'path', '')
|
||
|
||
# بدنهی بزرگتر از DATA_UPLOAD_MAX_MEMORY_SIZE (≈ ۲٫۵ مگابایت): Django خودش این را ۴۰۰ میکند، ولی
|
||
# چون DRF آن را نمیشناسد پیشتر اینجا «۵۰۰ + ERRORِ لاگ با traceback» میشد و هر درخواستِ بزرگ لاگ را پر
|
||
# میکرد (۲۰۲۶-۱۰-۰۷ روی سرورِ زنده دیده شد). باقیِ SuspiciousOperationها هم همان ۴۰۰ِ Django را میگیرند.
|
||
if isinstance(exc, RequestDataTooBig):
|
||
logger.warning('request_too_large path=%s', path)
|
||
return Response({'detail': 'حجمِ درخواست بیش از حدِ مجاز است.'}, status=413)
|
||
if isinstance(exc, SuspiciousOperation):
|
||
logger.warning('suspicious_operation path=%s type=%s', path, type(exc).__name__)
|
||
return Response({'detail': 'درخواستِ نامعتبر.'}, status=400)
|
||
|
||
user = getattr(request, 'user', None)
|
||
user_id = user.id if getattr(user, 'is_authenticated', False) else None
|
||
logger.exception(
|
||
'unhandled_exception path=%s user_id=%s',
|
||
path, user_id,
|
||
)
|
||
return Response(
|
||
{'detail': 'خطای غیرمنتظرهای رخ داد؛ لطفاً بعداً دوباره تلاش کنید.'},
|
||
status=500,
|
||
)
|