Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d088089
moved Request _form, _body, and _json to scope
nikordaris May 12, 2020
9c57988
Merge branch 'master' into request-body-cache
nikordaris Aug 27, 2020
7d5f379
Merge branch 'master' into request-body-cache
nikordaris Sep 28, 2020
bd5940e
Merge branch 'master' into request-body-cache
nikordaris Feb 19, 2021
e47a9ba
Merge branch 'master' into request-body-cache
nikordaris May 7, 2021
6a99771
Merge branch 'master' into request-body-cache
graingert Jul 7, 2021
f536e5c
Merge branch 'master' into request-body-cache
graingert Aug 13, 2021
dbf73be
Merge branch 'master' into request-body-cache
Kludex Sep 26, 2021
e9d830b
Merge branch 'master' into request-body-cache
nikordaris Jan 30, 2022
8efc924
Merge branch 'master' into request-body-cache
nikordaris Jan 31, 2022
41a07ee
removed json scope. moved cached body and form to properties to clean…
nikordaris Jan 31, 2022
3b72b77
reverted unnecessary change to body stream iterator
nikordaris Jan 31, 2022
dfeb14f
replaced body and form cache with raw stream cache
nikordaris Jan 31, 2022
febcbc9
moved scope stream to extensions
nikordaris Jan 31, 2022
196d8db
fixed linting and coverage
nikordaris Jan 31, 2022
16f0fcf
reverted stream caching to prevent large streams exhausting memory
nikordaris Jan 31, 2022
d8dc80d
renamed private stream cache wrapper
nikordaris Jan 31, 2022
57dfa2f
Merge branch 'master' into request-body-cache
nikordaris Jan 31, 2022
276a432
Merge branch 'master' into request-body-cache
nikordaris Feb 1, 2022
60d2947
Merge branch 'master' into request-body-cache
adriangb Feb 2, 2022
eb86ebb
Merge branch 'master' into request-body-cache
nikordaris Feb 3, 2022
992c70c
Merge branch 'master' into request-body-cache
nikordaris Feb 9, 2022
95e5b37
Merge branch 'master' into request-body-cache
adriangb Feb 14, 2022
7c830d4
Merge branch 'master' into request-body-cache
adriangb Feb 14, 2022
c73a078
Apply suggestions from code review
nikordaris Feb 14, 2022
510db9a
reverted Request form caching
nikordaris Feb 14, 2022
6b7125c
Merge branch 'request-body-cache' of github.com:nikordaris/starlette …
nikordaris Feb 14, 2022
7b08db9
Merge branch 'master' into request-body-cache
adriangb Feb 15, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 32 additions & 13 deletions starlette/requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,10 +205,33 @@ def method(self) -> str:
def receive(self) -> Receive:
return self._receive

@property
def _stream(self) -> typing.List[bytes]:
try:
return self.scope["extensions"]["starlette"]["stream"]
except KeyError:
raise AttributeError("_stream")

@_stream.setter
def _stream(self, chunks: typing.List[bytes]) -> None:
if "starlette" not in self.scope["extensions"]:
self.scope["extensions"]["starlette"] = {}
self.scope["extensions"]["starlette"]["stream"] = chunks

async def _cache_stream(self) -> typing.AsyncGenerator[bytes, None]:
_stream: typing.List[bytes] = []

async for chunk in self.stream():
_stream.append(chunk)
yield chunk

if not hasattr(self, "_stream"):
self._stream = _stream

async def stream(self) -> typing.AsyncGenerator[bytes, None]:
if hasattr(self, "_body"):
yield self._body
yield b""
if hasattr(self, "_stream"):
for chunk in self._stream:
yield chunk
return

if self._stream_consumed:
Expand All @@ -229,18 +252,14 @@ async def stream(self) -> typing.AsyncGenerator[bytes, None]:
yield b""

async def body(self) -> bytes:
if not hasattr(self, "_body"):
chunks = []
async for chunk in self.stream():
chunks.append(chunk)
self._body = b"".join(chunks)
return self._body
chunks = []
async for chunk in self._cache_stream():
chunks.append(chunk)
return b"".join(chunks)

async def json(self) -> typing.Any:
if not hasattr(self, "_json"):
body = await self.body()
self._json = json.loads(body)
return self._json
body = await self.body()
return json.loads(body)

async def form(self) -> FormData:
if not hasattr(self, "_form"):
Expand Down
15 changes: 15 additions & 0 deletions tests/test_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,21 @@ async def app(scope, receive, send):
assert response.json() == {"body": "<stream consumed>", "stream": "abc"}


def test_request_body_then_request_body(test_client_factory):
async def app(scope, receive, send):
request = Request(scope, receive)
body = await request.body()
request2 = Request(scope, request.receive)
body2 = await request2.body()
response = JSONResponse({"body": body.decode(), "body2": body2.decode()})
await response(scope, receive, send)

client = test_client_factory(app)

response = client.post("/", data="abc")
assert response.json() == {"body": "abc", "body2": "abc"}


def test_request_json(test_client_factory):
async def app(scope, receive, send):
request = Request(scope, receive)
Expand Down