diff --git a/swh/deposit/exception.py b/swh/deposit/exception.py index 99fcf653..cdd1f7d0 100644 --- a/swh/deposit/exception.py +++ b/swh/deposit/exception.py @@ -1,34 +1,38 @@ # Copyright (C) 2020 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information from typing import Dict, Optional from rest_framework.exceptions import APIException -from rest_framework.response import Response from rest_framework.views import exception_handler +from django.http import HttpResponse from django.db.utils import OperationalError -def custom_exception_handler(exc: APIException, context: Dict) -> Optional[Response]: +def custom_exception_handler( + exc: APIException, context: Dict +) -> Optional[HttpResponse]: """Custom deposit exception handler to ensure consistent xml output """ # drf's default exception handler first, to get the standard error response response = exception_handler(exc, context) if isinstance(exc, OperationalError): status = "Database backend maintenance" detail = "Service temporarily unavailable, try again later." data = f""" {status} {detail} -""" - return Response(data, status=503, content_type="application/xml") +""".encode( + "utf-8" + ) + return HttpResponse(data, status=503, content_type="application/xml") return response diff --git a/swh/deposit/tests/api/test_exception.py b/swh/deposit/tests/api/test_exception.py index 91272cfc..0d71926b 100644 --- a/swh/deposit/tests/api/test_exception.py +++ b/swh/deposit/tests/api/test_exception.py @@ -1,54 +1,53 @@ # Copyright (C) 2020 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information from swh.deposit.exception import custom_exception_handler from rest_framework.exceptions import APIException from rest_framework.response import Response from django.db.utils import OperationalError def test_custom_exception_handler_operational_error(mocker): """Operation error are translated to service unavailable """ fake_exception = OperationalError("Fake internal error", 503) response = custom_exception_handler(fake_exception, {}) assert response is not None - assert response.content_type == "application/xml" assert response.status_code == 503 status = "Database backend maintenance" detail = "Service temporarily unavailable, try again later." assert ( - response.data + response.content.decode("utf-8") == f""" {status} {detail} """ ) def test_custom_exception_handler_default_behavior_maintained(mocker): """Other internal errors are transmitted as is """ fake_exception = APIException("Fake internal error", 500) fake_response = Response( exception=fake_exception, status=fake_exception.status_code ) mock_exception_handler = mocker.patch("swh.deposit.exception.exception_handler") mock_exception_handler.return_value = fake_response response = custom_exception_handler(fake_exception, {}) assert response is not None assert response == fake_response