使用 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
上的数据,那么您就知道服务器端正在工作。
我正在研究 http2
nodejs
,但发现一个问题 pushStream
方法不起作用
不知是不是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
上的数据,那么您就知道服务器端正在工作。