Skip to content

fix error handler #200

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is propagate exceptions being removed here

Copy link
Author

@mozartilize mozartilize Aug 17, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want all exeptions if not handled by restx return to flask, therefore some extensions like flask-jwt-extended can work properly. I think the purpose of propagate_exceptions is for testing and debugging and if someone want to use it, they must be enduser, not library.

I see that restx's design is make the whole application for api only - by catch all exceptions and response to json, but what if i want the route /api to only handle api and the rest serves html?

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