- 后端
【免费下载链接】express-validator
An express.js middleware for validator.js.
express-validator 是一组面向 Express 的中间件集合,它在 validator.js 提供的校验器(validator)与净化器(sanitizer)之上,为你的路由添加声明式的字段校验能力。本文将以 5.2.0 版本文档的 Getting Started 指南为主体,结合仓库源码带你从安装起步,一步步把一段不设防的 Express 路由改造成带check()校验链与validationResult()错误收集的完整示例,并理解校验链底层如何串行执行、错误对象如何结构化输出,为后续进阶功能(净化、自定义校验器、自定义错误消息、通配符、Schema 校验)打下基础。
express-validator 是什么
express-validator 本质上是一个薄封装层:它把 validator.js 的校验与净化函数包装成Express 中间件(Middleware),让你能够像声明路由一样声明"某个字段必须满足哪些规则"。官方对其定位的描述是:
express-validator is a set of express.js middlewares that wraps validator.js validator and sanitizer functions.
在阅读本指南前,官方文档建议你先具备 express.js 模块的基础知识(中间件、路由、req/res的基本用法),因为校验中间件需要嵌入到 Express 的路由处理流程中才能发挥作用。
当前仓库即 express-validator 的完整源码工程(package.json 中版本号为 7.3.2),核心实现位于src/目录,通过 TypeScript 编写并编译输出到lib/。本文讲解的入门流程在 5.2.0 及后续版本中一脉相承:check()构建校验链、校验链作为中间件挂载、validationResult()汇总错误。
安装与运行环境
使用 npm 安装即可(5.2.0 文档要求 Node.js 6 或更新版本):
npm install --save express-validator需要说明的是,随着项目演进,当前仓库 package.json 的engines字段已要求node >= 14.0.0,并且依赖了validator ~13.x与lodash。如果你使用较新的 Node 版本,直接npm install express-validator后即可开始下面的示例。安装完成后,项目会同时提供编译产物与类型声明(main: ./lib/index.js、types: ./lib/index.d.ts),TypeScript 用户开箱即用。
基础指南:从无校验路由到带校验路由
第一步:先写一个不设防的路由
入门示例从"创建用户"接口开始。下面的路由直接读取req.body并落库,完全没有对输入做任何检查:
const express = require('express'); const app = express(); app.use(express.json()); app.post('/user', (req, res) => { User.create({ username: req.body.username, password: req.body.password }).then(user => res.json(user)); });这段代码的问题很明显:username可以是任意内容,password可以是任意长度,任何畸形请求都会直接进入数据库逻辑。接下来我们引入 express-validator 来补上这道防线。
第二步:用 check() 声明校验规则
导入check与validationResult(5.2.0 时代从express-validator/check子模块导入;当前仓库版本则统一从express-validator根入口导入,src/index.ts会导出check、body、validationResult等全部 API):
// ...rest of the initial code omitted for simplicity. const { check, validationResult } = require('express-validator/check'); app.post('/user', [ // username must be an email check('username').isEmail(), // password must be at least 5 chars long check('password').isLength({ min: 5 }) ], (req, res) => { // Finds the validation errors in this request and wraps them in an object with handy functions const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(400).json({ errors: errors.array() }); } User.create({ username: req.body.username, password: req.body.password }).then(user => res.json(user)); });这里发生了什么:
check('username').isEmail()创建了一条针对username字段的校验链(Validation Chain),并追加了isEmail()校验规则;check('password').isLength({ min: 5 })同样为password创建校验链,要求长度至少为 5;- 两条校验链组成数组作为中间件数组传给
app.post('/user', ...),在进入业务处理函数之前被执行; - 业务处理函数中通过
validationResult(req)取出本次请求的所有校验错误,errors.isEmpty()判断是否通过,不通过则返回 HTTP 400 与错误数组。
从源码看,check()的实现位于 src/middlewares/check.ts:它用ContextBuilder记录字段名、请求位置与默认消息,构建ContextRunnerImpl运行器,再通过Object.assign把运行器、校验器(ValidatorsImpl)、净化器(SanitizersImpl)与上下文处理方法绑定到同一个中间件函数上——这就是为什么一条校验链既能当中间件使用,又能链式调用.isEmail()、.isLength()、.trim()等方法的原因。测试 src/middlewares/check.spec.ts 也验证了校验链同时具备 validator、sanitizer、context-handler 与 context-runner 四类方法。
第三步:看看校验失败时的响应
Voila!现在,任何包含非法username或password字段的请求都会被拦截,服务器会返回如下结构的 JSON:
{ "errors": [{ "location": "body", "msg": "Invalid value", "param": "username" }] }这个错误对象是"字段级校验错误"的经典结构,含义为:
location:出错字段所在的请求位置,这里是body(还可能是cookies、headers、params、query);msg:错误消息。当某条校验规则没有显式指定消息时,默认就是Invalid value;param:出错的字段名。
对照当前仓库 src/base.ts 中定义的FieldValidationError类型可以看到,这一结构在后续版本中被细化为type: 'field'+location+path+value+msg的联合类型(字段名param演化为path),并且错误类型扩展出了alternative(oneOf()全部备选失败)、unknown_fields(checkExact()发现未知字段)等种类。但入门阶段你只需要理解:每个校验错误都携带"位置 + 字段 + 消息"三元信息,足够客户端精确提示。
第四步:校验通过后的正常流程
当username与password都合法时,validationResult(req).isEmpty()返回true,代码继续执行原有的User.create(...)逻辑,整个流程与最初的版本完全一致——express-validator 只在请求进入业务逻辑之前"拦截"非法输入,不改变合法的业务行为。
check() 校验链的工作原理(源码视角)
入门示例里最核心的 API 是check()。虽然入门指南只展示了最简用法,但理解其机制有助于你写出正确的校验代码。
校验的五个请求位置
check()默认会在以下所有请求对象中查找目标字段(从 src/middlewares/validation-chain-builders.ts 可见其默认 locations 为['body', 'cookies', 'headers', 'params', 'query']):
req.bodyreq.cookiesreq.headersreq.paramsreq.query
如果某个字段在多个位置同时出现,那么每一处取值都必须通过校验。例如请求同时携带query.id与body.id,check('id')会对两处值分别校验。
定位字段:通配符与路径展开
字段选择逻辑在 src/field-selection.ts 中实现:selectFields会把"字段 × 位置"展开成一组FieldInstance(含location、path、value),并自动去重。它还支持*、**通配符用于嵌套对象与数组(例如check('products.*.price')),这是入门后进阶(Wildcards 特性)的地基。另外注意:对于headers位置,字段名会被统一转为小写后再匹配。
校验链的执行顺序
check()构建出的校验链在作为中间件执行时,内部由 src/chain/context-runner-impl.ts 的run()驱动,关键行为包括:
- 同一字段的校验规则串行执行:校验链上的
.isEmail()、.isLength()等规则按声明顺序逐个运行,后一个规则看到的是前一个规则运行后的值(净化器修改值后,后续校验基于新值); - 不同字段并行执行:如果一条校验链同时覆盖多个字段,这些字段的校验互不阻塞;
- 值回写:净化器(sanitizer)修改字段值后,运行器会把新值写回
req对应位置(_.set(req[location], path, newValue)),这就是.trim()等净化方法能"原地修正输入"的原理; - 上下文收集:每个中间件运行后,其校验上下文(含错误列表)被挂到请求的
express-validator#contexts键上(见 src/base.ts 的contextsKey),validationResult(req)正是从这里汇总所有中间件的错误。
字段缺省时的行为
入门示例只展示了普通字段校验。若调用check()时不传任何字段,则校验整个请求位置(通常仅对req.body有意义,即 Whole Body Validation 特性)。本指南不展开,详见后续的进阶文档。
validationResult:统一收集与读取校验错误
validationResult(req)接收 Express 的请求对象,把所有中间件产生的校验错误抽取出来,包装成一个validation result 对象。其实现位于 src/validation-result.ts,核心逻辑是:从请求的 contexts 中flatMap出所有错误,交给Result类实例管理。
Result实例提供了几个实用的方法:
isEmpty():是否没有错误,入门示例用它作为继续执行业务逻辑的开关;array():把错误转换为数组(默认返回全部错误;传入{ onlyFirstError: true }则每个字段只保留第一条错误),入门示例用errors.array()直接序列化进响应;mapped():把错误转换为"字段名 → 错误"的对象形式,便于按字段快速取用;throw():若存在校验错误则直接抛出异常,适合在try/catch中配合统一错误处理中间件使用;formatWith(fn):返回一个使用自定义格式化函数的新Result实例,用于定制错误输出结构。
入门示例中的res.status(400).json({ errors: errors.array() })即为最典型的用法:isEmpty()判断 +array()输出。
校验规则从哪里来
示例中的isEmail()、isLength({ min: 5 })并非 express-validator 自己实现,而是直接来自 validator.js 的校验器集合。express-validator 把 validator.js 中所有可用的校验器(及其选项)以同名方法的形式暴露在校验链上。当你需要更多内置规则(如isInt、isUUID、isIn等)时,可直接在链式调用中查阅这些方法及其选项。仓库的 declarations/validator.d.ts 即为 validator.js 的类型声明,可作为方法清单参考。
接下来可以深入的方向
入门指南到此已经覆盖了"安装 → 声明校验 → 收集错误 → 返回 400"的完整闭环。官方文档在此基础上推荐了五个进阶方向,均可在本仓库website/versioned_docs/version-5.2.0/目录下找到对应文档:
- Sanitization(净化):使用
.trim()、.escape()等方法在写入数据库前清理输入,防止脏数据与 XSS; - Custom validators/sanitizers(自定义校验器与净化器):当内置规则不够用时,编写自己的校验逻辑;
- Custom error messages(自定义错误消息):把默认的
Invalid value替换为对用户友好的提示; - Wildcards(通配符):校验嵌套对象与数组中的字段;
- Schema validation(Schema 校验):用声明式 Schema 对象一次性描述整张表单的校验规则。
在开始这些进阶话题之前,建议你先亲手把上面的/user路由跑通:发起一个带非法username或过短password的 POST 请求,观察 400 响应中的errors数组结构;再通过合法请求确认User.create正常执行。一旦你掌握了"校验链 + validationResult"这对组合,express-validator 的其余特性都只是在这条主线上叠加更多规则与更灵活的错误处理而已。
- 后端
【免费下载链接】express-validator
An express.js middleware for validator.js.
相关推荐
buku 项目 Bukuserver 多语言国际化:Flask-Babel 翻译工作流与 CLI 实战指南
buku 项目 Bukuserver 多语言国际化:Flask Babel 翻译工作流与 CLI 实战指南 导读 本文围绕 buku 仓库中 bukuserve
后端express-validator 快速入门:在 Express 应用中完成校验、错误处理与输入净化
express validator 快速入门:在 Express 应用中完成校验、错误处理与输入净化 本篇指南以 express validator 官方入门文
后端express-validator 快速上手:为 Express 请求接入 validator.js 校验与清洗中间件
express validator 快速上手:为 Express 请求接入 validator.js 校验与清洗中间件 express validator 是一
后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考