Skip to content

Commit cc679a6

Browse files
authored
fix outbound request body streaming (spinframework#103)
There was a subtle issue in `spin_sdk.http.send_async` which caused deadlock when sending a request to a server that waits for the full request body before sending any part of a response. Specifically, we must close the `Sink` as soon as we've written the whole body in order to communicate that there will be no further bytes. Previously, we only closed the `Sink` after we'd started receiving the response, which can lead to deadlock. This also bumps the package version to 3.2.0 and makes a minor README.md correction. Signed-off-by: Joel Dice <joel.dice@fermyon.com>
1 parent d981b88 commit cc679a6

File tree

3 files changed

+8
-7
lines changed

3 files changed

+8
-7
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,13 @@ Finally, you can test your app using e.g. `curl` in another terminal:
8080
curl -i http://127.0.0.1:3000
8181
```
8282

83-
If all goes well, you should see:
83+
If all goes well, you should see something like:
8484

8585
```
8686
HTTP/1.1 200 OK
8787
content-type: text/plain
88-
transfer-encoding: chunked
89-
date: Tue, 09 Jan 2024 18:26:52 GMT
88+
content-length: 18
89+
date: Thu, 11 Apr 2024 17:42:31 GMT
9090
9191
Hello from Python!
9292
```

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "spin-sdk"
7-
version = "3.1.0"
7+
version = "3.2.0"
88
description = "Experimental SDK for Spin and Componentize-Py"
99
readme = "README.md"
1010
license = { file = "LICENSE" }

src/spin_sdk/http/__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,11 +184,9 @@ async def send_async(request: Request) -> Response:
184184
sink = Sink(outgoing_request.body())
185185
incoming_response: IncomingResponse = (await asyncio.gather(
186186
poll_loop.send(outgoing_request),
187-
sink.send(outgoing_body)
187+
send_and_close(sink, outgoing_body)
188188
))[0]
189189

190-
sink.close()
191-
192190
response_body = Stream(incoming_response.consume())
193191
body = bytearray()
194192
while True:
@@ -207,3 +205,6 @@ async def send_async(request: Request) -> Response:
207205
else:
208206
body += chunk
209207

208+
async def send_and_close(sink: Sink, data: bytes):
209+
await sink.send(data)
210+
sink.close()

0 commit comments

Comments
 (0)