浏览代码

fix(api): rework pdns error handling, closes #265

Peter Thomassen 5 年之前
父节点
当前提交
fd36642206
共有 3 个文件被更改,包括 33 次插入15 次删除
  1. 5 0
      api/desecapi/exception_handlers.py
  2. 22 11
      api/desecapi/exceptions.py
  3. 6 4
      api/desecapi/pdns.py

+ 5 - 0
api/desecapi/exception_handlers.py

@@ -6,6 +6,8 @@ from rest_framework import status
 from rest_framework.response import Response
 from rest_framework.response import Response
 from rest_framework.views import exception_handler as drf_exception_handler
 from rest_framework.views import exception_handler as drf_exception_handler
 
 
+from desecapi.exceptions import PDNSException
+
 
 
 def exception_handler(exc, context):
 def exception_handler(exc, context):
     """
     """
@@ -44,4 +46,7 @@ def exception_handler(exc, context):
     if isinstance(exc, UnsupportedRule):
     if isinstance(exc, UnsupportedRule):
         return _perform_handling('UnsupportedRule')
         return _perform_handling('UnsupportedRule')
 
 
+    if isinstance(exc, PDNSException):
+        return _perform_handling('PDNSException')
+
     return drf_exception_handler(exc, context)
     return drf_exception_handler(exc, context)

+ 22 - 11
api/desecapi/exceptions.py

@@ -1,17 +1,28 @@
 import json
 import json
 from json import JSONDecodeError
 from json import JSONDecodeError
 
 
-from rest_framework.exceptions import APIException
+from rest_framework import status
+from rest_framework.exceptions import APIException, ValidationError
 
 
 
 
-class PDNSException(APIException):
+class RequestEntityTooLarge(APIException):
+    status_code = status.HTTP_413_REQUEST_ENTITY_TOO_LARGE
+    default_detail = 'Payload too large.'
+    default_code = 'too_large'
+
+
+class PDNSValidationError(ValidationError):
+    status_code = 422
+
+    def __init__(self, response=None):
+        try:
+            detail = json.loads(response.text)['error']
+        except JSONDecodeError:
+            detail = response.text
 
 
-    def __init__(self, response=None, detail=None, status=None):
-        self.status_code = status or response.status_code
-        if detail:
-            self.detail = detail
-        else:
-            try:
-                self.detail = json.loads(response.text)['error']
-            except (JSONDecodeError, KeyError):
-                self.detail = response.text
+        return super().__init__(detail=detail, code='invalid')
+
+
+class PDNSException(APIException):
+    def __init__(self, response=None):
+        return super().__init__(f'pdns response code: {response.status_code}, pdns response body: {response.text}')

+ 6 - 4
api/desecapi/pdns.py

@@ -5,7 +5,7 @@ import requests
 from django.conf import settings
 from django.conf import settings
 from django.core.exceptions import SuspiciousOperation
 from django.core.exceptions import SuspiciousOperation
 
 
-from desecapi.exceptions import PDNSException
+from desecapi.exceptions import PDNSException, PDNSValidationError, RequestEntityTooLarge
 
 
 NSLORD = object()
 NSLORD = object()
 NSMASTER = object()
 NSMASTER = object()
@@ -34,11 +34,13 @@ _config = {
 def _pdns_request(method, *, server, path, body=None):
 def _pdns_request(method, *, server, path, body=None):
     data = json.dumps(body) if body else None
     data = json.dumps(body) if body else None
     if data is not None and len(data) > settings.PDNS_MAX_BODY_SIZE:
     if data is not None and len(data) > settings.PDNS_MAX_BODY_SIZE:
-        raise PDNSException(detail='Payload too large', status=413)
+        raise RequestEntityTooLarge
 
 
     r = requests.request(method, _config[server]['base_url'] + path, data=data, headers=_config[server]['headers'])
     r = requests.request(method, _config[server]['base_url'] + path, data=data, headers=_config[server]['headers'])
-    if r.status_code not in range(200, 300):
-        raise PDNSException(r)
+    if r.status_code == PDNSValidationError.status_code:
+        raise PDNSValidationError(response=r)
+    elif r.status_code not in range(200, 300):
+        raise PDNSException(response=r)
 
 
     return r
     return r