如何使用Node.js模块http2将http2与ExpressJS集成?

26

我正在使用Node.js和Express创建一个API,希望将HTTP2集成到ExpressJS中。

这是我的代码:

'use strict';

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

const express = require('express');
const bodyParser = require('body-parser');

const app = express();
const port = process.env.PORT || 443;

// Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

// Routes variables
const indexRouter = require('./routes/index');

// Routes uses
app.use('/', indexRouter);

// Server configurations
const key = path.join(__dirname + '/security/key.pem');
const cert = path.join(__dirname + '/security/certificate.pem');

const options = {
    key: fs.readFileSync(key),
    cert: fs.readFileSync(cert)
}

const server = http2.createSecureServer(options, app);

server.on('error', err => console.log(err));

server.listen(port, () => {
   console.log('Server running')
})

我试图将 Express 服务器作为 createSecureServer() 的第二个参数传递,但我不确定是否正确,因为我收到了以下错误:

[nodemon] 2.0.2 [nodemon] 若要在任何时候重新启动,请输入rs [nodemon] 正在监视的目录: . [nodemon] 监视的扩展名:js、mjs、json [nodemon] 正在启动 node index.js _http_incoming.js:96 if (this.socket.readable) ^

TypeError: Cannot read property 'readable' of undefined at IncomingMessage._read (_http_incoming.js:96:19) at IncomingMessage.Readable.read (stream_readable.js:491:10) at resume (_stream_readable.js:976:12) at processTicksAndRejections (internal/process/task_queues.js:80:21) [nodemon] 应用程序已崩溃 - 在启动之前等待文件更改...

应该注意到,虽然我的证书是自签名的且不可靠的,但它已经成功加载。 如果可能,我尝试避免使用第三方模块,如果有帮助请指教?

2个回答

29

expressjs 仍然没有官方支持 Node http2

enter image description here

查看更多详情,请点击这里

但是你可以使用node-spdy。使用此模块,您可以在 node.js 中创建 HTTP2 / SPDY 服务器,并具有自然的 http 模块接口,并回退到常规的 https(适用于尚未支持 HTTP2 或 SPDY 的浏览器):

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

const port = 3000
const app = express()

app.get('*', (req, res) => {
  res
    .status(200)
    .json({message: 'ok'})
})
const options = {
  key: fs.readFileSync(__dirname + '/server.key'),
  cert:  fs.readFileSync(__dirname + '/server.crt')
}
console.log(options)
spdy
  .createServer(options, app)
  .listen(port, (error) => {
    if (error) {
      console.error(error)
      return process.exit(1)
    } else {
      console.log('Listening on port: ' + port + '.')
    }
  })

想要了解更多关于spdy的细节,请点击此处

如果您可以选择其他框架,则可以使用支持节点http2'KOA''HAPI'这对你可能有用

此外,请阅读发布5.0#2237。它说:

Express 5的目标是进行API调整并从Express存储库中删除所有代码, 移动到pillarjs项目中的组件(https://github.com/pillarjs), 至少提供基本的支持for promise-returning handlers和完整的HTTP / 2 功能。 Express 5将成为“pillarjs的视图”,并将 是这些组件的安排。


1
今天,您是否建议我使用Nginx代理来绕过Express并使用HTTP/2?我正在使用Kubernetes的微服务架构。 - Diesan Romero
两年过去了。这个问题在“Express”方面解决了吗?还是仍然需要使用“spdy”? - Kok How Teh
看起来 Express 5.0 仍处于测试版阶段:https://expressjs.com/ - Eric
这个还没有实施。我相信目前正在等待这个PR: https://github.com/expressjs/compression/pull/170 我正在考虑转移到fastify。 - undefined
我在 Express JS 的 Gitter 频道上发布了关于合并那个 PR 的帖子,但似乎很冷清。我认为是时候转向 Fastify 了。 - undefined

0
我找到了两种解决方案来使用Express.js运行HTTP2服务器。
解决方案1(来源:https://dirask.com/snippets/Express-js-run-server-using-HTTP2-h2-or-h2c-p5ddRD):
const fs = require('fs');
const path = require('path');
const spdy = require('spdy');        // npm install spdy
const express = require('express');  // npm install express

const credentials = {
    key: fs.readFileSync(path.join(__dirname, 'key.pem'), 'utf8'),
    cert: fs.readFileSync(path.join(__dirname, 'cert.pem'), 'utf8'),
};

const app = express();

// ...

app.get('/', (request, response) => {
    response.send('Hello World!');
});

// ...

const server = spdy.createServer(credentials, app);

server.listen(8443, () => console.log('Server started on https://localhost:8443'));

解决方案2(来源:https://dirask.com/snippets/Express-js-run-server-using-HTTP2-h2-or-h2c-1b88wp):
const fs = require('fs');
const path = require('path');
const http2 = require('http2');
const express = require('express');              // npm install express
const bridge = require('http2-express-bridge');  // npm install http2-express-bridge

const credentials = {
    key: fs.readFileSync(path.join(__dirname, 'key.pem'), 'utf8'),
    cert: fs.readFileSync(path.join(__dirname, 'cert.pem'), 'utf8'),
};

const app = bridge(express);

// ...

app.get('/', (request, response) => {
    response.send('Hello World!');
});

// ...

const server = http2.createSecureServer(credentials, app);

server.listen(8443, () => console.log('Server started on https://localhost:8443'));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接