【问题标题】:node.js server and HTTP/2 (2.0) with express.jsnode.js 服务器和 HTTP/2 (2.0) 与 express.js
【发布时间】:2015-04-22 18:46:22
【问题描述】:

目前是否可以获取 node.js HTTP/2 (HTTP 2.0) 服务器?还有http 2.0版本的express.js?

【问题讨论】:

标签: node.js http express http2


【解决方案1】:
var express = require('express');
var app = express();

app.get('/', function (req, res) {
  res.send('hello, http2!');
});

var options = {
  key: fs.readFileSync('./example/localhost.key'),
  cert: fs.readFileSync('./example/localhost.crt')
};

require('http2').createServer(options, app).listen(8080);

编辑

此代码 sn-p 取自a conversation on Github.

【讨论】:

  • 仅供参考,这不适用于 express@4.13.3http2@3.2.0,并且看起来 express 直到 v5 才支持它。 github.com/molnarg/node-http2/issues/100
  • node@v6.7.0express@5.0.0-alpha.2http2@3.3.6 对我不起作用。 TypeError: dest.end 不是函数
【解决方案2】:

如果你使用express@^5http2@^3.3.4,那么启动服务器的正确方法是:

const http2 = require('http2');
const express = require('express');

const app = express();

// app.use('/', ..);

http2
    .raw
    .createServer(app)
    .listen(8000, (err) => {
        if (err) {
            throw new Error(err);
        }

        /* eslint-disable no-console */
        console.log('Listening on port: ' + argv.port + '.');
        /* eslint-enable no-console */
    });

注意https2.rawThis is required if you want to accept TCP connections.

请注意,在撰写本文时 (2016 05 06),none of the major browsers support HTTP2 over TCP

如果要接受 TCP 和 TLS 连接,则需要使用默认的createServer 方法启动服务器:

const http2 = require('http2');
const express = require('express');
const fs = require('fs');


const app = express();

// app.use('/', ..);

http2
    .createServer({
        key: fs.readFileSync('./localhost.key'),
        cert: fs.readFileSync('./localhost.crt')
    }, app)
    .listen(8000, (err) => {
        if (err) {
            throw new Error(err);
        }

        /* eslint-disable no-console */
        console.log('Listening on port: ' + argv.port + '.');
        /* eslint-enable no-console */
    });

请注意,在撰写本文时,我确实设法使expresshttp2 工作(请参阅https://github.com/molnarg/node-http2/issues/100#issuecomment-217417055)。但是,我已经设法让 http2(和 SPDY)使用 spdy 包工作。

const spdy = require('spdy');
const express = require('express');
const path = require('path');
const fs = require('fs'); 

const app = express();

app.get('/', (req, res) => {
    res.json({foo: 'test'});
});

spdy
    .createServer({
        key: fs.readFileSync(path.resolve(__dirname, './localhost.key')),
        cert: fs.readFileSync(path.resolve(__dirname, './localhost.crt'))
    }, app)
    .listen(8000, (err) => {
        if (err) {
            throw new Error(err);
        }

        /* eslint-disable no-console */
        console.log('Listening on port: ' + argv.port + '.');
        /* eslint-enable no-console */
    });

【讨论】:

  • 有趣的是,当我使用它时,github.com/expressjs/express/issues/2761#issuecomment-216912022 我得到了这个错误。 (节点)警告:检测到可能的 EventEmitter 内存泄漏。添加了 11 个错误侦听器。使用emitter.setMaxListeners() 增加限制。
  • 我正在尝试遵循您的第一个示例,但 http2.raw.createServer(app).listen(...) 抛出错误,因为 http2.rawundefined。我需要使用原始 TCP,因为 TLS 加密正在被服务器的反向代理终止。有关如何解决此问题的任何建议?
  • 注意http2内置于Node 9+
【解决方案3】:

自 2018 年以来,Express 5.0 有一个公开的公关,https://github.com/expressjs/express/pull/3730。在合并之前,它不会开箱即用。

我以包的形式创建了解决方案,https://www.npmjs.com/package/http2-express-bridge

const express = require('express')
const http2Express = require('http2-express-bridge')
const http2 = require('http2')
const { readFileSync } = require('fs')

// Use the wrapper function that returns the application
const app = http2Express(express)

const options = {
    key: readFileSync('<Certificate Key>'),
    cert: readFileSync('<Certificate file>'),
    allowHTTP1: true
};


app.get('/', function (req, res) {
  res.send('Hello World')
})

const server = http2.createSecureServer(options, app)

server.listen(3000, () => {
        console.log(`listening on port 3000`)
})

这行得通,当它收到一个 Http/1.1 请求时,它会回退到 Http/1.1。

我还包含了“res.push”方法以方便服务器推送。该软件包适用于 ESModules 和 Typescript。

【讨论】:

  • 这太棒了!
  • 当我用 curl localhost:3001 -kiv 检查c 时它起作用了,但是当我在浏览器上打开时,页面没有加载,你知道为什么吗?这个页面不工作 localhost 没有发送任何数据。 ERR_EMPTY_RESPONSE
【解决方案4】:

这个问题今天仍然存在(截至撰写本文时是 2016 年),所以我决定尝试解决方法以使 express 和 http2 包很好地协同工作:https://www.npmjs.com/package/express-http2-workaround

编辑:由于原生“http2”模块,不适用于 v8.4 以上的任何 NodeJS 版本。

通过 NPM 安装:npm install express-http2-workaround --save

// Require Modules
var fs = require('fs');
var express = require('express');
var http = require('http');
var http2 = require('http2');

// Create Express Application
var app = express();

// Make HTTP2 work with Express (this must be before any other middleware)
require('express-http2-workaround')({ express:express, http2:http2, app:app });

// Setup HTTP/1.x Server
var httpServer = http.Server(app);
httpServer.listen(80,function(){
  console.log("Express HTTP/1 server started");
});

// Setup HTTP/2 Server
var httpsOptions = {
    'key' : fs.readFileSync(__dirname + '/keys/ssl.key'),
    'cert' : fs.readFileSync(__dirname + '/keys/ssl.crt'),
    'ca' : fs.readFileSync(__dirname + '/keys/ssl.crt')
};
var http2Server = http2.createServer(httpsOptions,app);
http2Server.listen(443,function(){
  console.log("Express HTTP/2 server started");
});

// Serve some content
app.get('/', function(req,res){
    res.send('Hello World! Via HTTP '+req.httpVersion);
});

上面的代码是一个使用 nodejs http 模块(用于 HTTP/1.x)和 http2 模块(用于 HTTP/2)的快速应用程序。

如自述文件中所述,这会创建新的快速请求和响应对象,并将它们的原型设置为 http2 的 IncomingMessage 和 ServerResponse 对象。默认情况下,它是内置的 nodejs http IncomingMessage 和 ServerResponse 对象。

我希望这会有所帮助:)

【讨论】:

  • 不要为我工作,我使用节点 v13.7.0。收到此错误:http2 模块上缺少 IncomingMessage 属性?我之前包含了http2...
猜你喜欢
  • 2018-05-04
  • 1970-01-01
  • 1970-01-01
  • 2012-10-11
  • 2019-06-07
  • 2016-02-24
  • 1970-01-01
  • 2022-01-13
相关资源
最近更新 更多