-
-
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
Support HTTP/2 #342
Comments
I would agree with the general sentiment expressed in the OP: that HTTP/2 should be provided transparently, like it is in browsers. The biggest non-technical challenge right now, is that I haven't kept myself real up-to-date about the development of the http2 module in Node.js ;) Joking aside, I see the following issues. They may or may not be faced by other workalike modules.
I would of course appreciate any insights or literature about these topics, and if anyone volunteers to take a stab at this or any of the above issues turn out to be non-concerns – even better :) |
I am not sure HTTP/2 is actually enforced in Fetch, see their headers requirement: #260, that's explicitly not HTTP/2 AFAIK. (EDIT: also interesting to know what sort of use-cases people can think of, make Fetch HTTP/2-aware is unlikely going to give much performance or usability improvement over a simple keepalive on Nodejs?) |
@bitinn Compressed headers are still nice though. |
@TimothyGu a few things:
|
No :( I don't think so, at least. We would want to make the HTTP/1 and HTTP/2 distinction fully transparent, and doing so requires either ALPN (for HTTPS) or
👍 I'll try to raise this to Node.js for some help on making such a module, as I'm not entirely sure how (or if it would be possible) to create a client HTTP/2 session from an existing socket in Node.js yet. |
Really glad to hear there might be interest. Yeah James seems to have dropped quite the bomb with this and it seems really impressive work that will take some time to integrate and upgrade ourselves for :P It seems like one of the differences handling HTTP/2 is due to the fact that Fetch in browsers has a cache layer which can deal with push requests. A separate "on('push')" or similar may be needed to have a special Node handler for this case, without assuming default cache population, which I think would be a fine solution. The main advantage to focus on though is getting the high throughput multiplexing of HTTP/2 when using I'm sure the HTTP/2 implementation is in need of feedback as well, so if something like reusing a previously created socket is a concern, these are likely useful discussions to have and be seeking assistance on. This side of things is not really my area, but I would definitely do as much as I can to help here as the pay off from a performance perspective would be amazing to see. |
Yeah, I agree with the Agent thing. Connection pooling is substantially more well-defined for HTTP/2. But at the same time, an HTTP/2 connection is not stateless like an HTTP/1.1 connection is: there are SETTINGS controlling behaviors in an HTTP/2 connection. For this reason, while Node.js' HTTP/1.1 client has global agents, a similar concept for HTTP/2 would be difficult to reason about, either node-fetch-global or Node.js-global. Also, as long as we don't provide caching and Fetch doesn't provide server push APIs, I don't really want to try to support server push |
Only for the server side, unfortunately. |
Aren't the settings limited to connection-level settings though? Window size etc mostly for managing the correct bandwidth settings? Or are there other more stateful things to do with the connection? I would have said based on this that the same Agent model of default global pooling would apply, but otherwise http2 could be enabled say through a pool option or similar perhaps
If there's a way to disable PUSH for HTTP/2 servers then great, but as far as I'm aware the CANCEL response for PUSH only happens after data is pushed, such that responding to the event may well still be beneficial. |
Hmm I think you are right. There is |
I wasn't aware it was possible to negotiate an opt-out of push through settings. That sounds like a sensible default then. |
Given this module is for Node, and often it will be used between services in a backend (where encryption isn't always important), user will more or less have to know (and choose) whether to connect to an HTTP/1 or HTTP/2 server. The session/socket/agent handling is radically different between the two, and services may almost depend on H2 in terms of multiple long-polling streams etc. The choice of the web browsers to only speak H2 over TLS has a subtle benefit - they don't need to know in beforehand if the server speaks HTTP/1 or 2. For clients speaking unencrypted H2, it'll get tricker, so a Because of the above, (and also because I quickly needed a nice I published it yesterday, so it's very early, but the |
@grantila great work, I haven't had a chance to play around with it yet but reading through the readme it looks very promising! And really appreciated for joining the discussion here for possible collaboration. How closely does it follow the same sort of API here down to the request and stream details? Looking through the API compatibility it seems like they are very similar, in providing For credentials, it could be nice to possible mimic the In terms of how to select between HTTP/1 and HTTP/2, do you think a boolean option provide enough information here - If that would be adequate, there would be no reason not to keep these two as separate projects, but then have Of course this is all up to @TimothyGu here, so will wait for him to respond further. |
I would prefer it all to be transparent, i.e. not add another dependency that does the same thing we can do in just a few lines. In nodejs/node#16256 Node.js seems to be making good progress towards transparent HTTP 1.1 vs. 2 for TLS/ALPN at least, and if they do end up adding agent support we should be good to go too. |
For alternative http2 pure JS implementation I recommend checking http2.js see details here: |
@hthetiot We will not be using any HTTP/2 implementation other than the one in Node.js, when the Node.js used has HTTP/2 support. |
What's the status on this? I'm presently writing tests leveraging |
i'm going to take a look at this now, i have a working alpn negotiation script which connects to sites (rn hardcoded as google 😛) either with h2 or http/1.1 |
@devsnek do you mean to say that you're going to take a look at updating this module? looking to clarify before I get too excited 🙃 /cc @TimothyGu @bitinn |
@shellscape yes thats what i'm looking into @TimothyGu i would call Http2ClientSession a valid "Agent", i'll look into abstracting the interface |
> void require('.')('https://nghttp2.org/httpbin/get').then(r => r.json()).then(console.log)
undefined
> (node:71326) ExperimentalWarning: The http2 module is an experimental API.
{ args: {},
headers: { Host: 'nghttp2.org:443', Via: '2 nghttpx' },
origin: '7x.7x.20x.7x',
url: 'https://nghttp2.org:443/httpbin/get' } right now the only problem is a new Http2ClientSession for every request (back to the agent stuff) |
I just noticed this project - https://github.com/hisco/http2-client. Since it mimics the http / https APIs that might provide a drop-in path to supporting transparent HTTP/2 in this project? I'm sure there will be issues along the way, but it could be worth trying if anyone is interested in working on this! |
@guybedford thanks for sharing that. definitely going to have a look at that this weekend. |
@guybedford That's a neat compatibility layer. I generally like the Fetch API as a common ground between Node.js and browserland. One thing I miss are server push streams/events. Anyone know if there is progress on this in the standards effort? Perhaps a general mechanism that could be extended to other HTTP/2 frames like ping, altsvc, etc. |
Agree with @bitinn I’ll get started on a PR |
@NotMoni While I created a PR for that, feel free to submit another one or review mine ;) |
Sure |
@bitinn Did you work on this? :) |
@thernstig nope, however we will take a HTTP 1+2 wrapper PR if it's done properly, the main thing is we want http.Agent to still be usable (so users don't have to remember 2 sets of options). So far it has proven to be a great obstacle. |
+1 on this! I tried to move to cross-fetch across my server and client code, which uses node-fetch underneath. It failed when parsing the response from the Apple apns server, which requires HTTP2: |
+1, this is a need for our project at PWABuilder. We use node-fetch in our backend to package PWAs for different app stores. What we are seeing is many PWAs are now using HTTP/2. Our software fails on these sites because node-fetch doesn't work with HTTP/2. |
Once we transition to ESM (#1141) I will be able to look into this once again. |
- `node-fetch` doesn't support HTTP/2 and has had an issue for support open since 2017: node-fetch/node-fetch#342 - `fetch-h2` supports HTTP1.1 and HTTP/2 with upgrade.
- `node-fetch` doesn't support HTTP/2 and has had an issue for support open since 2017: node-fetch/node-fetch#342 - `fetch-h2` supports HTTP1.1 and HTTP/2 with upgrade.
* Replaces `node-fetch` with `fetch-h2` on `core` - `node-fetch` doesn't support HTTP/2 and has had an issue for support open since 2017: node-fetch/node-fetch#342 - `fetch-h2` supports HTTP1.1 and HTTP/2 with upgrade. - Defaults to using `fetch-h2`. - Allows optionally using `node-fetch`. - Centralises calls to `fetch` in `FetchUtils`.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
I'm afraid there won't be any real effort into trying to accomplice this complicated task of trying to upgrade connections to HTTP/2 by conditionally check if the server supports it or not. node-fetch is kind of being replaced by built in fetch provided by NodeJS (undici) themself I think it will be best to follow: nodejs/undici#399 |
I just wanted to try and start a discussion here to see if this is something suitable for this project, or if it is something more suited to another one?
In the browser HTTP/2 gets used opaquely - would be really nice to get the same experience in NodeJS to provide a unified experience, perhaps with just an opt-in flag for using the Node core support here.
I wonder what the technical hurdles would be faced with the API? I guess HTTP/2 doesn't have an "agent" interface the same way, but perhaps a userland agent wrapper could be created for HTTP/2, would that make sense? Apart from that what other API's may provide issues?
The text was updated successfully, but these errors were encountered: