Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
29 changes: 23 additions & 6 deletions src/pyodide/internal/workers-api/src/workers/_workers.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,23 @@ def _to_js_headers(headers: Headers):
raise TypeError("Received unexpected type for headers argument")


@contextmanager
def _get_js_body(body):
if isinstance(body, bytes):
proxy_bytes = create_proxy(body)
proxy_buffer = proxy_bytes.getBuffer()
try:
yield proxy_buffer.data
return
finally:
proxy_buffer.release()
proxy_bytes.destroy()
if isinstance(body, FormData):
yield body.js_object
return
yield body


class Response(FetchResponse):
"""
This class represents the response to an HTTP request, with a similar API to that of the web
Expand Down Expand Up @@ -349,7 +366,7 @@ def __init__(
raise TypeError(
f"Unsupported type in Response: {body.constructor.name}"
)
elif not isinstance(body, str | FormData) and body is not None:
elif not isinstance(body, str | FormData | bytes) and body is not None:
raise TypeError(f"Unsupported type in Response: {type(body).__name__}")

# Handle constructing a Response from a JS Response.
Expand All @@ -363,11 +380,11 @@ def __init__(

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

# Initialize via the FetchResponse super-class which gives us access to
# methods that we would ordinarily have to redeclare.
js_resp = js.Response.new(
body.js_object if isinstance(body, FormData) else body, **options
)
# To avoid unnecessary copies we use this context manager.
with _get_js_body(body) as js_body:
# Initialize via the FetchResponse super-class which gives us access to
# methods that we would ordinarily have to redeclare.
js_resp = js.Response.new(js_body, **options)
super().__init__(js_resp.url, js_resp)

def __repr__(self):
Expand Down
4 changes: 4 additions & 0 deletions src/workerd/server/tests/python/sdk/worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,10 @@ async def response_unit_tests(env):
assert response_none.status == 204
assert response_none.body is None

response_bytes = Response(b"test")
assert response_bytes.status == 200
assert await response_bytes.text() == "test"

class Test:
def __init__(self, x):
self.x = x
Expand Down