From c8b0e7f2a7f0d73424a68716b8dd6d11fa170fd5 Mon Sep 17 00:00:00 2001 From: Richard K Date: Mon, 12 Nov 2018 13:11:41 -0200 Subject: [PATCH] Created methods to append and finish body content on Request (#1379) * created methods to append and finish body content on request.py so the underlying body instance can have certain flexibility; modified server.py to reflect these changes * - made some adjustments (including the Request.body_init method) as requested by @ahopkins; - created a new test with a custom Request class implementation of the flexibility provided by the new methods; --- sanic/request.py | 11 +++++++- sanic/server.py | 4 +-- tests/test_custom_request.py | 53 ++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 tests/test_custom_request.py diff --git a/sanic/request.py b/sanic/request.py index 013a27ea..e775596a 100644 --- a/sanic/request.py +++ b/sanic/request.py @@ -85,7 +85,7 @@ class Request(dict): self.transport = transport # Init but do not inhale - self.body = [] + self.body_init() self.parsed_json = None self.parsed_form = None self.parsed_files = None @@ -106,6 +106,15 @@ class Request(dict): return True return False + def body_init(self): + self.body = [] + + def body_push(self, data): + self.body.append(data) + + def body_finish(self): + self.body = b"".join(self.body) + @property def json(self): if self.parsed_json is None: diff --git a/sanic/server.py b/sanic/server.py index 0d0bf29c..dc197941 100644 --- a/sanic/server.py +++ b/sanic/server.py @@ -300,7 +300,7 @@ class HttpProtocol(asyncio.Protocol): self.request.stream.put(body) ) return - self.request.body.append(body) + self.request.body_push(body) def on_message_complete(self): # Entire request (headers and whole body) is received. @@ -313,7 +313,7 @@ class HttpProtocol(asyncio.Protocol): self.request.stream.put(None) ) return - self.request.body = b"".join(self.request.body) + self.request.body_finish() self.execute_request_handler() def execute_request_handler(self): diff --git a/tests/test_custom_request.py b/tests/test_custom_request.py new file mode 100644 index 00000000..d0ae48e7 --- /dev/null +++ b/tests/test_custom_request.py @@ -0,0 +1,53 @@ +from io import BytesIO + +from sanic import Sanic +from sanic.request import Request +from sanic.response import json_dumps, text + + +class CustomRequest(Request): + __slots__ = ("body_buffer",) + + def body_init(self): + self.body_buffer = BytesIO() + + def body_push(self, data): + self.body_buffer.write(data) + + def body_finish(self): + self.body = self.body_buffer.getvalue() + self.body_buffer.close() + + +def test_custom_request(): + app = Sanic(request_class=CustomRequest) + + @app.route("/post", methods=["POST"]) + async def post_handler(request): + return text("OK") + + @app.route("/get") + async def get_handler(request): + return text("OK") + + payload = {"test": "OK"} + headers = {"content-type": "application/json"} + + request, response = app.test_client.post( + "/post", data=json_dumps(payload), headers=headers + ) + + assert isinstance(request.body_buffer, BytesIO) + assert request.body_buffer.closed + assert request.body == b'{"test":"OK"}' + assert request.json.get("test") == "OK" + assert response.text == "OK" + assert response.status == 200 + + request, response = app.test_client.get("/get") + + assert isinstance(request.body_buffer, BytesIO) + assert request.body_buffer.closed + assert request.body == b"" + assert response.text == "OK" + assert response.status == 200