Skip to content

Commit

Permalink
fix error handler
Browse files Browse the repository at this point in the history
make sure Api does not eat exceptions which don't have error handler register Api.
make it plays nicer with other extensions like Flask-JWT-Extended

refs:
- vimalloc/flask-jwt-extended#86
- noirbizarre/flask-restplus#340
  • Loading branch information
mozartilize authored Aug 13, 2020
1 parent 66d884f commit cb356e3
Showing 1 changed file with 40 additions and 39 deletions.
79 changes: 40 additions & 39 deletions flask_restx/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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(
[
Expand Down

0 comments on commit cb356e3

Please sign in to comment.