diff --git a/api/util.py b/api/util.py index 10fb414be864d6056610e19cd73a37e96ad38362..19dc2490f5794bcf9cc28943ea816008f30321f6 100644 --- a/api/util.py +++ b/api/util.py @@ -204,19 +204,20 @@ def format_hash(hash_alg, hash_): return '-'.join(('v0', hash_alg, hash_)) -def create_json_http_exception_response(message, code, custom=None): +def create_json_http_exception_response(message, code, request_id, custom=None): content = { 'message': message, - 'status_code': code + 'status_code': code, + 'request_id': request_id } if custom: content.update(custom) return content -def send_json_http_exception(response, message, code, custom=None): +def send_json_http_exception(response, message, code, request_id, custom=None): response.set_status(code) - json_content = json.dumps(create_json_http_exception_response(message, code, custom)) + json_content = json.dumps(create_json_http_exception_response(message, code, request_id, custom)) response.headers['Content-Type'] = 'application/json; charset=utf-8' response.write(json_content) diff --git a/api/web/base.py b/api/web/base.py index 5abae08376fe52d95e17e5f2c03d3a44adecd959..02a6c911ce20340c69e86b2724ced5e018348965 100644 --- a/api/web/base.py +++ b/api/web/base.py @@ -328,6 +328,7 @@ class RequestHandler(webapp2.RequestHandler): For all others use a generic 500 error code and log the stack trace """ + request_id = self.request.id custom_errors = None message = str(exception) if isinstance(exception, webapp2.HTTPException): @@ -369,9 +370,9 @@ class RequestHandler(webapp2.RequestHandler): self.request.logger.error(tb) if return_json: - return util.create_json_http_exception_response(message, code, custom=custom_errors) + return util.create_json_http_exception_response(message, code, request_id, custom=custom_errors) - util.send_json_http_exception(self.response, message, code, custom=custom_errors) + util.send_json_http_exception(self.response, message, code, request_id, custom=custom_errors) def log_user_access(self, access_type, cont_name=None, cont_id=None, multifile=False): diff --git a/api/web/start.py b/api/web/start.py index ace553902220a8dae974965761bf5c6143a14bca..235afe4d31013ace5d796784e189b021046617cc 100644 --- a/api/web/start.py +++ b/api/web/start.py @@ -50,14 +50,14 @@ def dispatcher(router, request, response): response.write(json.dumps(rv, default=encoder.custom_json_serializer)) response.headers['Content-Type'] = 'application/json; charset=utf-8' except webapp2.HTTPException as e: - util.send_json_http_exception(response, str(e), e.code) + util.send_json_http_exception(response, str(e), e.code, request.id) except Exception as e: # pylint: disable=broad-except request.logger.error("Error dispatching request", exc_info=True) if config.get_item('core', 'debug'): message = traceback.format_exc() else: message = 'Internal Server Error' - util.send_json_http_exception(response, message, 500) + util.send_json_http_exception(response, message, 500, request.id) def app_factory(*_, **__): # pylint: disable=protected-access,unused-argument diff --git a/tests/integration_tests/python/test_errors.py b/tests/integration_tests/python/test_errors.py index 1e6f325abd5f3c1722b644e0c74de28ed6462773..841c09a086b3d4091eb5156dafb02a6e91efd716 100644 --- a/tests/integration_tests/python/test_errors.py +++ b/tests/integration_tests/python/test_errors.py @@ -12,3 +12,23 @@ def test_extra_param(as_admin): r = as_admin.get('/projects') assert r.ok assert not any(project['label'] == label for project in r.json()) + +def test_error_response(as_admin, as_user, as_public, data_builder): + + group = data_builder.create_group() + project = data_builder.create_project() + + # Test dao exception + r = as_admin.post('/users', json={'_id': "admin@user.com", 'firstname': "Firstname", 'lastname': "Lastname"}) + assert r.status_code == 409 + assert r.json().get('request_id') + + # Test schema exceptions + r = as_admin.post('/groups', json={'foo':'bar'}) + assert r.status_code == 400 + assert r.json().get('request_id') + + # Test Permission exception + r = as_user.put('/projects/' + project, json={'label':'Project'}) + assert r.status_code == 403 + assert r.json().get('request_id')