Skip to content

Commit 3acf280

Browse files
committed
fix: Move DRF custom exception handler to exceptions + support more types
1 parent 04370e8 commit 3acf280

File tree

3 files changed

+41
-17
lines changed

3 files changed

+41
-17
lines changed

twitch_hdt_ebs/exceptions.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
import logging
2+
3+
import requests
4+
from hearthsim.instrumentation.django_influxdb import write_point
15
from rest_framework import status
26
from rest_framework.exceptions import APIException
7+
from rest_framework.views import exception_handler
38

49

510
class TwitchAPITimeout(APIException):
@@ -20,3 +25,38 @@ class BadGateway(APIException):
2025
class BadTwitchResponse(BadGateway):
2126
default_detail = "Twitch returned an invalid response."
2227
default_code = "bad_twitch_response"
28+
29+
30+
def untapped_django_exception_handler(exc, context):
31+
"""A Django REST Framework "custom exception handler" for translating additional types.
32+
33+
This implementation attempts to convert upstream exception types corresponding to HTTP
34+
502 (Bad gateway) and HTTP 504 (Gateway timeout) before delegating to the default
35+
exception handler implementation.
36+
37+
See also
38+
https://www.django-rest-framework.org/api-guide/exceptions/#custom-exception-handling
39+
40+
:param exc:
41+
:param context:
42+
"""
43+
44+
if isinstance(exc, requests.Timeout):
45+
effective_exc = TwitchAPITimeout()
46+
elif (
47+
isinstance(exc, requests.ConnectionError) or
48+
isinstance(exc, requests.HTTPError)
49+
):
50+
effective_exc = BadGateway()
51+
else:
52+
effective_exc = exc
53+
54+
detail = getattr(exc, "detail", {})
55+
56+
logger = logging.getLogger("twitch_hdt_ebs")
57+
logger.error("Got exception %r, detail=%r", exc, detail)
58+
59+
if detail and isinstance(detail, dict):
60+
write_point("api_error", {"count": 1}, error=detail.get("error", "unknown"))
61+
62+
return exception_handler(effective_exc, context)

twitch_hdt_ebs/settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ def get_deployment_uuid():
138138
# Disable DRF browsable API (it requires templates to be setup)
139139
REST_FRAMEWORK = {
140140
"DEFAULT_RENDERER_CLASSES": ("rest_framework.renderers.JSONRenderer", ),
141-
"EXCEPTION_HANDLER": "twitch_hdt_ebs.views.exception_handler",
141+
"EXCEPTION_HANDLER": "twitch_hdt_ebs.utils.exceptions.untapped_django_exception_handler",
142142
}
143143

144144
# DRF CORS handling

twitch_hdt_ebs/views.py

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import base64
22
import hashlib
33
import json
4-
import logging
54
import string
65
from typing import Any, Dict, List, Optional
76

@@ -520,18 +519,3 @@ def get(self, request, user_id) -> Response:
520519
class PingView(View):
521520
def get(self, request):
522521
return HttpResponse("OK", content_type="text/plain")
523-
524-
525-
def exception_handler(exc, context):
526-
from rest_framework.views import exception_handler as original_handler
527-
528-
response = original_handler(exc, context)
529-
detail = getattr(exc, "detail", {})
530-
531-
logger = logging.getLogger("twitch_hdt_ebs")
532-
logger.error("Got exception %r, detail=%r", exc, detail)
533-
534-
if detail and isinstance(detail, dict):
535-
write_point("api_error", {"count": 1}, error=detail.get("error", "unknown"))
536-
537-
return response

0 commit comments

Comments
 (0)