最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

javascript - Getting socket.io, express & node-http2 to communicate though HTTP2 - Stack Overflow

matteradmin7PV0评论

I wrote a Web Socket server using socket.io, node-http2 and express in Node.js. The server works as intended, except for the fact that according to Chrome's DevTools socket.io's negotiation requests go through HTTP/1.1 (shown below). The "Protocol" column should be displaying h2 if the request was sent using HTTP/2.

This only happens in Chrome, other browsers use the correct protocol.

The server code (shortened):

var PORT = 8667,
    config = require('./config'),
    socketioServer = require('socket.io'),
    app = express(),
    https = require('http2'),
    cors = require('cors');

app.use(cors(function(req, callback){
    var corsOptions = { origin: false };
    if (/^https:\/\/mlpvc-rr\.lc/.test(req.header('Origin')))
        corsOptions.origin = true;
    callback(null, corsOptions);
}));

app.get('/', function (req, res) {
  res.sendStatus(403);
});

var server = https.createServer({
    cert: fs.readFileSync(config.SSL_CERT),
    key: fs.readFileSync(config.SSL_KEY),
}, app);
server.listen(PORT);
var io = socketioServer.listen(server);
// ...

Browser connection code:

var conn = io('https://ws.'+location.hostname+':8667/', { reconnectionDelay: 5000 });
conn.on('connect', function(){
    console.log('[WS] Connected');
});
conn.on('disconnect',function(){
    console.log('[WS] Disconnected');
});

Output of testssl.sh:

What do I need to change to make the socket.io requests go through HTTP/2?

I wrote a Web Socket server using socket.io, node-http2 and express in Node.js. The server works as intended, except for the fact that according to Chrome's DevTools socket.io's negotiation requests go through HTTP/1.1 (shown below). The "Protocol" column should be displaying h2 if the request was sent using HTTP/2.

This only happens in Chrome, other browsers use the correct protocol.

The server code (shortened):

var PORT = 8667,
    config = require('./config'),
    socketioServer = require('socket.io'),
    app = express(),
    https = require('http2'),
    cors = require('cors');

app.use(cors(function(req, callback){
    var corsOptions = { origin: false };
    if (/^https:\/\/mlpvc-rr\.lc/.test(req.header('Origin')))
        corsOptions.origin = true;
    callback(null, corsOptions);
}));

app.get('/', function (req, res) {
  res.sendStatus(403);
});

var server = https.createServer({
    cert: fs.readFileSync(config.SSL_CERT),
    key: fs.readFileSync(config.SSL_KEY),
}, app);
server.listen(PORT);
var io = socketioServer.listen(server);
// ...

Browser connection code:

var conn = io('https://ws.'+location.hostname+':8667/', { reconnectionDelay: 5000 });
conn.on('connect', function(){
    console.log('[WS] Connected');
});
conn.on('disconnect',function(){
    console.log('[WS] Disconnected');
});

Output of testssl.sh:

What do I need to change to make the socket.io requests go through HTTP/2?

Share Improve this question edited Jul 29, 2016 at 18:01 SeinopSys asked Jul 29, 2016 at 15:40 SeinopSysSeinopSys 8,93610 gold badges66 silver badges114 bronze badges 12
  • Hi. Can you get me a plete example? I would love to take a closer look to it. At first sight it seems something to do with websockets (which socket.io uses and which are not supported by HTTP/2) but the requests you show seem to be ordinary Ajax... – dsign Commented Jul 29, 2016 at 16:07
  • @dsign The server is open-sourced at github./ponydevs/MLPVC-WS – SeinopSys Commented Jul 29, 2016 at 16:12
  • Which SSL library are you using (openssl?) and which version and does it support ALPN? ma.ttias.be/… – Barry Pollard Commented Jul 29, 2016 at 16:57
  • @BazzaDP I have no idea about either, I just use whatever npm install installs by default. The config.* variables are simply strings pointing to specific SSL key/crt files. – SeinopSys Commented Jul 29, 2016 at 17:00
  • 1 Yeah need to use testssl.sh then instead. Also does it work with h2 in other browsers (e.g. Opera?)? Also do you have any anti-virus software intercepting your traffic which often downgrades you to http/1.1 – Barry Pollard Commented Jul 29, 2016 at 17:09
 |  Show 7 more ments

2 Answers 2

Reset to default 3

A little bit late but with Express4 and Spdy (npm) is working great.

bin/www:

var app = require('../app');
var debug = require('debug')('gg:server');
var spdy = require('spdy');
var fs = require('fs');
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
var options = {
    key: fs.readFileSync(__dirname + '/server.key'),
    cert: fs.readFileSync(__dirname + '/server.crt')
}
var server = spdy.createServer(options, app);
var io = app.io
io.attach(server);
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
...

app.js:

...
var app = express();
var io = app.io = require('socket.io')();
...

client screenshot:

As discussed in ments Chrome has recently stopped allowing the older NPN negotiation for HTTP/2 and insists on the newer ALPN protocol instead. See this article for more info: https://ma.ttias.be/day-google-chrome-disables-http2-nearly-everyone-may-31st-2016/

So you basically need Node.js to support ALPN which it looks as has only been added in v5 so far: https://github./nodejs/node/pull/2564 . An alternative would be to route your NodeJs calls through a webserver which is easier to upgrade OpenSSL (e.g. Nginx or Apache) to support HTTP/2 over ALPN.

You confirmed this was the issue by using the testssl.sh program which confirmed no ALPN support and the fact Firefox uses HTTP/2.

Post a comment

comment list (0)

  1. No comments so far