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):
这里有几个问题。
-
只有在请求的URL与磁盘上的文件不匹配时才会调用自助callback。 就像expression中间件一样,它本质上是
next
function。 因此,你从来没有真正推动任何事情。 -
res.push
的第一个参数是一个URL,而不是文件系统path。 -
在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.css
& theme.min.js
资源被推送:
第二:点击推送的资源后,打开“Headers”窗格并检查底部的“Request Headers”面板,检查Provisional headers are shown
。 如果资源显示警告,则会被推送。 看到这个答案为什么你会看到这个警告。
头部检查员:
如果你需要一些关于推送资源的更详细的信息,使用@ josh3736答案第二部分所述的chrome://net-internals/#http2
方法也可以。 但是如果你需要一个快速的方法来validation这个资源是否被客户端推送了,那么查看这个瀑布就会显示出来。