diff --git a/flask_rest_jsonapi/decorators.py b/flask_rest_jsonapi/decorators.py index 28d645c..22f910b 100644 --- a/flask_rest_jsonapi/decorators.py +++ b/flask_rest_jsonapi/decorators.py @@ -5,7 +5,7 @@ from flask import request, make_response, jsonify, current_app -from flask_rest_jsonapi.errors import jsonapi_errors +from flask_rest_jsonapi.errors import jsonapi_errors, format_http_exception from flask_rest_jsonapi.exceptions import JsonApiException from flask_rest_jsonapi.utils import JSONEncoder @@ -77,6 +77,12 @@ def wrapper(*args, **kwargs): e.status, headers) except Exception as e: + api_ex = format_http_exception(e) + if api_ex: + return make_response(jsonify(jsonapi_errors([api_ex.to_dict()])), + api_ex.status, + headers) + if current_app.config['DEBUG'] is True: raise e diff --git a/flask_rest_jsonapi/errors.py b/flask_rest_jsonapi/errors.py index 66906e5..40d1ffa 100644 --- a/flask_rest_jsonapi/errors.py +++ b/flask_rest_jsonapi/errors.py @@ -1,4 +1,13 @@ """Helper to format Api errors according to jsonapi specification""" +from flask_rest_jsonapi.exceptions import BadRequest, ObjectNotFound, InvalidType, AccessDenied, Unauthorized + +STATUS_MAP = { + 400: BadRequest, + 401: Unauthorized, + 404: ObjectNotFound, + 409: InvalidType, + 403: AccessDenied, +} def jsonapi_errors(jsonapi_errors): @@ -9,3 +18,23 @@ def jsonapi_errors(jsonapi_errors): """ return {'errors': [jsonapi_error for jsonapi_error in jsonapi_errors], 'jsonapi': {'version': '1.0'}} + + +def format_http_exception(ex): + """ + try to format http exception to jsonapi 1.0 + Warning! It only works for errors with status code less than 500 + :param ex: http exception + :return: + """ + code = getattr(ex, 'code', None) + try: + status = int(code) + except TypeError: + return + + api_ex = STATUS_MAP.get(status) + if not api_ex: + return + + return api_ex(detail=getattr(ex, 'description', '')) diff --git a/flask_rest_jsonapi/exceptions.py b/flask_rest_jsonapi/exceptions.py index 8b53a94..daff71a 100644 --- a/flask_rest_jsonapi/exceptions.py +++ b/flask_rest_jsonapi/exceptions.py @@ -98,6 +98,13 @@ class InvalidType(JsonApiException): status = '409' +class Unauthorized(JsonApiException): + """Throw this error if the user is not authorized""" + + title = 'Unauthorized' + status = '401' + + class AccessDenied(JsonApiException): """Throw this error when requested resource owner doesn't match the user of the ticket"""