日常作业中免不了频繁处理 GET/POST 的入参,你当然可以每个 action 中都重复地去做这些事情, - 从 query 或 body 取出入参,
- 对可选的入参进行判空,
- 处理入参的类型转换,
- 对入参进行逻辑校验,数字是否超限,类型是否非法等...
但这些通用的逻辑可通过抽取到插件或服务中,避免代码冗余和重复劳动。 egg-validationEgg.js 中可通过 egg-validation 插件来减少这部分的工作量。通过该插件,上面大部分工作可转成简单的配置。 安装插件配置插件启用: 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 的逻辑进行统一。 相关资源 |