diff --git a/api/api.py b/api/api.py index 4c4d5b5419cfef74d0141a830e06049a691bb14c..ac06191e560804f77dedcf057526eb14d2751136 100644 --- a/api/api.py +++ b/api/api.py @@ -134,11 +134,13 @@ routes = [ def dispatcher(router, request, response): - rv = router.default_dispatcher(request, response) - if rv is not None: - response.write(json.dumps(rv, default=util.custom_json_serializer)) - response.headers['Content-Type'] = 'application/json; charset=utf-8' - + try: + rv = router.default_dispatcher(request, response) + if rv is not None: + response.write(json.dumps(rv, default=util.custom_json_serializer)) + response.headers['Content-Type'] = 'application/json; charset=utf-8' + except (webapp2.exc.HTTPNotFound, webapp2.exc.HTTPMethodNotAllowed) as e: + util.send_json_http_exception(response, str(e), e.code) def app_factory(*_, **__): # don't use config.get_item() as we don't want to require the database at startup diff --git a/api/base.py b/api/base.py index 2e3ee02d7c703b4bf67ef9a9ff0045de56859978..36056990c77aa2764a2eacdb99617aa4d7edf653 100644 --- a/api/base.py +++ b/api/base.py @@ -7,6 +7,7 @@ import requests import urlparse import jsonschema +from . import util from . import config log = config.log @@ -119,6 +120,18 @@ class RequestHandler(webapp2.RequestHandler): def get_param(self, param, default=None): return self.request.GET.get(param, default) + def handle_exception(self, exception, debug): + # Log the error. + log.error(exception) + + # If the exception is a HTTPException, use its error code. + # Otherwise use a generic 500 error code. + if isinstance(exception, webapp2.HTTPException): + code = exception.code + else: + code = 500 + util.send_json_http_exception(self.response, str(exception), code) + def dispatch(self): """dispatching and request forwarding""" site_id = config.get_item('site', 'id') @@ -183,3 +196,4 @@ class RequestHandler(webapp2.RequestHandler): json_schema = copy.deepcopy(self.json_schema) json_schema['properties'].update(updates) return json_schema + diff --git a/api/util.py b/api/util.py index 9d3bd9c997c206abcab92655d28c338e71ba0087..13e374d3bcb8d7bbd9b63e01941f85fc9372100c 100644 --- a/api/util.py +++ b/api/util.py @@ -1,4 +1,5 @@ import os +import json import pytz import uuid import datetime @@ -108,6 +109,15 @@ def custom_json_serializer(obj): return pytz.timezone('UTC').localize(obj).isoformat() raise TypeError(repr(obj) + " is not JSON serializable") +def send_json_http_exception(response, message, code): + response.set_status(code) + content = json.dumps({ + 'message': message, + 'status_code': code + }) + response.headers['Content-Type'] = 'application/json; charset=utf-8' + response.write(content) + class Enum(baseEnum.Enum): # Enum strings are prefixed by their class: "Category.classifier". # This overrides that behaviour and removes the prefix.