https://eggjs.org/zh-cn/basics/middleware.html#mobileAside
Middleware中间件文档 https://eggjs.github.io/zh/guide/middleware.html
eggjs中间件的目录 src/app/middleware

image.png

什么是中间件

在NodeJS中,中间件主要是指封装所有Http 请求细节处理的方法

每个中间件都会执行2次,

一次 Http 请求通常包含很多工作,如

  • 记录日志、ip过滤、查询字符串、请求体解析、
  • Cookie处理、权限验证、
  • 参数验证、
  • 异常处理等

但对于Web应用而言,并不希望接触到这么多细节性的处理,

  • 因此引入中间件来简化和隔离这些基础设施与业务逻辑之间的细节,
  • 让开发者能够关注在业务的开发上,以达到提升开发效率的目的

自定义 koa中间件实现用户认证授权
koa-jwt中间件实现用户认证和鉴权

config.middleware

中间件可以帮我们解决一些不必要放在路由中的一些逻辑处理
在匹配到路由 之前 或者 之后做的一些事情

  • next()
  • 每次路由变化都会触发 中间件
  • 因为 egg 是基于 koa的 所以koa得洋葱模型也被 egg所采用

中间件必须返回 next() 否则不会往下执行
await next();

中间件的名字要和 ap/middleware下文件的名字保持一致

  1. config.middleware = [ 'httpLog', 'httpError', 'forbiddenIP' ];

洋葱圈模型

洋葱圈模型 https://eggjs.org/zh-cn/intro/egg-and-koa.html#midlleware

m1 start
m2 start

m2 end
m1 end

config.middleware中,注册的中间件是有执行的先后顺序的
中间件执行,按照洋葱圈模型的执行顺序,所以 中间件必须返回 next() 否则不会往下执行
await next();

  1. config.middleware = ['m1', 'm2'];

中间件模板

options 是给 中间件传来的参数
app 是当前的应用实例

  1. 'use strict';
  2. module.exports = (options, app) => {
  3. return async (ctx, next) => {
  4. console.log('options', options, app);
  5. await next();
  6. };
  7. };

config.default.js

在 src/config/config.default.js 中注册中间件
在路由匹配的时候 执行了下 并且参数也正确传入进去了

  1. // 配置中间件 文件名字要对应起来
  2. config.middleware = ['httpLog'];
  3. // 给中间件传参
  4. config.httpLog = {
  5. type: 'all'
  6. }

options参数
image.png

httpLog中间件

  1. 'use strict';
  2. const dayjs = require('moment');
  3. const fs = require('fs');
  4. /**
  5. * 拦截 http请求,将请求输入到 /logs/http/httpLog.log文件中
  6. * @param options
  7. * @param app
  8. * @returns {(function(*, *): Promise<void>)|*}
  9. */
  10. // eslint-disable-next-line no-unused-vars
  11. module.exports = (options, app) => {
  12. return async (ctx, next) => {
  13. const start = Date.now();
  14. const startedAt = dayjs().format('YYYY-MM-DD HH:mm:ss');
  15. const {
  16. method, url, body,
  17. } = ctx.request;
  18. // app.baseDir = /Users/lulongwen/Sites/珑文汽修/egg-server
  19. // console.log('options', options, app.baseDir);
  20. await next();
  21. const log = {
  22. method, url, body,
  23. startedAt,
  24. endAt: dayjs().format('YYYY-MM-DD HH:mm:ss'),
  25. time: Date.now() - start,
  26. };
  27. const data = `${dayjs().format('YYYY-MM-DD HH:mm:ss')} [httpLog] ${JSON.stringify(log)} \r\n`;
  28. const output = `${ctx.app.baseDir}/logs/http/httpLog.log`;
  29. fs.appendFileSync(output, data);
  30. };
  31. };