What's the point of Response.clone?

The Workers Runtime API has a Response.clone function. However, when I use it I’m unable to modify the headers of a response (getting the TypeError: Can't modify immutable headers. error). But when I use the constructor, everything works as expected. Is clone broken?

// This gives a "can't modify immutable headers" response
const newResponse = response.clone();

// But this allows me to modify the headers. Why are these different?
const newResponse = new Response(response.body, {
  headers: response.headers,
  status: response.status,
  statusText: response.statusText

bodyString = await response.clone().text();
To collect the response body into a single JS string, and later on still do a

response = new Response(response.body, response)

Since a response.body readable-stream can only be read ONCE (its copy by ref, not copy by val) and then it is “disturbed” and can’t be read again (in new Response or whenever the promise is await-ed later on, explicitly by you or by the runtime). clone() allows you to create TWO body read streams that both start at “offset 0” from 1 origin response.

. “Resonse”/fetch object are constructed/resolve after the “\n\n” of the HTTP response header, the body aka readable-stream object is NOT yet delivered to CF/CFW instance, its still in transit, even though the headers are fully delivered. the body readable-stream theoretically resolves AFTER your CFW “exits” by calling respondWith() outside the V8 sandbox. clone lets you duplicate a future readable-stream body to be read twice.

1 Like

Ah that makes sense. I’m sure I read that a long time ago, but had since forgotten. None of my workers need to consider response bodies, so it didn’t occur to me. Thanks for re-educating me!