1. 程式人生 > >Egg入門學習(三)---理解中介軟體作用

Egg入門學習(三)---理解中介軟體作用

Egg是基於koa的,因此Egg的中介軟體和Koa的中介軟體是類似的。都是基於洋蔥圈模型的。

在Egg中,比如我想禁用某些IP地址來訪問我們的網頁的時候,在egg.js中我們可以使用中介軟體來實現這個功能,中介軟體的作用無非就是說在Egg的外層在包一層來判斷某些事情是否符合要求,也就是在洋蔥圈模型外面再進行包一層。
在Egg入門二學習中(https://www.cnblogs.com/tugenhua0707/p/10226799.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. 因此整個專案的目錄變成如下這個樣子:

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

編寫中介軟體

我們在 app/middleware 目錄中 新建一個 forbidIp.js 檔案,該檔案的作用是 禁用某些ip地址訪問我們的網頁。因此程式碼編寫如下:

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 中加入下面的配置就可以完成了中介軟體的開啟和配置:程式碼如下:

// 配置需要的中介軟體,陣列的順序即為中介軟體載入的順序
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配置了。

如上中介軟體程式碼,它接收兩個引數:options 和 app;
options引數指的是 app.config[${middlewareName}]傳進來。我們在 如上中介軟體程式碼中列印 options; console.log(options); 及 列印 console.log(app); 如下圖所示:

可以看到 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原始碼中中介軟體程式碼