Skip to content

Commit 85c8668

Browse files
committed
Adds support for bytes passed to Python's Response constructor
1 parent 7bd9d97 commit 85c8668

File tree

2 files changed

+26
-7
lines changed

2 files changed

+26
-7
lines changed

src/pyodide/internal/workers-api/src/workers/_workers.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ def __init__(
348348
raise TypeError(
349349
f"Unsupported type in Response: {body.constructor.name}"
350350
)
351-
elif not isinstance(body, str | FormData) and body is not None:
351+
elif not isinstance(body, str | FormData | bytes) and body is not None:
352352
raise TypeError(f"Unsupported type in Response: {type(body).__name__}")
353353

354354
# Handle constructing a Response from a JS Response.
@@ -362,12 +362,27 @@ def __init__(
362362

363363
options = self._create_options(status, status_text, headers)
364364

365-
# Initialize via the FetchResponse super-class which gives us access to
366-
# methods that we would ordinarily have to redeclare.
367-
js_resp = js.Response.new(
368-
body.js_object if isinstance(body, FormData) else body, **options
369-
)
370-
super().__init__(js_resp.url, js_resp)
365+
# To avoid unnecessary copies we have to keep track of the proxy and destroy it
366+
# when we're done with it.
367+
js_body = body
368+
proxy_bytes = None
369+
proxy_buffer = None
370+
if isinstance(body, bytes):
371+
proxy_bytes = create_proxy(body)
372+
proxy_buffer = proxy_bytes.getBuffer()
373+
js_body = proxy_buffer.data
374+
elif isinstance(body, FormData):
375+
js_body = body.js_object
376+
try:
377+
# Initialize via the FetchResponse super-class which gives us access to
378+
# methods that we would ordinarily have to redeclare.
379+
js_resp = js.Response.new(js_body, **options)
380+
super().__init__(js_resp.url, js_resp)
381+
finally:
382+
if proxy_bytes:
383+
proxy_bytes.destroy()
384+
if proxy_buffer:
385+
proxy_buffer.release()
371386

372387
def __repr__(self):
373388
body = [f"status={self.status}"]

src/workerd/server/tests/python/sdk/worker.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,10 @@ async def response_unit_tests(env):
476476
assert response_none.status == 204
477477
assert response_none.body is None
478478

479+
response_bytes = Response(b"test")
480+
assert response_bytes.status == 200
481+
assert await response_bytes.text() == "test"
482+
479483
class Test:
480484
def __init__(self, x):
481485
self.x = x

0 commit comments

Comments
 (0)