HTTP2 / SPDY推送validation:如何testing?

我正在使用节点模块spdy 实施HTTP2 / SPDY推送资源。 我遵循indutny的文档 ,并已经做了testing运行实现他的例子到我的server.js。

问题是双重的; 我没有得到任何日志中的错误,也没有看到在浏览器中的alert 。 在开发者控制台中我也没有看到任何改变。 如果我设置一个伪造的推送url,我不会收到任何回应/错误等。 我相信在理论上,优先级应该从中medium High (?)。 请参阅屏幕截图。

有没有另外一种方法来testing浏览器是否被推送? 或者,我的脚本中是否有错误( 请检查不一致 )? 另外,抛出什么stream.on('error', function() {});

在Chrome(在ChromeBook上)中进行testing,在Chrome中validation了nodejs v5.1.0,npm v3.3.12 – 启用了H2。

server.js:

 var environment = '../env/' + process.env.NODE_ENV // Process User config , fS = require('fs') , jsonFile = fS.readFileSync(environment + '/config.json') , jsonString, hostIp, hostPort, cacheExp, cps; try { jsonString = JSON.parse(jsonFile); var SERV_HOST = jsonString['hostIp'] , SERV_PORT = jsonString['hostPort'] , CACHE_EXP = jsonString['cacheExp'] , CPS = jsonString['cps'] , xPowerBy = 'OceanPress' , xFrameOptions = 'DENY' , xXSSProtection = '1; mode=block' , xContentTypeOption = 'nosniff'; } catch (err) { console.log('There is an error parsing the json file : ' + err); } // Load modules var fs = require('fs') , watch = require('staticsmith-watch') , buffet = require('buffet')({root: environment + '/_public'}) , spdy = require('spdy') // spdy options , options = { key: fs.readFileSync(environment + '/keys/key.pem') , cert: fs.readFileSync(environment + '/keys/cert.pem') // SPDY-specific options , spdy: { protocols: [ 'h2','spdy/3.1', 'spdy/3', 'spdy/2','http/1.1', 'http/1.0' ] , plain: false , maxStreams: 200 , connection: { windowSize: 1024 * 1024 , autoSpdy31: false } } // Set ip and port , host: SERV_HOST , port: SERV_PORT } // Security header options , security = [ { name: 'X-Powered-By', option: xPowerBy } , { name: 'x-frame-options', option: xFrameOptions } , { name: 'X-XSS-Protection', option: xXSSProtection } , { name: 'X-Content-Type-Options', option: xContentTypeOption } , { name: 'Cache-Control', option: CACHE_EXP } , { name: 'Content-Security-Policy', option: CPS } , { name: 'server', option: 'Who knows' } ]; if (process.env.NODE_ENV == 'production') { spdy.createServer(options, function(req, res) { // Add Content Security Rules for(var i = 0; i < security.length; i++) { res.setHeader(security[i].name, security[i].option); } // @see https://www.npmjs.com/package/buffet buffet(req, res, function (err, result) { // Push JavaScript asset (main.js) to the client var stream = res.push('/js/main.js', { req: {'accept': '*/*'}, res: {'content-type': 'application/javascript'} }); stream.on('acknowledge', function() { console.log("Stream ACK"); }); stream.on('error', function() { console.error("stream ERR"); }); stream.end('alert("hello from push stream!");'); // write main response body and terminate stream res.end('<script src="/js/main.js"></script>'); // There was an error serving the file? Throw it! if (err) { console.error("Error serving " + req.url + " - " + err.message); // Respond to the client res.writeHead(err.status, err.headers); } }); }).listen(options.port, options.host); console.log("serving at https://" + options.host + ":" + options.port); console.log("On Node v" + process.versions.node); console.log("On npm v" + process.versions.npm); watch({ pattern: '**/*', livereload: true, }); } 

更新:我还补充说:

  stream.on('acknowledge', function() { console.log('stream ACK'); }); 

没有写控制台日志 – 就像这个function已经死了。

具有推送stream的开发控制台(main.js):
推送控制台(main.js)

这里有几个问题。

  1. 只有在请求的URL与磁盘上的文件匹配时才会调用自助callback。 就像expression中间件一样,它本质上是nextfunction。 因此,你从来没有真正推动任何事情。

  2. res.push的第一个参数是一个URL,而不是文件系统path。

  3. 在HTTP / 1.1连接上不会存在res.push ; 你需要确保它在那里,否则你会抛出一个未捕获的exception(和崩溃)。

这是一个简化的工作示例。

 spdy.createServer({ key: fs.readFileSync('./s.key'), cert: fs.readFileSync('./s.crt') }, function(req, res) { if (req.url == '/') { res.writeHead(200, { 'Content-Length': 42 }); res.end('<h1>Hi</h1><script src="main.js"></script>'); if (res.push) { // Push JavaScript asset (main.js) to the client var stream = res.push('/main.js', { req: {'accept': '**/*'}, res: {'content-type': 'application/javascript'} }); stream.on('error', function() { console.error(err); }); stream.end('alert("hello from push stream!");'); } } else { res.writeHead(404); res.end(); } }).listen(777); 

至于在Chrome中实际validation事情正在推动,打开一个新的标签,并inputchrome://net-internals/#http2 。 单击与您的服务器的HTTP / 2会话的ID,然后单击左侧窗格中的会话。 与最初的请求混在一起,你会看到类似于:

 t= 3483 [st= 19] HTTP2_SESSION_RECV_PUSH_PROMISE --> :method: GET :path: /main.js :scheme: https :authority: localhost:777 --> id = 3 --> promised_stream_id = 4 t= 3483 [st= 19] HTTP2_SESSION_RECV_HEADERS --> fin = false --> :status: 200 --> stream_id = 4 t= 3483 [st= 19] HTTP2_SESSION_RECV_DATA --> fin = true --> size = 0 --> stream_id = 4 t= 3546 [st= 82] HTTP2_STREAM_ADOPTED_PUSH_STREAM --> stream_id = 4 --> url = "https://localhost:777/main.js" 

(我没有看到开发工具中的main.js更改的优先级 – 它仍然是中等。)

在Chrome检查器中 ,我发现在服务器推送资源时很容易识别。

首先:在networking视图/选项卡中,相关资源几乎不会显示发送request并在瀑布中显示“正在等待(TTFB)”( 请参见下图 )。

theme.min.csstheme.min.js资源被推送:

在这里输入图像说明

第二:点击推送的资源后,打开“Headers”窗格并检查底部的“Request Headers”面板,检查Provisional headers are shown 。 如果资源显示警告,则会被推送。 看到这个答案为什么你会看到这个警告。

头部检查员:

在这里输入图像说明

如果你需要一些关于推送资源的更详细的信息,使用@ josh3736答案第二部分所述的chrome://net-internals/#http2方法也可以。 但是如果你需要一个快速的方法来validation这个资源是否被客户端推送了,那么查看这个瀑布就会显示出来。