首页 > 语言 > JavaScript > 正文

详解基于Node.js的HTTP/2 Server实践

2024-05-06 15:33:42
字体:
来源:转载
供稿:网友

虽然HTTP/2目前已经逐渐的在各大网站上开始了使用,但是在目前最新的Node.js上仍然处于实验性API,还没有能有效解决生产环境各种问题的应用示例。因此在应用HTTP/2的道路上我自己也遇到了许多坑,下面介绍了项目的主要架构与开发中遇到的问题及解决方式,也许会对你有一点点启示。

配置

虽然W3C的规范中没有规定HTTP/2协议一定要使用ssl加密,但是支持非加密的HTTP/2协议的浏览器实在少的可怜,因此我们有必要申请一个自己的域名和一个ssl证书。

本项目的测试域名是 you.keyin.me ,首先我们去域名提供商那把测试服务器的地址绑定到这个域名上。然后使用Let's Encrypt生成一个免费的SSL证书:

sudo certbot certonly --standalone -d you.keyin.me

输入必要信息并通过验证之后就可以在 /etc/letsencrypt/live/you.keyin.me/ 下面找到生成的证书了。

改造Koa

Koa是一个非常简洁高效的Node.js服务器框架,我们可以简单改造一下来让它支持HTTP/2协议:

class KoaOnHttps extends Koa { constructor() {  super(); } get options() {  return {   key: fs.readFileSync(require.resolve('/etc/letsencrypt/live/you.keyin.me/privkey.pem')),   cert: fs.readFileSync(require.resolve('/etc/letsencrypt/live/you.keyin.me/fullchain.pem'))  }; } listen(...args) {  const server = http2.createSecureServer(this.options, this.callback());  return server.listen(...args); } redirect(...args) {  const server = http.createServer(this.callback());  return server.listen(...args); }}const app = new KoaOnHttps();app.use(sslify());//...app.listen(443, () => {logger.ok('app start at:', `https://you.keyin.cn`);});// receive all the http request, redirect them to httpsapp.redirect(80, () => {logger.ok('http redirect server start at', `http://you.keyin.me`);});

上述代码简单基于Koa生成了一个HTTP/2服务器,并同时监听80端口,通过sslify中间件的帮助自动将http协议的连接重定向到https协议。

静态文件中间件

静态文件中间件主要用来返回url所指向的本地静态资源。在http/2服务器中我们可以在访问html资源的时候通过服务器推送(Server push)将该页面所依赖的js/css/font等资源一起推送回去。具体代码如下:

const send = require('koa-send');const logger = require('../util/logger');const { push, acceptsHtml } = require('../util/helper');const depTree = require('../util/depTree');module.exports = (root = '') => { return async function serve(ctx, next) {  let done = false;  if (ctx.method === 'HEAD' || ctx.method === 'GET') {   try {    // 当希望收到html时,推送额外资源。    if (/(/.html|//[/w-]*)$/.test(ctx.path)) {     depTree.currentKey = ctx.path;     const encoding = ctx.acceptsEncodings('gzip', 'deflate', 'identity');     // server push     for (const file of depTree.getDep()) {      // server push must before response!      // https://huangxuan.me/2017/07/12/upgrading-eleme-to-pwa/#fast-skeleton-painting-with-settimeout-hack      push(ctx.res.stream, file, encoding);     }    }    done = await send(ctx, ctx.path, { root });   } catch (err) {    if (err.status !== 404) {     logger.error(err);     throw err;    }   }  }  if (!done) {   await next();  } };};            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选