-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WebStream API support #387
Comments
Not sure it would be useful in a nodejs enviorment where everything is written with node streams. There is a grate package called node-web-streams for conversion between those two const webStreams = require('node-web-streams');
const readableStream = webStreams.toWebReadableStream(nodeReadable); if we where to implement ReadableStream in node-fetch I'm guessing most ppl would just to the opposite and try to convert it back to a node stream It would be a breaking change since Response.prototype.body is now a node stream and some are already using it. |
I've recently been implementing the That way if people want the web-streams API, they can opt-in to it. |
@ThisIsMissEm There are nontrivial differences in the There have some exciting developments over on the Node.js side (nodejs/node#22352), and if Web Streams eventually get in Node core we can certainly add support for it. (Does this answer your question or am I missing something you are trying to say?) |
Yeah, we realised this was the case, so we've forked node-fetch to use ReadableStream API. You can see the start of our attempt here: master...titel-media:whatwg-readablestreams |
Whilst my usage of node-fetch is for reimplementing the API of CloudFlare Workers, I think it’s worth noting that several modules that depend on node-fetch claim that they expose the whatwg-fetch spec, which isn’t true, as that’d mean they expose whatwg streams; They’ve possibly missed the note about difference in stream APIs |
@TimothyGu We actually have pretty much full tests passing — I removed a bunch of stuff and can do a PR, but in order for my team to move forward we'll be publishing a scoped fork. It's up to you if you want to take my changes into node-fetch, I'm happy to have a fork for now. |
Found out something that is going to make this cross browser/node chunk reading much simpler! Async iterator!!! Node implemented if (!ReadableStream.prototype[Symbol.asyncIterator]) {
ReadableStream.prototype[Symbol.asyncIterator] = async function* () {
const reader = this.getReader()
while (1) {
const r = await reader.read()
if (r.done) return value
yield r.value
}
}
} now what you can do in both the browser and Node is: const res = await fetch('https://httpbin.org/bytes/500000')
for await (const chunk of res.body) {
console.log(chunk)
} Both yields a Uint8Array array (well, a buffer in node, but they are inherited by Uint8array) so you can treat them the same Hopefully this will make the WebStream api for node-fetch more irrelevant this is something i would very much like to see in the readme 😛 |
@jimmywarting Unfortunately, async iterators don't provide a full replacement for streams with regards to things like backpressure. This is obviously a step in the right direction but there is still value in exposing Web streams. For context, a PR that adds async iterators to web streams is whatwg/streams#950. |
@jimmywarting wow! That makes it SO much nicer than using the reader / while loop interface. |
@TimothyGu wouldn't backpressure with async iterator just be handled via something like: const res = await fetch('https://httpbin.org/bytes/500000')
for await (const chunk of res.body) {
await doSomework(chunk)
} So because we're delaying in each iteration backpressure applies? |
Hm, I guess I was more referring to the |
Okay, so, an update from my end: We're publishing a fork with ReadableStreams as @titelmedia/node-fetch, such that we can use it in our Cloudflare Worker development server. It's up to you @TimothyGu if you choose to adopt the changes I've made. |
Think you should have highlighted the differences between your fork and |
Oh, yes.. I forgot about that. The package description has it though. |
@TimothyGu not sure your take on this but the nodejs core web stream PR didn't land; it seems the only viable solution is to use https://github.com/MattiasBuelens/web-streams-polyfill for now. |
Some good news: |
So what is the verdict? should we implement web-streams-polyfill for v3? I guessing some ppl will complain about the switch from node stream to whatwg streams |
@jimmywarting don't think there is a verdict yet, stream is a different spec which I believe isn't quite finished yet, and browser support isn't quite on-par the last time I checked. I recently thought about what if Fetch options allow users to pass in a stream implementation (node or web), and use that instead, just like how we handled AbortController support. And since there is a lack of man-power on this issue, another likely outcome is we wait for nodejs to implement it, which will be a long while. See also: MattiasBuelens/web-streams-polyfill#1 |
I kinda feel like it's the right step forward to implement whatwg streams (to be isomorphic compatible cross node and browser) while at the same time i also feel like node-fetch is not quite ready for it yet. here is some other ideas i thought of to keep the users that still uses node-streams Or make some utility function something like const asNodeStream = require('fetch/as-node-stream') // or
const { asNodeStream } = require('fetch')
fetch(url).then(res => {
asNodeStream(res.body) // returns the internal body stream
.pipe(dest)
}) Another idea is the use of symbol. const { internalNodeStreamSymbol } = require('fetch')
fetch(url).then(res => {
res[internalNodeStreamSymbol].pipe(dest)
}) |
@ThisIsMissEm I can't thank you enough for sharing that fork! After an hour or two of trying to mash polyfills together unsuccessfully I thought I was going to have to implement something myself. (sorry for the noise) |
Recently I found
|
We got plans to bring in whatwg streams polyfill and change the response body to whatwg streams for v4, but it's going to be a breaking change... would like to fix some issues before making that release |
I've been having great success with web-streams-polygill inside the make-fetch library. Wasn't too hard to migrate to it from node streams. |
By breaking change, do you mean that v4 no longer supports Node.js stream? I'm a bit confused. |
`node-fetch` does not yet support webstreams, which is required for `.body` node-fetch/node-fetch#387
* feat!: Upgrade to `node-fetch` v3 * refactor: Use native `FormData` in testing * feat!: Improve spec compliance * test(temp): Run 18+ * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * feat: Improve types, streamline, and standardize * test: Adopt `Headers` type from merge * feat: Introduce `GaxiosOptionsPrepared` for improved type guarantees * feat: Ensure `GaxiosOptionsPrepared.url` is always a `URL` * refactor: Clean-up Types & Resolve lint warnings * refactor: streamline `.data` for `Response` * docs: Simplify example * refactor: streamline, no error case * feat: Basic `GET` Support for `Request` objects `node-fetch` does not yet support webstreams, which is required for `.body` node-fetch/node-fetch#387 * test: remove `.only` * refactor: simplify `httpMethodsToRetry` * chore: update `nock` * test: cleanup * fix: `File` in Node 18 * docs: clarification for node-fetch `.data` * chore: fix webpack for node-fetch v3 * docs: clarifications * fix: Types for Node.js-only environments --------- Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
* feat!: Upgrade to `node-fetch` v3 * refactor: Use native `FormData` in testing * feat!: Improve spec compliance * test(temp): Run 18+ * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * feat: Improve types, streamline, and standardize * test: Adopt `Headers` type from merge * feat: Introduce `GaxiosOptionsPrepared` for improved type guarantees * feat: Ensure `GaxiosOptionsPrepared.url` is always a `URL` * refactor: Clean-up Types & Resolve lint warnings * refactor: streamline `.data` for `Response` * docs: Simplify example * refactor: streamline, no error case * feat: Basic `GET` Support for `Request` objects `node-fetch` does not yet support webstreams, which is required for `.body` node-fetch/node-fetch#387 * test: remove `.only` * refactor: simplify `httpMethodsToRetry` * chore: update `nock` * test: cleanup * feat!: Headers should be `Headers` * fix: Multipart Headers * refactor: clean-up and optimize --------- Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
* feat!: Upgrade to `node-fetch` v3 * refactor: Use native `FormData` in testing * feat!: Improve spec compliance * test(temp): Run 18+ * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * feat: Improve types, streamline, and standardize * feat!: Do Not Treat Buffers as JSON By Default * test: Adopt `Headers` type from merge * feat: Introduce `GaxiosOptionsPrepared` for improved type guarantees * feat: Ensure `GaxiosOptionsPrepared.url` is always a `URL` * refactor: Clean-up Types & Resolve lint warnings * refactor: streamline `.data` for `Response` * docs: Simplify example * refactor: streamline, no error case * docs: clarification * feat: Basic `GET` Support for `Request` objects `node-fetch` does not yet support webstreams, which is required for `.body` node-fetch/node-fetch#387 * test: remove `.only` * refactor: simplify `httpMethodsToRetry` * chore: update `nock` * test: cleanup * test: add test for asserting no default `content-type` * docs: Add detail for `code` property * docs: uniform --------- Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
This has been sort of worked on in #140 but then was continued in another branch #140 (comment).
Is the WebStream API, that is published in FF & Chrome, like
getReader()
etc. too experimental for node-fetch?The text was updated successfully, but these errors were encountered: