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)