使用 Nodejs pushStream 方法的服务器推送不起作用

Server Push with Nodejs pushStream method is not working

我正在研究 http2 nodejs,但发现一个问题 pushStream 方法不起作用

(client side do not show "Pushed/[fileName]" on developer tool)

不知是不是nodejs版本的问题(我安装的是最新版v9.8.0)

我的代码如下:

server.js

'use strict'

const fs = require('fs');
const path = require('path');
const http2 = require('http2');
const utils = require('./utils');

const { HTTP2_HEADER_PATH } = http2.constants;

const PORT = process.env.PORT || 3000;

// The files are pushed to stream here
function push(stream, path) {
  const file = utils.getFile(path);
  if (!file) {
    return;
  }
  stream.pushStream({ [HTTP2_HEADER_PATH]: path}, (err, pushStream, headers) => {
    if (err) throw err;
    pushStream.respondWithFD(file.content, file.headers)
  });
}

// Request handler
function onRequest(req, res) {
  const reqPath = req.headers[':path'] === '/' ? '/index.html' : req.headers[':path']
  const file = utils.getFile(reqPath);

  // 404 - File not found
  if (!file) {
    res.statusCode = 404;
    res.end();
    return;
  }

  // Push with index.html
  if (reqPath === '/index.html') {
    push(res.stream, '/assets/main.js');
    push(res.stream, '/assets/style.css');
  } else {
    console.log("requiring non index.html")
  }

  // Serve file
  res.stream.respondWithFD(file.content, file.headers);
}

// creating an http2 server
const server = http2.createSecureServer({
  cert: fs.readFileSync(path.join(__dirname, '/certificate.crt')),
  key: fs.readFileSync(path.join(__dirname, '/privateKey.key'))
}, onRequest);

// start listening
server.listen(PORT, (err) => {
  if (err) {
    console.error(err);
    return -1;
  }
  console.log(`Server listening to port ${PORT}`);
});

utils.js

'use strict';
const fs = require('fs');
const mime = require('mime');

module.exports = {
  getFile: function (path) {
    const filePath = `${__dirname}/public${path}`;
    try {
      const content = fs.openSync(filePath, 'r');
      const contentType = mime.getType(filePath);
      return {
        content,
        headers: {
          'content-type': contentType
        }
      };
    } catch (e) {
      return null;
    }
  }
}

2020 年 01 月 28 日更新

已解决:原因是chromev65最新版本。有错误,导致客户端不信任 PUSH_PROMISE 框架。我备份 chrome v64 然后它现在可以工作了。

我没有尝试 运行 你的代码,但注意到 Chrome 不允许 HTTP/2 使用不受信任的 HTTPS 证书推送(例如 self-signed尚未添加到信任库)。 Raised a bug with the Chrome team.

如果您有红色的不安全挂锁项,那么您也可能会遇到此问题。将证书添加到您的信任库中,重新启动 Chrome 并重新加载您应该获得绿色挂锁的站点。

注意 Chrome 需要一个主题备用名称 (SAN) 字段与域匹配的证书,因此如果您只有较旧的主题字段,即使将其添加到您的信任库。

另一种选择是查看 Chrome HTTP2 帧,方法是在 URL:

中输入
chrome://net- internals/#http2

如果您看到推送承诺帧(带有 promised_stream_id),然后是 headers 和 promised_stream_id 上的数据,那么您就知道服务器端正在工作。