Egg入门学习(三)---理解中间件做用

Egg是基于koa的,所以Egg的中间件和Koa的中间件是相似的。都是基于洋葱圈模型的。css

在Egg中,好比我想禁用某些IP地址来访问咱们的网页的时候,在egg.js中咱们可使用中间件来实现这个功能,中间件的做用无非就是说在Egg的外层在包一层来判断某些事情是否符合要求,也就是在洋葱圈模型外面再进行包一层。
在Egg入门二学习中(https://www.cnblogs.com/tugenhua0707/p/10226799.html), 咱们最后的项目的目录结构以下:html

egg-demo2
├── app
│   ├── controller
│   │   └── home.js
|   |   |-- index.js
│   └── router.js
│   ├──public
|   | |---css
|   | | |-- index.css
|   | |---js
|   | | |-- index.js
|   |--- view
|   | |-- index
|   | | |-- list.tpl(模板文件list)
|   |--- service
|   | |--- index.js
├── config
│   └── config.default.js
└── package.json

在Egg中,中间件也有本身的配置和目录,所以在Egg中约定了中间件是放在 app/middleware 目录中的文件。该文件须要exports一个普通的function. 所以整个项目的目录变成以下这个样子:git

egg-demo2
├── app
│   ├── controller                # 用于解析用户的输入,处理后返回响应的结果
│   │   └── home.js
|   |   |-- index.js
│   └── router.js                 # 用于配置url路由的配置规则
│   ├──public                     # 资源文件目录
|   | |---css
|   | | |-- index.css
|   | |---js
|   | | |-- index.js
|   |--- view                     # 存放模板文件的目录
|   | |-- index
|   | | |-- list.tpl(模板文件list)
|   |--- service                  # 编写业务逻辑的目录
|   | |--- index.js
|   |--- middleware               # 用于编写中间件的目录
|   | |--- xxx.js
├── config                        # 相关的配置文件
│   └── config.default.js
└── package.json

编写中间件github

咱们在 app/middleware 目录中 新建一个 forbidIp.js 文件,该文件的做用是 禁用某些ip地址访问咱们的网页。所以代码编写以下:json

module.exports = (options, app) => {
  return async function forbidIp(ctx, next) {
    console.log(options);
    console.log('---------');
    console.log(app);

    // 须要被屏蔽的id
    const ids = options.forbidips;
    // 获取客户端的ip
    const clientIp = ctx.request.ip;

    const isHasIp = ids.some(val => {
      if (val === clientIp) {
        return true;
      }
      return false;
    });
    if (isHasIp) {
      ctx.status = 403;
      ctx.body = '您的IP已经被屏蔽掉了';
    } else {
      await next();
    }
  }
}

使用中间件数组

如上中间件编写完成后,咱们还须要手动挂载中间件。所以咱们须要在 config/config.default.js 中加入下面的配置就能够完成了中间件的开启和配置:代码以下:app

// 配置须要的中间件,数组的顺序即为中间件加载的顺序
exports.middleware = [
  'forbidIp'
];
// 上面中间件的配置 ip
exports.forbidIp = {
  forbidips: [
    '192.168.1.12',
    '127.0.0.1',
  ]
}

注意:如上 exports.middleware = ['forbidIp']; 该 forbidIp 指向与 app/middleware 中的 forbidIp.js, 所以须要注意大小写。也就是说是 forbidIp.js 中间件。而后下面的 exports.forbidIp = {}; forbidIp中间件的名字也须要同样的。exports.forbidIp 里面的对象就是中间件的ip配置了。koa

如上中间件代码,它接收两个参数:options 和 app;
options参数指的是 app.config[${middlewareName}]传进来。咱们在 如上中间件代码中打印 options; console.log(options); 及 打印 console.log(app); 以下图所示:
async

能够看到 console.log(options); options参数的值就是 config配置项中的 学习

{
  forbidips: [
    '192.168.1.12',
    '127.0.0.1',
  ]
}

打印 config.log(app) 的值,如上图所示;它的含义是指 当前应用Application的实列。

所以咱们继续访问 http://127.0.0.1:7001/ 后能够看到以下信息,页面被禁用了。以下图所示:

若是咱们继续把 config/config.default.js 配置代码改为其余的ip地址,代码以下:

// 配置须要的中间件,数组的顺序即为中间件加载的顺序
exports.middleware = [
  'forbidIp'
];
// 上面中间件的配置 ip
exports.forbidIp = {
  forbidips: [
    '192.168.1.12',
    '127.0.0.12'
  ]
}

咱们继续访问 http://127.0.0.1:7001/ 后,页面就正常了。以下所示:

二:在 router.js路由中使用中间件。

如上使用中间件都是全局的,每一次请求都会处理的,可是有时候我想针对单个路由生校的话,咱们就不须要再 config中配置了。咱们直接在路由中配置便可。

router.js在未使用中间件处理以前代码是以下:

module.exports = app => {
  const { router, controller } = app;
  router.get('/', controller.home.index);
  router.get('/index', controller.index.list);
}

如今咱们须要在 router.get('/'); 下使用禁用ip中间件,所以咱们能够先注释掉 config中全局的中间件配置。咱们能够直接在 router.js 下处理便可,以下代码所示:

首先:config/config.default.js 代码注释掉中间件:

/*
// 配置须要的中间件,数组的顺序即为中间件加载的顺序
exports.middleware = [
  'forbidIp'
];
// 上面中间件的配置 ip
exports.forbidIp = {
  forbidips: [
    '192.168.1.12',
    '127.0.0.12'
  ]
}
*/

而后在单个路由中使用中间件, router.js的代码以下:

module.exports = app => {
  const { router, controller } = app;

  // 路由中使用中间件
  const forbidIp = app.middleware.forbidIp({
    forbidips: [
      '127.0.0.1'
    ]
  });

  router.get('/', forbidIp, controller.home.index);
  router.get('/index', controller.index.list);
}

而后咱们继续访问 http://127.0.0.1:7001/ 后,页面也会提示该ip地址已经被屏蔽掉了。

更多的关于中间件配置介绍,请看官网中介绍的(https://eggjs.org/zh-cn/basics/middleware.html)

查看github源码中中间件代码

相关文章
相关标签/搜索