@@ -314,6 +314,23 @@ def _to_js_headers(headers: Headers):
314314 raise TypeError ("Received unexpected type for headers argument" )
315315
316316
317+ @contextmanager
318+ def _get_js_body (body ):
319+ if isinstance (body , bytes ):
320+ proxy_bytes = create_proxy (body )
321+ proxy_buffer = proxy_bytes .getBuffer ()
322+ try :
323+ yield proxy_buffer .data
324+ return
325+ finally :
326+ proxy_buffer .release ()
327+ proxy_bytes .destroy ()
328+ if isinstance (body , FormData ):
329+ yield body .js_object
330+ return
331+ yield body
332+
333+
317334class Response (FetchResponse ):
318335 """
319336 This class represents the response to an HTTP request, with a similar API to that of the web
@@ -349,7 +366,7 @@ def __init__(
349366 raise TypeError (
350367 f"Unsupported type in Response: { body .constructor .name } "
351368 )
352- elif not isinstance (body , str | FormData ) and body is not None :
369+ elif not isinstance (body , str | FormData | bytes ) and body is not None :
353370 raise TypeError (f"Unsupported type in Response: { type (body ).__name__ } " )
354371
355372 # Handle constructing a Response from a JS Response.
@@ -363,11 +380,11 @@ def __init__(
363380
364381 options = self ._create_options (status , status_text , headers , web_socket )
365382
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- )
383+ # To avoid unnecessary copies we use this context manager.
384+ with _get_js_body ( body ) as js_body :
385+ # Initialize via the FetchResponse super-class which gives us access to
386+ # methods that we would ordinarily have to redeclare.
387+ js_resp = js . Response . new ( js_body , ** options )
371388 super ().__init__ (js_resp .url , js_resp )
372389
373390 def __repr__ (self ):
0 commit comments