Skip to content

Commit a0d8c71

Browse files
committed
memorising of web.Request read, text, json
1 parent f492f86 commit a0d8c71

File tree

3 files changed

+36
-22
lines changed

3 files changed

+36
-22
lines changed

aiohttp/web.py

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,10 @@ def __init__(self, app, message, payload, transport, reader, writer, *,
172172
self._payload = payload
173173
self._cookies = None
174174

175+
self._read_bytes = None
176+
self._text = None
177+
self._json = None
178+
175179
@property
176180
def method(self):
177181
"""Read only property for getting HTTP method.
@@ -300,26 +304,32 @@ def read(self):
300304
301305
Returns bytes object with full request content.
302306
"""
303-
body = bytearray()
304-
while True:
305-
chunk = yield from self._payload.readany()
306-
body.extend(chunk)
307-
if chunk is EOF_MARKER:
308-
break
309-
return bytes(body)
307+
if self._read_bytes is None:
308+
body = bytearray()
309+
while True:
310+
chunk = yield from self._payload.readany()
311+
body.extend(chunk)
312+
if chunk is EOF_MARKER:
313+
break
314+
self._read_bytes = bytes(body)
315+
return self._read_bytes
310316

311317
@asyncio.coroutine
312318
def text(self):
313319
"""Return BODY as text using encoding from .charset."""
314-
bytes_body = yield from self.read()
315-
encoding = self.charset or 'utf-8'
316-
return bytes_body.decode(encoding)
320+
if self._text is None:
321+
bytes_body = yield from self.read()
322+
encoding = self.charset or 'utf-8'
323+
self._text = bytes_body.decode(encoding)
324+
return self._text
317325

318326
@asyncio.coroutine
319327
def json(self, *, loader=json.loads):
320328
"""Return BODY as JSON."""
321-
body = yield from self.text()
322-
return loader(body)
329+
if self._json is None:
330+
body = yield from self.text()
331+
self._json = loader(body)
332+
return self._json
323333

324334
@asyncio.coroutine
325335
def post(self):

docs/web_reference.rst

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,10 @@ first positional parameter.
173173

174174
The method is a :ref:`coroutine <coroutine>`.
175175

176-
.. warning::
176+
.. note::
177177

178-
The method doesn't store read data internally, subsequent
179-
:meth:`~Request.read` call will return empty bytes ``b''``.
178+
The method **does** store read data internally, subsequent
179+
:meth:`~Request.read` call will return the same value.
180180

181181
.. method:: text()
182182

@@ -187,10 +187,10 @@ first positional parameter.
187187

188188
The method is a :ref:`coroutine <coroutine>`.
189189

190-
.. warning::
190+
.. note::
191191

192-
The method doesn't store read data internally, subsequent
193-
:meth:`~Request.text` call will return empty string ``''``.
192+
The method **does** store read data internally, subsequent
193+
:meth:`~Request.text` call will return the same value.
194194

195195
.. method:: json(*, loader=json.loads)
196196

@@ -208,10 +208,10 @@ first positional parameter.
208208
and returns :class:`dict` with parsed
209209
JSON (:func:`json.loads` by default).
210210

211-
.. warning::
211+
.. note::
212212

213-
The method doesn't store read data internally, subsequent
214-
:meth:`~Request.json` call will raise an exception.
213+
The method **does** store read data internally, subsequent
214+
:meth:`~Request.json` call will return the same value.
215215

216216
.. method:: post()
217217

@@ -226,7 +226,7 @@ first positional parameter.
226226
*application/x-www-form-urlencoded* or *multipart/form-data*
227227
returns empty multidict.
228228

229-
.. warning::
229+
.. note::
230230

231231
The method **does** store read data internally, subsequent
232232
:meth:`~Request.post` call will return the same value.

tests/test_web_functional.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ def test_post_text(self):
8080
def handler(request):
8181
data = yield from request.text()
8282
self.assertEqual('русский', data)
83+
data2 = yield from request.text()
84+
self.assertEqual(data, data2)
8385
return web.Response(text=data)
8486

8587
@asyncio.coroutine
@@ -101,6 +103,8 @@ def test_post_json(self):
101103
def handler(request):
102104
data = yield from request.json()
103105
self.assertEqual(dct, data)
106+
data2 = yield from request.json()
107+
self.assertEqual(data, data2)
104108
resp = web.Response()
105109
resp.content_type = 'application/json'
106110
resp.body = json.dumps(data).encode('utf8')

0 commit comments

Comments
 (0)