Fetch body streams are not full duplex · Issue #1254 · whatwg/fetch · GitHub
Skip to content

Fetch body streams are not full duplex #1254

Open
@lucacasonato

Description

With request body streams and response body streams one would think it is now possible to use fetch for full duplex communication over HTTP, like in the example below:

const intervalStream = new ReadableStream({
  start(c) {
    let count = 0;
    const timer = setInterval(() => {
      console.log("sent!");
      c.enqueue("Hello\n");
      if (count === 5) {
        clearInterval(timer);
        c.close();
      }
      count++;
    }, 1000);
  },
}).pipeThrough(new TextEncoderStream());

const resp = await fetch("https://full-duplex-server.deno.dev/", {
  method: "POST",
  body: intervalStream,
});

console.log("foo");

const reader = resp.body.pipeThrough(new TextDecoderStream()).getReader();

while (true) {
  const { value, done } = await reader.read();
  if (done) break;
  console.log(value);
}

console.log("done!");

In this example the server just pipes the incoming request body stream into the response body steam with no modification.

If full duplex communication was working, you would see "sent!" and "Hello\n" being logged in close proximity to each other, live. This is however not the case, because the promise returned from fetch does not resolve until the entire request body stream has been sent and closed.

The solution here would be to resolve the Promise<Response> returned from fetch before the request body stream has completed. To do this, body upload streaming has to happen in parallel. The main issue with the spec in this area is that the promise returned from fetch is expected to reject if a chunk of the request body stream is not a Uint8Array (behaviour is tested in https://staging.wpt.fyi/results/fetch/api/basic/request-upload.any.html).

Are there any plans to resolve this shortcoming before request body streaming is sthbilized in browsers? HTTP/2 and QUIC are very capable duplex stream protocols (HTTP/1 is theoretically also capable) and it would be a shame if that power was not exposed to the web platform.

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions