diff --git a/flask_restx/api.py b/flask_restx/api.py index bda1c0c1..ebd390c6 100644 --- a/flask_restx/api.py +++ b/flask_restx/api.py @@ -14,7 +14,7 @@ from functools import wraps, partial from types import MethodType -from flask import url_for, request, current_app +from flask import url_for, request, current_app, Response from flask import make_response as original_flask_make_response from flask.helpers import _endpoint_from_view_func from flask.signals import got_request_exception @@ -651,12 +651,9 @@ def handle_error(self, e): # When propagate_exceptions is set, do not return the exception to the # client if a handler is configured for the exception. - if ( - not isinstance(e, HTTPException) - and current_app.propagate_exceptions - and not isinstance(e, tuple(self.error_handlers.keys())) + if not isinstance(e, HTTPException) and not isinstance( + e, tuple(self.error_handlers.keys()) ): - exc_type, exc_value, tb = sys.exc_info() if exc_value is e: raise @@ -695,47 +692,51 @@ def handle_error(self, e): "message": code.phrase, } - if include_message_in_response: - default_data["message"] = default_data.get("message", str(e)) - - data = getattr(e, "data", default_data) - fallback_mediatype = None + if isinstance(default_data, Response): + resp = default_data + else: + if include_message_in_response: + default_data["message"] = default_data.get("message", str(e)) + + data = getattr(e, "data", default_data) + fallback_mediatype = None + + if code >= HTTPStatus.INTERNAL_SERVER_ERROR: + exc_info = sys.exc_info() + if exc_info[1] is None: + exc_info = None + current_app.log_exception(exc_info) + + elif ( + code == HTTPStatus.NOT_FOUND + and current_app.config.get("ERROR_404_HELP", True) + and include_message_in_response + ): + data["message"] = self._help_on_404(data.get("message", None)) + + elif code == HTTPStatus.NOT_ACCEPTABLE and self.default_mediatype is None: + # if we are handling NotAcceptable (406), make sure that + # make_response uses a representation we support as the + # default mediatype (so that make_response doesn't throw + # another NotAcceptable error). + supported_mediatypes = list(self.representations.keys()) + fallback_mediatype = ( + supported_mediatypes[0] if supported_mediatypes else "text/plain" + ) - if code >= HTTPStatus.INTERNAL_SERVER_ERROR: - exc_info = sys.exc_info() - if exc_info[1] is None: - exc_info = None - current_app.log_exception(exc_info) + # Remove blacklisted headers + for header in HEADERS_BLACKLIST: + headers.pop(header, None) - elif ( - code == HTTPStatus.NOT_FOUND - and current_app.config.get("ERROR_404_HELP", True) - and include_message_in_response - ): - data["message"] = self._help_on_404(data.get("message", None)) - - elif code == HTTPStatus.NOT_ACCEPTABLE and self.default_mediatype is None: - # if we are handling NotAcceptable (406), make sure that - # make_response uses a representation we support as the - # default mediatype (so that make_response doesn't throw - # another NotAcceptable error). - supported_mediatypes = list(self.representations.keys()) - fallback_mediatype = ( - supported_mediatypes[0] if supported_mediatypes else "text/plain" + resp = self.make_response( + data, code, headers, fallback_mediatype=fallback_mediatype ) - # Remove blacklisted headers - for header in HEADERS_BLACKLIST: - headers.pop(header, None) - - resp = self.make_response( - data, code, headers, fallback_mediatype=fallback_mediatype - ) - if code == HTTPStatus.UNAUTHORIZED: resp = self.unauthorized(resp) return resp + def _help_on_404(self, message=None): rules = dict( [