深入解析express-validator自定义验证与错误处理
express-validator 项目地址: https://gitcode.com/gh_mirrors/exp/express-validator
express-validator是一个功能强大的Express中间件,用于验证和清理请求数据。在实际开发中,我们经常需要超越其内置功能,实现自定义验证逻辑和错误处理。本文将详细介绍如何在express-validator中进行高级定制。
自定义验证器和清理器
自定义验证器实现
自定义验证器是处理特定业务逻辑验证的强大工具。它们可以同步或异步执行,只需返回一个表示验证结果的布尔值、Promise或抛出错误。
典型应用场景:
- 检查邮箱是否已被注册
- 验证密码和确认密码是否匹配
- 检查用户名是否符合特定格式要求
// 检查邮箱是否已注册的异步验证器示例
app.post('/register',
body('email').custom(async email => {
const user = await User.findByEmail(email);
if (user) {
throw new Error('该邮箱已被注册');
}
return true;
}),
(req, res) => {
// 处理请求
}
);
注意事项:
- 返回
true
表示验证通过 - 返回
false
或抛出错误表示验证失败 - 异步验证器必须返回Promise
自定义清理器实现
清理器用于转换输入数据,使其符合特定格式或标准。与验证器不同,清理器不验证数据,而是修改数据。
典型应用场景:
- 将字符串ID转换为MongoDB ObjectId
- 去除字符串两端的空白
- 转换日期格式
// 将字符串ID转换为ObjectId的清理器示例
app.get('/user/:id',
param('id').customSanitizer(value => new ObjectId(value)),
(req, res) => {
// req.params.id现在是一个ObjectId对象
}
);
重要提示:如果清理器没有返回值,字段值将变为undefined
!
错误消息定制
express-validator提供了多层次的错误消息定制方式,使错误反馈更加友好和具体。
验证器级别消息
使用.withMessage()
方法为特定验证规则设置错误消息:
body('email')
.isEmail().withMessage('请输入有效的邮箱地址')
.isLength({ max: 50 }).withMessage('邮箱长度不能超过50个字符');
自定义验证器消息
在自定义验证器中抛出错误时,错误信息将自动作为验证失败消息:
body('username').custom(username => {
if (username.includes('admin')) {
throw new Error('用户名不能包含"admin"');
}
return true;
});
字段级别消息
在创建验证链时设置默认错误消息,作为所有验证规则的备用消息:
body('password', '密码格式不正确')
.isLength({ min: 8 }) // 使用默认消息
.matches(/\d/).withMessage('密码必须包含数字'); // 覆盖默认消息
ExpressValidator类的高级用法
对于需要重用自定义验证逻辑的项目,ExpressValidator
类提供了完美的解决方案。它允许你创建预配置的验证器实例,包含所有自定义验证和清理逻辑。
创建自定义验证器实例
import { ExpressValidator } from 'express-validator';
const { body, validationResult } = new ExpressValidator(
{
// 自定义验证器
isValidPhone: value => /^1[3-9]\d{9}$/.test(value)
},
{
// 自定义清理器
trimAll: value => typeof value === 'string' ? value.trim() : value
}
);
// 使用自定义验证器和清理器
app.post('/user',
body('phone').isValidPhone().withMessage('请输入有效的手机号码'),
body('name').trimAll(),
(req, res) => {
const errors = validationResult(req);
// 处理验证结果
}
);
TypeScript支持
对于TypeScript项目,可以创建类型化的验证链和模式:
import { ExpressValidator, CustomValidationChain, CustomSchema } from 'express-validator';
const myValidator = new ExpressValidator({ isValidPhone });
const { body, checkSchema } = myValidator;
type MyValidationChain = CustomValidationChain<typeof myValidator>;
type MySchema = CustomSchema<typeof myValidator>;
const phoneValidator = (): MyValidationChain =>
body('phone').isValidPhone().withMessage('无效的手机号');
const userSchema: MySchema = {
phone: {
isValidPhone: true
}
};
最佳实践建议
- 错误消息:始终提供明确的错误消息,帮助用户理解问题所在
- 异步验证:对于数据库查询等IO操作,使用异步验证器
- 代码复用:通过
ExpressValidator
类封装常用验证逻辑 - 安全性:清理器应在验证前执行,确保验证的是最终数据
- 性能:对于复杂验证,考虑添加早期返回以减少不必要的处理
通过灵活运用express-validator的自定义功能,你可以构建出既强大又易于维护的验证系统,满足各种复杂的业务需求。
express-validator 项目地址: https://gitcode.com/gh_mirrors/exp/express-validator
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考