From ee9bb8df9ce1536c912e15421a4f4ec726874c27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Hurtado?= Date: Thu, 14 Nov 2019 15:05:19 +0100 Subject: [PATCH] New error handling in poc and features --- poc/bin/kapow | 25 +++++++++++-------- .../control/append/error_malformed.feature | 8 +++++- .../append/error_unprocessable.feature | 16 ++++++++++-- .../control/delete/error_notfound.feature | 8 +++++- .../control/get/error_notfound.feature | 8 +++++- .../control/insert/error_malformed.feature | 8 +++++- .../insert/error_unprocessable.feature | 8 +++++- .../handler/error_handleridnotfound.feature | 8 +++++- .../handler/error_invalidresource.feature | 8 +++++- .../data/handler/error_itemnotfound.feature | 8 +++++- spec/test/features/steps/steps.py | 10 ++++++++ 11 files changed, 95 insertions(+), 20 deletions(-) diff --git a/poc/bin/kapow b/poc/bin/kapow index e9d6e66..cccb574 100755 --- a/poc/bin/kapow +++ b/poc/bin/kapow @@ -178,14 +178,14 @@ async def get_field(request): try: connection = CONNECTIONS[id] except KeyError: - response = web.Response(status=404, reason="Handler ID Not Found") + response = web.json_response(data=error_body("Handler ID Not Found"), status=404, reason="Not Found") else: try: content = await connection.get(field) except ValueError: - return web.Response(status=400, reason="Invalid Resource Path") + return web.json_response(data=error_body("Invalid Resource Path"), status=400, reason="Bad Request") except KeyError: - return web.Response(status=404, reason="Resource Item Not Found") + return web.json_response(data=error_body("Resource Item Not Found"), status=404, reason="Not Found") if isinstance(content, StreamReader): response = web.StreamResponse(status=200, reason="OK") @@ -210,8 +210,10 @@ async def set_field(request): try: connection = CONNECTIONS[id] + except ValueError: + return web.json_response(data=error_body("Invalid Resource Path"), status=400, reason="Bad Request") except KeyError: - response = web.Response(status=404, reason="Handler ID Not Found") + response = web.json_response(data=error_body("Handler ID Not Found"), status=404, reason="Not Found") else: try: await connection.set(field, request.content) @@ -275,6 +277,9 @@ def handle_route(entrypoint, command): ######################################################################## +def error_body(reason): + return {"reason": reason} + def get_routes(app): async def _get_routes(request): """Return the list of registered routes.""" @@ -302,7 +307,7 @@ def get_route(app): "entrypoint": r.entrypoint, "command": r.command}) else: - return web.Response(status=404, reason="Not Found") + return web.json_response(data=error_body("Route Not Found"), status=404, reason="Not Found") return _get_route @@ -312,7 +317,7 @@ def insert_route(app): try: content = await request.json() except ValueError: - return web.Response(status=400, reason="Malformed JSON") + return web.json_response(data=error_body("Malformed JSON"), status=400, reason="Bad Request") try: index = int(content["index"]) @@ -330,7 +335,7 @@ def insert_route(app): + [route] + app["user_routes"][index:])) except (InvalidRouteError, KeyError, AssertionError, ValueError) as exc: - return web.Response(status=422, reason="Invalid Route") + return web.json_response(data=error_body("Invalid Route"), status=422, reason="Unprocessable Entity") else: app["user_routes"].insert(index, route) return web.json_response({"id": route.id, @@ -348,7 +353,7 @@ def append_route(app): try: content = await request.json() except ValueError as exc: - return web.Response(status=400, reason="Malformed JSON") + return web.json_response(data=error_body("Malformed JSON"), status=400, reason="Bad Request") try: method = content.get("method", "GET") @@ -362,7 +367,7 @@ def append_route(app): handler=handle_route(entrypoint, command)) app.change_routes(app["user_routes"] + [route]) except (InvalidRouteError, KeyError) as exc: - return web.Response(status=422, reason="Invalid Route") + return web.json_response(data=error_body("Invalid Route"), status=422, reason="Unprocessable Entity") else: app["user_routes"].append(route) return web.json_response({"id": route.id, @@ -381,7 +386,7 @@ def delete_route(app): id = request.match_info["id"] routes = [r for r in app["user_routes"] if r.id != id] if len(routes) == len(app["user_routes"]): - return web.Response(status=404, reason="Not Found") + return web.json_response(data=error_body("Route Not Found"), status=404, reason="Not Found") else: app.change_routes(routes) app["user_routes"] = routes diff --git a/spec/test/features/control/append/error_malformed.feature b/spec/test/features/control/append/error_malformed.feature index e64414d..493375c 100644 --- a/spec/test/features/control/append/error_malformed.feature +++ b/spec/test/features/control/append/error_malformed.feature @@ -28,4 +28,10 @@ Feature: Kapow! server reject append requests with malformed JSON bodies. Hi! I am an invalid JSON document. """ Then I get 400 as response code - And I get "Malformed JSON" as response reason phrase + And the response header "Content-Type" contains "application/json" + And I get the following response body: + """ + { + "reason": "Malformed JSON" + } + """ diff --git a/spec/test/features/control/append/error_unprocessable.feature b/spec/test/features/control/append/error_unprocessable.feature index 1a21b46..06c2a0d 100644 --- a/spec/test/features/control/append/error_unprocessable.feature +++ b/spec/test/features/control/append/error_unprocessable.feature @@ -31,7 +31,13 @@ Feature: Kapow! server rejects requests with semantic errors. } """ Then I get 422 as response code - And I get "Invalid Route" as response reason phrase + And the response header "Content-Type" contains "application/json" + And I get the following response body: + """ + { + "reason": "Invalid Route" + } + """ Scenario: Error because bad route format. If a request contains an invalid expression in the @@ -48,4 +54,10 @@ Feature: Kapow! server rejects requests with semantic errors. } """ Then I get 422 as response code - And I get "Invalid Route" as response reason phrase + And the response header "Content-Type" contains "application/json" + And I get the following response body: + """ + { + "reason": "Invalid Route" + } + """ diff --git a/spec/test/features/control/delete/error_notfound.feature b/spec/test/features/control/delete/error_notfound.feature index d70292a..18d2a90 100644 --- a/spec/test/features/control/delete/error_notfound.feature +++ b/spec/test/features/control/delete/error_notfound.feature @@ -24,4 +24,10 @@ Feature: Fail to delete a route in Kapow! server. Given I have a just started Kapow! server When I delete the route with id "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx" Then I get 404 as response code - And I get "Not Found" as response reason phrase + And the response header "Content-Type" contains "application/json" + And I get the following response body: + """ + { + "reason": "Route Not Found" + } + """ diff --git a/spec/test/features/control/get/error_notfound.feature b/spec/test/features/control/get/error_notfound.feature index 69e1e31..dfdb951 100644 --- a/spec/test/features/control/get/error_notfound.feature +++ b/spec/test/features/control/get/error_notfound.feature @@ -24,4 +24,10 @@ Feature: Fail to retrieve route details in Kapow! server. Given I have a just started Kapow! server When I get the route with id "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx" Then I get 404 as response code - And I get "Not Found" as response reason phrase + And the response header "Content-Type" contains "application/json" + And I get the following response body: + """ + { + "reason": "Route Not Found" + } + """ diff --git a/spec/test/features/control/insert/error_malformed.feature b/spec/test/features/control/insert/error_malformed.feature index d2453db..20596bc 100644 --- a/spec/test/features/control/insert/error_malformed.feature +++ b/spec/test/features/control/insert/error_malformed.feature @@ -37,4 +37,10 @@ Feature: Kapow! server rejects insertion requests with malformed JSON bodies. } """ Then I get 400 as response code - And I get "Malformed JSON" as response reason phrase + And the response header "Content-Type" contains "application/json" + And I get the following response body: + """ + { + "reason": "Malformed JSON" + } + """ diff --git a/spec/test/features/control/insert/error_unprocessable.feature b/spec/test/features/control/insert/error_unprocessable.feature index 04bc4a0..18468da 100644 --- a/spec/test/features/control/insert/error_unprocessable.feature +++ b/spec/test/features/control/insert/error_unprocessable.feature @@ -67,4 +67,10 @@ Feature: Kapow! server rejects insertion requests with semantic errors. } """ Then I get 422 as response code - And I get "Invalid Route" as response reason phrase + And the response header "Content-Type" contains "application/json" + And I get the following response body: + """ + { + "reason": "Invalid Route" + } + """ diff --git a/spec/test/features/data/handler/error_handleridnotfound.feature b/spec/test/features/data/handler/error_handleridnotfound.feature index 34b13f2..464891e 100644 --- a/spec/test/features/data/handler/error_handleridnotfound.feature +++ b/spec/test/features/data/handler/error_handleridnotfound.feature @@ -25,4 +25,10 @@ Feature: Fail to retrieve resources from nonexistent handler in Kapow! server. Given I have a running Kapow! server When I get the resource "/request/path" for the handler with id "XXXXXXXXXX" Then I get 404 as response code - And I get "Handler ID Not Found" as response reason phrase + And the response header "Content-Type" contains "application/json" + And I get the following response body: + """ + { + "reason": "Handler ID Not Found" + } + """ diff --git a/spec/test/features/data/handler/error_invalidresource.feature b/spec/test/features/data/handler/error_invalidresource.feature index 73dcc94..fc911f1 100644 --- a/spec/test/features/data/handler/error_invalidresource.feature +++ b/spec/test/features/data/handler/error_invalidresource.feature @@ -27,4 +27,10 @@ Feature: Fail to retrieve an invalid resource for a handler in Kapow! server. When I send a request to the testing route "/foo" And I get the resource "/invented/path" Then I get 400 as response code - And I get "Invalid Resource Path" as response reason phrase + And the response header "Content-Type" contains "application/json" + And I get the following response body: + """ + { + "reason": "Invalid Resource Path" + } + """ diff --git a/spec/test/features/data/handler/error_itemnotfound.feature b/spec/test/features/data/handler/error_itemnotfound.feature index 887446a..16dd246 100644 --- a/spec/test/features/data/handler/error_itemnotfound.feature +++ b/spec/test/features/data/handler/error_itemnotfound.feature @@ -28,4 +28,10 @@ Feature: Fail to retrieve nonexistent resource items in Kapow! server. When I send a request to the testing route "/foo" And I get the resource "/request/params/meloinvento" Then I get 404 as response code - And I get "Resource Item Not Found" as response reason phrase + And the response header "Content-Type" contains "application/json" + And I get the following response body: + """ + { + "reason": "Resource Item Not Found" + } + """ diff --git a/spec/test/features/steps/steps.py b/spec/test/features/steps/steps.py index 6e04527..39d987a 100644 --- a/spec/test/features/steps/steps.py +++ b/spec/test/features/steps/steps.py @@ -185,6 +185,16 @@ def step_impl(context, code): assert context.testing_response.status_code == int(code), f"Got {context.testing_response.status_code} instead" +@then('the response header {header_name} contains {value}') +def step_impl(context, header_name, value): + assert context.response.headers.get(header_name) == value, f"Got {context.response.headers.get(header_name)} instead" + + +@then('the testing response header {header_name} contains {value}') +def step_impl(context, header_name, value): + assert context.testing_response.headers.get(header_name) == value, f"Got {context.testing_response.headers.get(header_name)} instead" + + @then('I get "{reason}" as response reason phrase') def step_impl(context, reason): assert context.response.reason == reason, f"Got {context.response.reason} instead"