Skip to content

Commit 5762112

Browse files
committed
Adds support for bytes passed to Python's Response constructor
1 parent a14eccb commit 5762112

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
@@ -349,7 +349,7 @@ def __init__(
349349
raise TypeError(
350350
f"Unsupported type in Response: {body.constructor.name}"
351351
)
352-
elif not isinstance(body, str | FormData) and body is not None:
352+
elif not isinstance(body, str | FormData | bytes) and body is not None:
353353
raise TypeError(f"Unsupported type in Response: {type(body).__name__}")
354354

355355
# Handle constructing a Response from a JS Response.
@@ -363,12 +363,27 @@ def __init__(
363363

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

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

373388
def __repr__(self):
374389
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)