获取 socket.io、express 和 node-http2 通过 HTTP/2 进行通信
Getting socket.io, express & node-http2 to communicate though HTTP/2
我使用 socket.io、node-http2 和 express Node.js 编写了一个 Web Socket 服务器。服务器按预期工作,除了根据 Chrome 的 DevTools socket.io 的协商请求通过 HTTP/1.1(如下所示)这一事实。如果使用 HTTP/2.
发送请求,"Protocol" 列应显示 h2
这只发生在 Chrome,其他浏览器使用正确的协议。
服务器代码(缩写):
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);
// ...
浏览器连接码:
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');
});
testssl.sh 的输出:
我需要更改什么才能使 socket.io 请求通过 HTTP/2?
正如评论中所讨论的那样,Chrome 最近已停止允许 HTTP/2 的旧 NPN 协商,而是坚持使用较新的 ALPN 协议。有关详细信息,请参阅本文:https://ma.ttias.be/day-google-chrome-disables-http2-nearly-everyone-may-31st-2016/
所以你基本上需要 Node.js 来支持 ALPN,到目前为止它看起来只在 v5 中添加:https://github.com/nodejs/node/pull/2564。另一种方法是通过网络服务器路由您的 NodeJs 调用,这样更容易升级 OpenSSL(例如 Nginx 或 Apache)以支持 HTTP/2 over ALPN。
您使用 testssl.sh 程序确认了此问题,该程序确认不支持 ALPN 并且 Firefox 使用 HTTP/2。
有点晚了,但使用 Express4 和 Spdy (npm) 效果很好。
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')();
...
客户端截图:
我使用 socket.io、node-http2 和 express Node.js 编写了一个 Web Socket 服务器。服务器按预期工作,除了根据 Chrome 的 DevTools socket.io 的协商请求通过 HTTP/1.1(如下所示)这一事实。如果使用 HTTP/2.
发送请求,"Protocol" 列应显示h2
这只发生在 Chrome,其他浏览器使用正确的协议。
服务器代码(缩写):
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);
// ...
浏览器连接码:
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');
});
testssl.sh 的输出:
我需要更改什么才能使 socket.io 请求通过 HTTP/2?
正如评论中所讨论的那样,Chrome 最近已停止允许 HTTP/2 的旧 NPN 协商,而是坚持使用较新的 ALPN 协议。有关详细信息,请参阅本文:https://ma.ttias.be/day-google-chrome-disables-http2-nearly-everyone-may-31st-2016/
所以你基本上需要 Node.js 来支持 ALPN,到目前为止它看起来只在 v5 中添加:https://github.com/nodejs/node/pull/2564。另一种方法是通过网络服务器路由您的 NodeJs 调用,这样更容易升级 OpenSSL(例如 Nginx 或 Apache)以支持 HTTP/2 over ALPN。
您使用 testssl.sh 程序确认了此问题,该程序确认不支持 ALPN 并且 Firefox 使用 HTTP/2。
有点晚了,但使用 Express4 和 Spdy (npm) 效果很好。
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')();
...
客户端截图: