Given the latest version of Node.js with experimental HTTP2 support:
$ node -v
v9.2.0
An HTTP2 server:
var options = {
key: getKey(),
cert: getCert(),
allowHTTP1: true
}
var server = http2.createSecureServer(options)
server.on('stream', onstream)
server.on('error', onerror)
server.on('connect', onconnect)
server.on('socketError', onsocketerror)
server.on('frameError', onframeerror)
server.on('remoteSettings', onremotesettings)
server.listen(8443)
function onconnect() {
console.log('connect')
}
function onremotesettings(settings) {
console.log('remote settings', settings)
}
function onframeerror(error) {
console.log('frame error', error)
}
function onsocketerror(error) {
console.log('socket error', error)
}
function onerror(error) {
console.log(error)
}
function onstream(stream, headers) {
console.log('stream')
}
And a request made to it:
var https = require('https')
var options = {
method: 'GET',
hostname: 'localhost',
port: '8443',
path: '/',
protocol: 'https:',
rejectUnauthorized: false,
agent: false
}
var req = https.request(options, function(res){
var body = ''
res.setEncoding('utf8')
res.on('data', function(data){
body += data;
});
res.on('end', function(){
callback(null, body)
})
})
req.end()
It just hangs and eventually says:
Error: socket hang up
at createHangUpError (_http_client.js:330:15)
at TLSSocket.socketOnEnd (_http_client.js:423:23)
at TLSSocket.emit (events.js:164:20)
at endReadableNT (_stream_readable.js:1054:12)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
at process._tickCallback (internal/process/next_tick.js:180:9)
If rejectUnauthorized: true
is set, then it errors:
Error: self signed certificate
at TLSSocket.onConnectSecure (_tls_wrap.js:1036:34)
at TLSSocket.emit (events.js:159:13)
at TLSSocket._finishInit (_tls_wrap.js:637:8)
Not sure what is going wrong and why it won't get to the point of logging stream
.
If I go in the browser and visit https://localhost:8443, and click through the warning messages, it does actually log stream
and successfully make the request. But haven't been able to get node to make the request.
I would like to treat this as an HTTP1 server, so don't want to use the HTTP2 client to make the request. But tried using that and same thing.
HTTP/1 doesn't share the same request semantics as HTTP/2 so HTTP/1 clients need to be detected and handled in a HTTP/2 server. To support both you need to use the HTTP2 Compatibility API.
The "hang" occurs when a HTTP1 client connects to a HTTP/2 server with
allowHTTP1: true
set but doesn't handle the HTTP/1 request.The examples are based on the Node documentation example code.
HTTP/1 and /2 Mixed Server
HTTP/2 Client
Then running:
HTTP/1 Client
Then running
HTTP/2 Server
Using the plain HTTP/2 Server will work with the
http2_client
but will "hang" for ahttp1_client
. The TLS connection from a HTTP/1 client will be closed when you removeallowHTTP1: true
.Certs
With the extended intermediate certificate setup detailed in the gist, the complete certificate chain for the CA needs to be supplied to the clients.
Then in the clients use this
ca
in the options.These examples were run withe the following simple CA setup from this circle.com article: