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;
This commit is contained in:
Richard K 2018-11-12 13:11:41 -02:00 committed by Stephen Sadowski
parent 6ce88ab5a4
commit c8b0e7f2a7
3 changed files with 65 additions and 3 deletions

View File

@ -85,7 +85,7 @@ class Request(dict):
self.transport = transport self.transport = transport
# Init but do not inhale # Init but do not inhale
self.body = [] self.body_init()
self.parsed_json = None self.parsed_json = None
self.parsed_form = None self.parsed_form = None
self.parsed_files = None self.parsed_files = None
@ -106,6 +106,15 @@ class Request(dict):
return True return True
return False 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 @property
def json(self): def json(self):
if self.parsed_json is None: if self.parsed_json is None:

View File

@ -300,7 +300,7 @@ class HttpProtocol(asyncio.Protocol):
self.request.stream.put(body) self.request.stream.put(body)
) )
return return
self.request.body.append(body) self.request.body_push(body)
def on_message_complete(self): def on_message_complete(self):
# Entire request (headers and whole body) is received. # Entire request (headers and whole body) is received.
@ -313,7 +313,7 @@ class HttpProtocol(asyncio.Protocol):
self.request.stream.put(None) self.request.stream.put(None)
) )
return return
self.request.body = b"".join(self.request.body) self.request.body_finish()
self.execute_request_handler() self.execute_request_handler()
def execute_request_handler(self): def execute_request_handler(self):

View File

@ -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