Egg.js 中入参的校验
Egg.js 中入参的校验
日常作业中免不了频繁处理 GET/POST 的入参,你当然可以每个 action 中都重复地去做这些事情,
- 从 query 或 body 取出入参,
- 对可选的入参进行判空,
- 处理入参的类型转换,
- 对入参进行逻辑校验,数字是否超限,类型是否非法等...
但这些通用的逻辑可通过抽取到插件或服务中,避免代码冗余和重复劳动。
egg-validation
Egg.js 中可通过 egg-validation 插件来减少这部分的工作量。通过该插件,上面大部分工作可转成简单的配置。
安装插件
$ yarn add egg-validate
配置插件
启用:
config/plugin.ts
const plugin: EggPlugin = {
// ...
validate: {
enable: true,
package: 'egg-validate',
},
// ...
};
export default plugin;
配置插件:
config/config.default.ts
export default (appInfo: EggAppInfo) => {
const config = {} as PowerPartial<EggAppConfig>;
// ...
config.validate = {
convert: true,
widelyUndefined:true
};
// ...
};
其配置项为 node-modules/parameter 的所有可用配置项,因为该插件其实就是后者的 Egg.js 封装。
convert
会对入参进行转换,建议开启。举个例子,使用表单中默认的 submit 类型按钮提交表单时,提交过来的往往是序列化后的字符串,那些期望是数字类型的字段就会始终验证不过。而开启此项后,会对入参按希望的类型进行转换。widelyUndefined
开启后,会把空字符串,NaN
,null
这些转成undefined
,将这些异常的数据进行了统一,方便后续处理。
使用
插件在 app
及 context
上扩展了 validator
对象,通过调用 validator.validate(rules,data)
来进行验证。
比如接收一个名为 name
的字符串入参:
app/controller/home.ts
const errors = this.app.validator.validate({ name: 'string' }, this.request.body);
if (errors) {
this.ctx.body = errors;
}
验证规则
validate
第一个参数为规则,它是个对象。其每个字段对应同名的入参。字段的值可以是简单的字符串,指定字段的类型,也可以是对象,在这个对象里进行更加详细的规则指定。
const rules = {
param1: 'string', // 必填的字符串入参
param2: 'string?', // 可选的字符串入参
param3: {
type: 'int', // 整形入参
required: false, // 该入参可选
min: 0, // 该入参的最小值
max: 10, // 该入参的最大值
},
};
规则默认入参是必填的,对于可选的入参,可通过在类型后加问号,与 TypeScript 类似,也可以显式指定 required: false
。
预设可用的参数类型参见 parameter。
针对参数的规则配置,根据参数的类型,有不同的配置顶,比如对于数字类型,可配置其最大最小值;对于枚举,可定义其候选值,一旦入参不在这些值之内,便验证不通过。每种类型可用的配置项参见 parameter。
自定义验证规则
如果上面文档中预设的这些类型无法满足需求,可通过 validator.addRule(type,checker)
自定义规则来扩充。
其中 type
为新增规则的类型名, checker
为用来校验的正则或方法。如果是个方法,其入参为规则本身及需要校验的数据,文档里没有体现其入参,可参考源码。
checker.call(self, rule, obj[key], obj);
比如增加一种类型为 jsonString
的验证规则,限定入参必需为合法的 JSON 数据。
app.ts
export default (app) => {
app.validator.addRule('jsonString', (_rule, value) => {
try {
JSON.parse(value);
} catch (err) {
return 'must be json string';
}
});
};
示例代码
一个可本地运行调试,配合了预设的验证规则及自定义的规则的示例,完整代码可在 GitHub 找到。
结论
写了过多的重复的代码后,比如这种入参的校验,就应该想想如何优雅地来处理这些重复的工作,无论是自己造轮子,还是找轮子。入参的校验如此之常见,进而,甚至可以去追求一套前后台通用的校验逻辑,将浏览器端的 JavaScript 与 Node.js 的逻辑进行统一。