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.