使用Joi來對egg項目進行參數校驗
Joi是什麼
Joi 是 hapijs 自帶的數據校驗模塊,高度封裝常用的參數校驗功能. Joi文檔
項目中引入Joi
將Joi掛載在app對象下, app.js
const Joi = require('@hapi/joi');
const path = require('path');
class AppBootHook {
constructor(app) {
this.app = app;
const directory = path.join(app.config.baseDir, 'app/validator');
app.Joi = Joi;
app.loader.loadToApp(
directory,
'validator'
);
}
}
module.exports = AppBootHook;
新建Joi校驗文件
base_contoller文件下添加Joi攔截
const { Controller } = require('egg');
class BaseController extends Controller {
constructor(request, response, app) {
super(request, response, app);
this.options = {
//允許存在不在 schema 中的字段
allowUnknown: true,
//過濾不存在 schema 中的字段
stripUnknown: true,
//可以在檢測到第一個錯誤時立即返回,默認false(檢查全部)
abortEarly: true,
//可以嘗試將值轉換爲所需的類型(例如,將字符串轉換爲數字)
convert: true,
messages: {
'any.required': '{{#label}}不能爲空',
'number.base': '{{#label}}參數錯誤',
'string.base': '{{#label}}參數錯誤'
}
};
}
assert(schema, params) {
const Joi = this.app.Joi;
const result = Joi.object(schema).validate(params, this.options);
if (result.error) {
throw new Error(result.error.details[0].message);
}
}
}
module.exports = BaseController;
添加中間件進行參數攔截校驗
/**
* 統一錯誤處理
* @param options {*}
* @param app
* @returns {errorHandler}
*/
module.exports = (options, app) => {
return async function errorHandler(ctx, next) {
try {
await next();
} catch (err) {
ctx.error = err;
let message = err.message;
if (err.status === 500) {
app.logger.error(err);
message = err.stack;
if (app.config.env === 'prod') {
message = '服務暫時不可用,正在努力修復中。';
}
}
ctx.status = err.status || 200;
ctx.body = {
code: 1,
message,
status: ctx.status
};
}
};
};
contorller使用方法
以獲取主題列表接口爲例
// 獲取主題列表
this.assert(
{
forumId: this.app.Joi.number().required().label('版塊ID')
},
this.ctx.query);