We "need" a way to create an Http2Session from a socket
While building fetch-h2
and when discussing with node-fetch
, and while participating in #14671 I realize that we need this in Node.js; a protocol-agnostic connect()
to a TLS-enabled web server and let the ALPN handshake allow for both "h2"
and "http/1.1"
. Without this, we won't be able to connect to an https-server without knowing in beforehand if that server wants to (or even can!) speak HTTP/1.1 or HTTP/2.
I'm thinking of something like tls.handoverConnect()
which doesn't take application-level (http) arguments (path, headers, etc), it just connects and returns (through a callback, likely) the protocol ("http/1.1" or "h2") and a corresponding session.
A question is what the session data is. In case of HTTP/2, it should be an Http2Session, but for HTTP/1.1 it must be something where the user can perform the request, and it should probably be integrated with Agents. There's unfortunately an inheritance jungle in the design of these old functions, like https.request()
where ip/tcp/application-level options are merged into one blob, but the "https/1.1 session" here (let's call it Http1SessionProxy
) should be something that looks like the http
module, in how it has a request()
function, with the tcp/ip-level options removed.
Let's say this feature belongs in tls
(which I think it does):
const connectOpts = { host: "my-server.com", port: 443, /* ... */ };
tls.handoverConnect( connectOpts, ( err, protocol ) =>
{
if ( err ) ... ;
// session is an Http2Session or Http1SessionProxy
const { name, session } = protocol;
if ( name === 'http/1.1' )
{
// session.request acts just like http.request
const req = session.request(
{ path: '/foo', headers, ... },
( res ) => { ... }
);
}
else if ( name === 'h2' )
{
// well, the usual http2-stuff
const stream = session.request( headers, options );
}
} );
In this example, perhaps an Agent could be passed in the connectOpts
, so that if the session turns out to be HTTP/1.1, the connection will be added to this agent (and by default the global Agent is used, just like traditional http{s}.request()
).
Any thoughts on this? I guess it's a good time to look into this now, as the http2
module is being tested in the wild, but before it's "stable".