From 29b4a2a08cbbd5c39c05049fa62bbcc6b11d6b10 Mon Sep 17 00:00:00 2001 From: Jeong YunWon Date: Fri, 9 Jun 2017 14:46:12 +0900 Subject: [PATCH 1/7] Gunicorn worker hints app weather it is being terminated For now, `Sanic.is_running` is set when the worker is started but not unset when it is about to stopped. Setting the flag for quit signal will not affect working requests, but the `Sanic.is_running` flag still can be used to support graceful termination. --- sanic/worker.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sanic/worker.py b/sanic/worker.py index d15fda41..1d3e384b 100644 --- a/sanic/worker.py +++ b/sanic/worker.py @@ -159,6 +159,7 @@ class GunicornWorker(base.Worker): def handle_quit(self, sig, frame): self.alive = False + self.app.callable.is_running = False self.cfg.worker_int(self) def handle_abort(self, sig, frame): From 4942af27dc51fdba4fbcf2e5c3190022e351feb1 Mon Sep 17 00:00:00 2001 From: Yun Xu Date: Fri, 9 Jun 2017 08:33:34 -0700 Subject: [PATCH 2/7] handle NotFound --- sanic/router.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sanic/router.py b/sanic/router.py index 2581e178..f379b095 100644 --- a/sanic/router.py +++ b/sanic/router.py @@ -351,7 +351,10 @@ class Router: :param request: Request object :return: bool """ - handler = self.get(request)[0] + try: + handler = self.get(request)[0] + except NotFound: + return False if (hasattr(handler, 'view_class') and hasattr(handler.view_class, request.method.lower())): handler = getattr(handler.view_class, request.method.lower()) From 236daf48ffde46694f7aeeeabc5681e6a238bab6 Mon Sep 17 00:00:00 2001 From: Yun Xu Date: Fri, 9 Jun 2017 08:42:48 -0700 Subject: [PATCH 3/7] add unit tests --- tests/test_request_stream.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/test_request_stream.py b/tests/test_request_stream.py index 0ceccf60..3a81a7c8 100644 --- a/tests/test_request_stream.py +++ b/tests/test_request_stream.py @@ -163,6 +163,30 @@ def test_request_stream_app(): assert response.text == data +def test_request_stream_handle_exception(): + '''for handling exceptions properly''' + + app = Sanic('test_request_stream_exception') + + @app.post('/post/', stream=True) + async def post(request, id): + assert isinstance(request.stream, asyncio.Queue) + + async def streaming(response): + while True: + body = await request.stream.get() + if body is None: + break + response.write(body.decode('utf-8')) + return stream(streaming) + + + # 404 + request, response = app.test_client.post('/in_valid_post', data=data) + assert response.status == 404 + assert response.text == 'Error: Requested URL /in_valid_post not found' + + def test_request_stream_blueprint(): '''for self.is_request_stream = True''' From 24b946e850ee05d8b9c354ed4bfeb8bc658b5339 Mon Sep 17 00:00:00 2001 From: Yun Xu Date: Fri, 9 Jun 2017 08:43:23 -0700 Subject: [PATCH 4/7] make flake8 happy --- tests/test_request_stream.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_request_stream.py b/tests/test_request_stream.py index 3a81a7c8..fdfffb77 100644 --- a/tests/test_request_stream.py +++ b/tests/test_request_stream.py @@ -180,7 +180,6 @@ def test_request_stream_handle_exception(): response.write(body.decode('utf-8')) return stream(streaming) - # 404 request, response = app.test_client.post('/in_valid_post', data=data) assert response.status == 404 From cf30ed745cd127cf3bd509344353555401e85c98 Mon Sep 17 00:00:00 2001 From: Yun Xu Date: Sat, 10 Jun 2017 09:42:48 -0700 Subject: [PATCH 5/7] also should handle InvalidUsage exception --- sanic/router.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sanic/router.py b/sanic/router.py index f379b095..691f1388 100644 --- a/sanic/router.py +++ b/sanic/router.py @@ -353,7 +353,7 @@ class Router: """ try: handler = self.get(request)[0] - except NotFound: + except (NotFound, InvalidUsage): return False if (hasattr(handler, 'view_class') and hasattr(handler.view_class, request.method.lower())): From 6a80bdafa6cab506164ca7a7fc89b66c4bea43b4 Mon Sep 17 00:00:00 2001 From: Yun Xu Date: Sat, 10 Jun 2017 09:48:30 -0700 Subject: [PATCH 6/7] add unit tests --- tests/test_request_stream.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/test_request_stream.py b/tests/test_request_stream.py index fdfffb77..4ca4e44e 100644 --- a/tests/test_request_stream.py +++ b/tests/test_request_stream.py @@ -185,6 +185,11 @@ def test_request_stream_handle_exception(): assert response.status == 404 assert response.text == 'Error: Requested URL /in_valid_post not found' + # 405 + request, response = app.test_client.get('/post/random_id', data=data) + assert response.status == 405 + assert response.text == 'Error: Method GET not allowed for URL /post/random_id' + def test_request_stream_blueprint(): '''for self.is_request_stream = True''' From acaafabc23ab0e726bba15fbeeeb9efa9c7392d6 Mon Sep 17 00:00:00 2001 From: Yun Xu Date: Sat, 10 Jun 2017 09:57:32 -0700 Subject: [PATCH 7/7] retry build