Skip to content
关注公众号,获取新课通知

参数验证


插件地址:

https://www.npmjs.com/package/egg-valparams

安装

shell
npm i egg-valparams --save

配置

js
// config/plugin.js
valparams : {
  enable : true,
  package: 'egg-valparams'
},
// config/config.default.js
config.valparams = {
    locale    : 'zh-cn',
    throwError: true
};

中间件:app/middleware/error_handler.js

module.exports = (option, app) => {
    return async function errorHandler(ctx, next) {
        try {
            await next();
            // 404 处理
            if (ctx.status === 404 && !ctx.body) {
                ctx.body = {
                    msg: "fail",
                    data: '404 错误'
                };
            }
        } catch (err) {
            // 记录一条错误日志
            app.emit('error', err, ctx);

            let status = err.status || 500;
            // 生产环境时 500 错误的详细错误内容不返回给客户端,因为可能包含敏感信息
            let error = status === 500 && app.config.env === 'prod'
                ? 'Internal Server Error'
                : err.message;

            // 从 error 对象上读出各个属性,设置到响应中
            ctx.body = {
                msg: "fail",
                data: error
            };

            // 参数验证异常
            if (status === 422 && err.message === "Validation Failed") {
                if (err.errors && Array.isArray(err.errors)) {
                    error = err.errors[0].err[0] ? err.errors[0].err[0] : err.errors[0].err[1];
                }
                ctx.body = {
                    msg: "fail",
                    data: error
                };
            }

            ctx.status = status;
        }
    };
};

在控制器里使用

js
class XXXController extends app.Controller {
  // ...
  async XXX() {
    const { ctx } = this;
    ctx.validate({
      system: {
        type: "string",
        required: false,
        defValue: "account",
        desc: "系统名称",
      },
      token: { type: "string", required: true, desc: "token 验证" },
      redirect: { type: "string", required: false, desc: "登录跳转" },
    });
    // if (config.throwError === false)
    if (ctx.paramErrors) {
      // get error infos from `ctx.paramErrors`;
    }
    let params = ctx.params;
    let { query, body } = ctx.request;
    // ctx.params        = validater.ret.params;
    // ctx.request.query = validater.ret.query;
    // ctx.request.body  = validater.ret.body;
    // ...
    ctx.body = query;
  }
  // ...
}

ValParams API 说明

参数验证处理

Valparams.setParams(req, params, options);

ParamTypeDescriptionExample
reqObjectrequest 对象,这里我们就是取相应的三种请求的参数进行参数验证
paramsObject参数的格式配置 { pname: {alias, type, required, range: {in, min, max, reg, schema }, defValue, trim, allowEmptyStr, desc[, detail] } }{sysID : {alias:'sid',type: 'int', required: true, desc: '所属系统id'}}
params[pname]String参数名
params[pname].aliasString参数别名,可以使用该参数指定前端使用的参数名称
params[pname].typeString参数类型常用可选类型有 int, string, json 等,其他具体可见下文或用 Valparams.vType 进行查询
params[pname].requiredBoolean是否必须
params[pname].rangeObject参数范围控制
params[pname].range.minALL最小值、最短、最早(不同 type 参数 含义有所差异)
params[pname].range.maxALL最大值、最长、最晚(不同 type 参数 含义有所差异)
params[pname].range.inArray在XX中,指定参数必须为其中的值
params[pname].range.regRegExp正则判断,参数需要符合正则
params[pname].range.schemaObjectjsonSchema,针对JSON类型参数有效,使用ajv对参数进行格式控制
params[pname].defValueALL默认值,没传参数或参数验证出错时生效,此时会将该值赋值到相应参数上
params[pname].trimBoolean是否去掉参数前后空格字符,默认false
params[pname].allowEmptyStrBoolean是否允许接受空字符串,默认false
params[pname].descString参数含义描述
optionsObject参数关系配置
options.choicesArray参数挑选规则[{fields: ['p22', 'p23', 'p24'], count: 2, force: true}] 表示'p22', 'p23', 'p24' 参数三选二
options.choices[].fieldsArray涉及的参数
options.choices[].countNumber需要至少传 ${count} 个
options.choices[].forceBoolean默认 false,为 true 时,涉及的参数中只能传 ${count} 个, 为 false 时,可以多于 ${count} 个
options.equalsArray参数相等[['p20', 'p21'], ['p22', 'p23']] 表示 'p20', 'p21' 两个值需要相等,'p22', 'p23' 两个值需要相等
options.equals[]Array涉及的参数(涉及的参数的值需要是相等的)
options.comparesArray参数大小关系[['p25', 'p26', 'p27']] 表示 'p25', 'p26', 'p27' 必须符合 'p25' <= 'p26' <= 'p27'
options.compares[]Array涉及的参数(涉及的参数的值需要是按顺序从小到大的)
options.casesObject参数条件判断[{when: ['p30'], then: ['p31'], not: ['p32']}] 表示 当传了 p30 就必须传 p31 ,同时不能传p32
options.cases.whenArray条件
options.cases.when[]String涉及的参数,(字符串)只要接收到的参数有这个字段即为真
options.cases.when[].field涉及的参数的名(对象)---
options.cases.when[].value涉及的参数的值(对象)需要参数的值与该值相等才为真---
options.cases.thenArray符合when条件时,需要必传的参数
options.cases.notArray符合when条件时,不能接收的参数
const Valparams = require('path/to/Valparams[/index]');
Valparams.locale('zh-cn');

