首页 nodejs 正文
406

Nodejs: http2之push示例

Node自8.4.0开始已经内置了http2模块,利用http2的特性可以将资源事先push给客户端。客户端收到push的资源会放在缓存里,当页面解析过程中遇到了相匹配的资源时,就会直接从缓存中获取,而不需要重新发起请求。

要使用http2, 先得搭建http2服务,与http不同的是,http2需要证书。 对于本机来说,可以用如下命令生成证书:

openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout server.key -out server.crt

中途弹出的输入项都可以不输入。

有了证书之后,就可以运行http2服务了。

直接上示例代码:
const http2 = require('http2'); // node >= 8.4.0 内置 http2模块

const {
  HTTP2_HEADER_METHOD,
  HTTP2_HEADER_PATH,
  HTTP2_HEADER_STATUS,
  HTTP2_HEADER_CONTENT_TYPE
} = http2.constants;

const fs = require("fs");

//http://nodejs.cn/api/http2.html#http2_class_http2secureserver
const server = http2.createSecureServer({ 
    cert: fs.readFileSync("./server.crt"),
    key: fs.readFileSync("./server.key")
}, (req,  res) => { //设置响应handler
       const path = req.url;
       const method = req.method;
       
       const stream = res.stream;
       for (const asset of ['/public/styles.css']) {
              stream.pushStream({':path' : asset}, (err, pushStream) => {
                  if (err) throw err;
                  
                  //如果没有对pushStream的error设置handler, 则会在第二次访问的时候报错。
                  pushStream.on('error',  function(err) {
                      //do something
                  });
                  
                  if (!pushStream.destroyed) {
                      pushStream.respondWithFile(__dirname + asset);
                  }
              });
       }
       
       if (path === '/' || path === '/index.html') {
           stream.respondWithFile('./index.html');
       } else if (fs.existsSync(__dirname + path)) {
           stream.respondWithFile(__dirname + path);
       } else {
           stream.respond({
            [HTTP2_HEADER_STATUS]: 404
          });
          stream.write('Request Error: ');
          stream.end('File not found!');
       }
});

//或者用如下方法进行响应
/*
server.on('stream', (stream, headers, flags) => {
  const method = headers[HTTP2_HEADER_METHOD];
  const path = headers[HTTP2_HEADER_PATH];

  //Push resources
  for (const asset of ['/public/styles.css']) {
      stream.pushStream({':path' : asset}, (err, pushStream) => {
          if (err) throw err;
          
          //如果没有对pushStream的error设置handler, 则会在第二次访问的时候报错。
          pushStream.on('error',  function(err) {
              //do something
          });
          
          if (!pushStream.destroyed) {
              pushStream.respondWithFile(__dirname + asset);
          }
      });
  }
  // Pushing end.
  
  if (path === '/' || path === '/index.html') {
      stream.respondWithFile('./index.html');
  } else if (fs.existsSync(__dirname + path)) {
      stream.respondWithFile(__dirname + path);
  } else {
      stream.respond({
        [HTTP2_HEADER_STATUS]: 404
      });
      stream.write('Request Error: ');
      stream.end('File not found.');
  }
  
  //发送headers
  //stream.respond({
    //[HTTP2_HEADER_STATUS]: 200,
    //[HTTP2_HEADER_CONTENT_TYPE]: 'text/plain; charset=utf-8'
  //});
});
*/

server.listen(4000);

正在加载评论...