Skip to content

Commit

Permalink
Attaching error handler to blueprint level instead of global. Issue j…
Browse files Browse the repository at this point in the history
  • Loading branch information
jkehler committed Oct 21, 2014
1 parent f19cde6 commit 47aaf9c
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 32 deletions.
45 changes: 38 additions & 7 deletions flask_restless/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
from collections import defaultdict

from flask import Blueprint

from werkzeug.exceptions import default_exceptions
from .views import http_exception_json_response
from werkzeug.exceptions import HTTPException
from .views import jsonify
from .views import API
from .views import FunctionAPI

Expand Down Expand Up @@ -196,7 +198,6 @@ def init_app(self, app, session=None, flask_sqlalchemy_db=None,
self.universal_preprocessors = preprocessors or {}
self.universal_postprocessors = postprocessors or {}


def create_api_blueprint(self, model, methods=READONLY_METHODS,
url_prefix='/api', collection_name=None,
allow_patch_many=False, allow_functions=False,
Expand Down Expand Up @@ -472,6 +473,40 @@ def create_api_blueprint(self, model, methods=READONLY_METHODS,
view_func=eval_api_view)
return blueprint

def add_blueprint_error_handlers(self, blueprint):
"""Applys custom error handlers to the blueprint via the
`flask.Flask.Blueprint.app_errorhandler' decorator.
A decorator is applied for each error code present in
`werkzeug.exceptions.default_exceptions`
By default werkzueg exceptions are returned in HTML format. This can
pose a problem for RESTful api's since the client will be expecting
JSON formatted responses. A decorator is applied for each error code
present in `werkzeug.exceptions.default_exceptions`. The custom
decorator will convert any exceptions raised by werkzeug into JSON
format.
"""

for code in default_exceptions.keys():
@blueprint.app_errorhandler(code)
def http_exception_json_response(ex):
""" Convert werkzeug http exceptions into a JSON response.
`ex` is an Exception raised by `werkzueg.exceptions`.
"""

response = jsonify(message=str(ex))
if isinstance(ex, HTTPException):
for header in ex.get_response().headers:
if header[0] == 'Allow':
response.headers['Allow'] = header[1]
response.status_code = (ex.code
if isinstance(ex, HTTPException)
else 500)
self.app.logger.exception(str(ex))
return response

def create_api(self, *args, **kw):
"""Creates and registers a ReSTful API blueprint on the
:class:`flask.Flask` application specified in the constructor of this
Expand All @@ -491,9 +526,5 @@ def create_api(self, *args, **kw):
"""
blueprint = self.create_api_blueprint(*args, **kw)
self.add_blueprint_error_handlers(blueprint)
self.app.register_blueprint(blueprint)
# override bulit in default exception handler to convert unhandled
# exceptions from html responses to json responses instead
for code in default_exceptions.keys():
self.app.error_handler_spec[None][code] = \
http_exception_json_response
25 changes: 0 additions & 25 deletions flask_restless/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,31 +146,6 @@ def decorator(*args, **kw):
return decorator


def http_exception_json_response(ex):
""" Convert werkzeug http exceptions into a JSON response.
`ex` is an Exception raised by `werkzueg.exceptions`.
By default werkzueg exceptions are returned in HTML format. This can
pose a problem for RestFul api's since the client will be expecting
JSON formatted responses. Werkzueg exceptions are catched by assigning
this function to `flask.Flask.error_handler_spec` with a list of error
codes. As a result all unhandled http exceptions will be converted
into a JSON format.
See http://flask.pocoo.org/docs/0.10/api/#flask.Flask.error_handler_spec
for more details.
"""
response = jsonify(message=str(ex))
if isinstance(ex, HTTPException):
for header in ex.get_response().headers:
if header[0] == 'Allow':
response.headers['Allow'] = header[1]
response.status_code = (ex.code if isinstance(ex, HTTPException) else 500)
current_app.logger.exception(str(ex))
return response


def set_headers(response, headers):
"""Sets the specified headers on the specified response.
Expand Down

0 comments on commit 47aaf9c

Please sign in to comment.