function list(req, res, next) {
  let validater = Valparams.setParams(req, {
    sysID : {alias:'sid',type: 'int', required: true, desc: '所属系统id'},
    page  : {type: 'int', required: false, defValue: 1, range:{min:0}, desc: '页码'},
    size  : {type: 'int', required: false, defValue: 30, desc: '页面大小'},
    offset: {type: 'int', required: false, defValue: 0, desc: '位移'}
  }, {
    choices : [{fields: ['sysID', 'page'], count: 1, force: false}],
  });
  if (validater.err && validater.err.length) {
    console.log(validater.err);
  }
  else {
    console.log(validater);
    //{ query: { page: 1, size: 30 },
    //  body: {},
    //  params: { sysID: 2 },
    //  all: { sysID: 2, page: 1, size: 30 },
    //  err: null }
    //  raw: { query: { page: 1, size: 30 },
    //         body: {},
    //         params: { sid: 2 },
    //       }
    //}
    //do something
  }
}

返回支持的类型列表

Valparams.vType = {
  ALL        : 'all',
  STRING     : 'string',
  ARRAY      : 'array',
  DATE       : 'date',
  INT        : 'int',
  FLOAT      : 'float',
  LETTER     : 'letter',
  NUMBER     : 'number',
  IP         : 'ip',
  EMAIL      : 'email',
  PHONE      : 'phone',
  URL        : 'url',
  JSON       : 'json',
  BOOL       : 'bool',
  NULL       : 'null',
  RANGE      : 'range',
  DATERANGE  : 'dateRange',
  INTRANGE   : 'intRange',
  FLOATRANGE : 'floatRange',
  NUMBERRANGE: 'numberRange'
};
自定义本地化文件

Valparams.defineLocale(key, value);

ParamTypeDescriptionExample
keyString语言标识zh-cn
valueObject本地化内容,可配置内容有 em_type, em_minmax, em_reg, em_in, em_schema, em_required, em_range_relation, em_choices, em_equals, em_compares, em_cases---
更新已有本地化文件内容

Valparams.updateLocale(key, value);

参数含义同 defineLocale

获取本地化文件内容

Valparams.localeData(key);

ParamTypeDescriptionExample
keyString语言标识zh-cn
列出已加载的本地化文件

Valparams.locales(key);

目前已有 en 、 zh-cn

ParamTypeDescriptionExample
keyString语言标识zh-cn
设置使用的本地化文件

Valparams.locale(locale); 如: Valparams.locale('zh-cn');