-
Notifications
You must be signed in to change notification settings - Fork 66
proposal: Implement HTTP/2 in Node.js core #38
Conversation
I'd be for this if the API could be worked out before it lands in core... Should probably investigate User modules heavily beforehand. |
Yes, already in the process of doing so. This will be a long process with several iterations likely before anything lands in core... and even then the impl/API will need to land as experimental for a bit before becoming officially supported. |
given the amount of work that's going to be involved, I'd really like to know if anyone is in the "oy, we really shouldn't do this" phase ... I'd rather get the Yes/No decision out of the way before tackling the How. |
Upgrading the http_parser would be way too much work and we'd simply end up duplicating what nghttp2 has already done. HTTP/2 switches to a binary framing protocol that completely moves away from the text and line-delimited format assumed by the http-parser. It carries a whole different set of semantics. |
5. The HTTP/2 specification allows for push streams (server initiated streams | ||
with an *assumed* HTTP request). Both the low-level and high-level HTTP | ||
APIs will support the use of push streams on both the client and server | ||
side. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this could be reflected in the proposed API, that would be good.
I'm very curious about the performance implications of using nghttp2 over a pure JS implementation like node-spdy. I would argue it would be good if this were measured before a decision is taken. |
@ronkorving ... yep, once the nghttp2 implementation is a bit further along I will be putting together a set of benchmark and feature comparisons with existing ecosystem implementations like node-spdy. If you have ideas / recommendations / suggestions along these lines please definitely let me know! :-) |
Probably. I need to dig into that more. |
What would be expected setup if people would want to make upgrading to http2 transparent for their users? Listen on http1 and upgrade/redirect to http2 if some criteria is met? |
The http/2 spec outlines a negotiation scheme for both HTTPS and HTTP On Friday, August 12, 2016, Yury notifications@github.com wrote:
|
I feel like the usefulness of HTTP/2 drops quite a bit without the upgrade path there. It might be wise to base it on |
I definitely don't disagree, and what I suspect is that we won't be able to move the http/2 implementation out of Experimental status to Supported status without having the upgrade mechanism included. That said, just getting the basic implementation working and making sure the API is solid will need to take initial priority. There's also the concern that this work needs to not interfere with the existing operation of the http module until it is fully baked. In other words, yes we can do the upgrade path, but it's going to take some time to get there. |
oh, and btw, if anyone is interested in jumping in and collaborating on this, we could probably create a new repo that forks off master and move forward that way. |
I am so excited about this proposal.
|
|
This is super awesome.
Count me in |
Nice work. I think there will definitely be use cases where we explicitly want either HTTP/1.x or HTTP/2.0: e.g. testing, modern services, etc. Even in a service that has to support both protocols, it will make sense to be able to attach different event handlers, in order to take advantage of new capabilities in HTTP/2.0. I do think a very common case for services will involve auto-negotiation over the same port. This can probably be achieved in userland initially, but it would be terrific to follow up this initial support with an example library, at least. |
One question, why is the server completely separate from the regular http server given the protocol is "upgraded." Basically, I'm wondering why we can't do something similar to what we do for WebSockets. https://nodejs.org/api/http.html#http_event_upgrade What is keeping us from having an "http2" event that hands over a new session object? This proposal doesn't include a client, is this because we are thinking we'll just implement that later or are we expecting the ecosystem to handle that via the new bindings for decoding? |
wow... I just realized this isn't a breaking change and is purely a feature addition, we could land this in a minor release :) |
@mikeal ... exactly, doing it this way we'd be able to land this as a semver-minor and iterate without risking any breakage to the existing http module. Once we're sure it's working and we have the API down, we can begin to modify things so that upgrade works between the two. This would include a client but I'm still working through all the details on that. |
@jasnell hrm... I still think that we might want to go the upgrade right off.
If we're this freaked out about touching http.js maybe we should just implement |
I'm on using "http2", rather than touching http.js. For two reasons:
I'm really 👍 on this @jasnell. Count me in for anything on this, we should get the ball rolling. |
@mcollina the exact same comments could be made about WebSockets. Completely different semantics and parsing. My understanding of why node-spdy is so hacky has to do with not being in the core codebase. I don't see how people are going to be able to actually use this as a separate library being that you will still need a lot of fallbacks for http and you still need a full HTTP/1 implementation to get setup. That said, I'd be happy with just |
I'll have a repo set up to work on this by the end of the week; and I'll create a nodejs/http2 team. The repo will be initialized off of master. I do have a basically working prototype based on nghttp2 already but I'll hold off just pushing that in so we can start from a clean slate and make sure things are done right from the beginning ;-) |
A I think a options object on |
Rethinking this a bit, we wouldn't want it to be an event but instead a feature of the HTTP server response object. http.createServer((req, res) => {
if (req.headers.upgrade === 'h2c') {
var session = res.http2CreateSession()
return
}
}) |
@silverwind actually, it's the client's responsibility to signal it supports HTTP2 and the server is free to respond with a regular HTTP/1 response even if it does support HTTP2. If we were to implement it as I described above, on the response object, it would be the response objects job to figure out if it is over TLS or not setup the connection via the appropriate method. |
Given that there's already an Keep in mind that there are two paths for negotiating an HTTP/2 session... one for TLS and one for plain text... and given the differences in the implementation internals, it's going to be significantly easier to do this if we focus on the basic impl and standalone impl first, then find ways of bringing them together for the upgrade path. That said, here's what I'm currently thinking as far as bootstrap is concerned...
This would allow us to maintain separation between the http/1 and http/2 implementations, preserve the existing API model for upgrades, and support both upgrade models specified by http/2. |
Went ahead and created the repo and initialized it from master... https://github.com/nodejs/http2 ... will begin getting the first PRs open by end of week |
FWIW, I've never seen plain text negotiation work. It seems no browser supports it, but would be thrilled if proven wrong. |
@ronkorving at least Mozilla and Google were strictly against supporting HTTP/2 in the browser without TLS. https://daniel.haxx.se/blog/2015/03/06/tls-in-http2/ Now, there are actually use cases for plain text HTTP/2, as daniel mentions later in the post, but no consumer browser indicates any intention to support it over plain text. EDIT: or do you mean upgrading plain text HTTP/1 to TLS HTTP/2? Would this not first require an upgrade from plain text to TLS, and then the TLS handshake could use ALPN to ask for h2? |
@Kovensky No, you are right. You're confirming my statement. Given that, I'm just not sure what would be the point of having a plain text upgrade path implemented at all in Node. |
I can definitely see why I would use http 2 over plaintext - http is used for a lot more than browsers and services often communicate using it and sometimes it's fine for them to pass plaintext. That said - the overhead of using tls is tiny anyway. |
Fair enough. If there is an official way to do it, and browsers choose to ignore it, that should not mean by default that we should ignore it too. |
In a production deployment of a web service, it is common for HTTPS to be terminated at the load balancer, and for requests from the load balancer to the worker to be plain-text. Ideally (?), you would want every worker to be able to provision an internally-signed certificate, so that load balancer requests can also be performed over HTTPS. But this is configuration is impractical for many, and might not even have the desired safety advantages. Virtual private networking likely has more of a security impact here than internal certificate verification. So at least within the context of machine-to-machine communication, support for plain-text HTTP/2.0 will be necessary for the time being. |
Sounds reasonable. As data points, both httpd and nginx support plaintext HTTP/2. |
Random comment from the peanut gallery but wouldn't using nghttp2 facilitate the implementation of https://fetch.spec.whatwg.org/ and other high-quality HTTP client interfaces? |
@louiscryan you can already use fetch via npm, https://www.npmjs.com/package/whatwg-fetch nghttp2 is just the underlying protocol, not a high level api. |
@mikeal My interest is in the context of the full-duplex streaming capabilities & of the Fetch API which is now an accepted feature Full-duplex is not possible with HTTP/1.1 but is a standard feature of HTTP2 so nghttp2 ends up being a dependency here. I also care about this |
Saw that you are planning to export |
Since work is now in progress at https://github.com/nodejs/http2, should we now merge this PR? AFAIK that doesn't mean all is set in stone, but that we agree on the initial approach. @jasnell - any idea on when this would first be included in a core release, presumably as experimental? Thanks! |
@jasnell everything here looks good. If you want go ahead and change the |
|
@nodejs/collaborators @nodejs/http : This is the beginnings of a proposal to implement HTTP/2 in Node.js core. There are still many details that need to be worked out, but this outlines the basic direction.