☰
Midway Hooks 参数校验完全指南:Validate 与 ValidateHttp 实战
2026/10/8 1:51:18 网站建设 项目流程
  • 后端
  • 微服务
  • 云原生

【免费下载链接】midway

🍔 A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 🌈

项目地址:https://gitcode.com/gh_mirrors/mi/midway
点击查看免费下载

Midway Hooks 将 zod 作为内置参数校验方案,通过Validate(...schemas)校验函数入参、ValidateHttp(options)校验 HTTP 结构(Query / Params / Headers / Body),并在校验失败时返回标准化的错误结构。本文以 validate.md 为主线,结合仓库中的校验组件源码与官方示例,完整讲解从安装、基础用法、错误处理到类型推导的全流程,帮助你在全栈一体化应用中快速落地可靠的入参防护。

快速开始:安装 zod

Midway Hooks 使用 zod(zod@3)作为校验器,使用前需要先安装:

npm install zod

zod 是独立的类型安全校验库,只负责描述 Schema 与执行校验;Midway Hooks 负责把 zod 的 Schema 接入到接口的执行链路中,让校验失败自动变成 HTTP 错误返回给调用方。在仓库的生态组件 packages/validation-zod/package.json 中可以看到,Midway 生态整体以 zod 3.x(如zod: 3.25.76)为基础,并配套zod-validation-error、zod-i18n-map等工具完善错误格式化与国际化。

Validate:按位置校验函数入参

Validate接收一个或多个 zod Schema,Schema 的顺序与函数入参的顺序一一对应。函数执行前,框架会按顺序校验每个入参,任何一个不满足都会中止调用并抛出校验错误。

基础示例

下面这段代码定义了一个POST /hello接口,第一个入参必须是string,第二个入参必须是number:

import { Api, Post, Validate, } from '@midwayjs/hooks'; import { z } from 'zod'; export default Api( Post('/hello'), Validate(z.string(), z.number()), async (name: string, age: number) => { return `Hello ${name}, you are ${age} years old.`; } );

Validate(z.string(), z.number())声明了「第一个参数必须是字符串、第二个参数必须是数字」的规则。由于 zod Schema 自带完整的 TypeScript 类型,这里函数签名中的name: string、age: number也可以进一步通过类型推导自动获得(见后文「TypeScript 支持」一节)。

一体化调用

在 Midway Hooks 的一体化(fullstack)模式下,前端直接导入后端函数进行类型安全调用。当传入不合法的参数时,调用会抛出错误,可从error.data.message中解析出完整错误信息,error.status为422:

import hello from './api'; try { await hello(null, null); } catch (error) { console.log( JSON.parse(error.data.message) ); console.log(error.status); // 422 }

手动调用

如果不使用一体化调用,也可以通过 HTTP 客户端直接请求接口,将参数包装在args数组中发送:

fetcher .post('/hello', { args: [null, null], }) .catch((error) => { console.log( JSON.parse(error.data.message) ); console.log(error.status); // 422 });

这里的fetcher指的是请求客户端。Midway Hooks 默认使用@midwayjs/rpc作为请求客户端,其中setupHttpClient({ fetcher })允许替换底层实现(默认基于 redaxios),详细说明可参考 client.md。

错误处理

校验失败的错误可以通过 Try/Catch 捕获。错误响应中包含固定的业务错误码与错误详情:

try { // 调用接口 } catch (error) { console.log(error.data.code); // VALIDATION_FAILED console.log( JSON.parse(error.data.message) ); }

error.data.code为VALIDATION_FAILED,标识这是一次参数校验失败;error.data.message是 JSON 字符串,需使用JSON.parse解析后才能得到可读的错误明细,解析后的结构与 zod 的标准错误格式一致,例如:

[ { code: 'invalid_type', expected: 'string', received: 'number', path: [0, 'name'], message: 'Expected string, received number', }, ];

其中各字段含义如下:

  • message: 人类可读的错误信息,例如「期望字符串,实际收到数字」;
  • path: 错误路径,如[0, 'name']表示「第 0 个参数(即第一个入参)中的name字段校验出错」,数组第一位是参数下标,第二位是对象内的字段名。对于非对象参数,path只包含参数下标。

你可以基于这些结构化信息手动解析错误消息,拼装成面向用户的中文提示后展示。

关于422状态码:HTTP 422(Unprocessable Entity)是校验失败的标准语义。在仓库的 Midway 校验组件默认配置 config.default.ts 中,errorStatus的默认值即为422,与本文档中error.status === 422的行为保持一致。

ValidateHttp:校验 HTTP 结构

当接口需要同时校验 Query、路径参数、Headers 或请求体时,Validate这种「按位置校验入参」的方式就不够用了。此时应使用ValidateHttp(options),它专门面向 HTTP 请求结构。

ValidateHttp支持传入options参数,类型如下:

type ValidateHttpOption = { query?: z.Schema<any>; params?: z.Schema<any>; headers?: z.Schema<any>; data?: z.Schema<any>[]; };

各字段的作用:

  • query: 校验 URL Query 参数的 Schema,通常为z.object({ ... });
  • params: 校验路径参数(如/user/:id中的id)的 Schema;
  • headers: 校验请求头的 Schema;
  • data: 校验请求体参数的 Schema 数组,顺序与函数入参一一对应(等价于Validate的语义)。

以校验 Query 为例

后端代码定义一个GET /api/filterPosts接口,要求 Query 中的searchString至少 5 个字符:

import { Api, Get, Query, useContext, ValidateHttp, } from '@midwayjs/hooks'; import { z } from 'zod'; const QuerySchema = z.object({ searchString: z.string().min(5), }); export const filterPosts = Api( Get('/api/filterPosts'), Query<z.infer<typeof QuerySchema>>(), ValidateHttp({ query: QuerySchema }), async () => { const ctx = useContext(); return ctx.query.searchString; } );

这段代码展示了两个要点:

  1. Query<z.infer<typeof QuerySchema>>()让ctx.query获得{ searchString: string }的静态类型;
  2. ValidateHttp({ query: QuerySchema })在运行时用同一个 Schema 校验真实请求。

ctx通过useContext()获取,ctx.query.searchString即为解析后的 Query 值。一体化调用时,通过query字段传入:

import filterPosts from './api'; try { await filterPosts({ query: { searchString: '' }, }); } catch (error) { console.log( JSON.parse(error.data.message) ); console.log(error.status); // 422 }

手动调用时,把参数拼进 URL 即可:

fetcher .get( '/api/filterPosts?searchString=1' ) .catch((error) => { console.log( JSON.parse(error.data.message) ); console.log(error.status); // 422 });

由于searchString只有 1 个字符,不满足min(5),两种情况都会以 422 结束,错误详情指出该字段违反了最小长度约束。

TypeScript 支持:用 zod 推导接口类型

zod 的核心价值之一是其 Schema 本身就是类型定义。通过z.infer,可以把 zod Schema 直接推导为 TypeScript 类型,让校验规则与静态类型永远保持同步,避免「类型说一套、校验做一套」。

以创建一个项目接口为例:

import { Api, Post, Validate, } from '@midwayjs/hooks'; import { z } from 'zod'; const Project = z.object({ name: z.string(), description: z.string(), owner: z.string(), members: z.array(z.string()), }); export default Api( Post('/project'), Validate(Project), async ( // { name: string, description: string, owner: string, members: string[] } project: z.infer<typeof Project> ) => { return project; } );

z.infer<typeof Project>自动推导出{ name: string; description: string; owner: string; members: string[] },注释中已展示推导结果。修改 Schema 时,函数签名类型也会随之自动更新。

一体化调用时,即使传入错误的字段类型(如name: 1),也能在编译期被 TypeScript 拦截,运行时同样会被 zod 拒绝:

import createProject from './api'; try { await createProject({ name: 1, description: 'test project', owner: 'test', members: ['test'], }); } catch (error) { console.log(error.message); console.log(error.status); // 422 }

手动调用同理:

fetcher .post('/project', { args: [ { name: 1, description: 'test project', owner: 'test', members: ['test'], }, ], }) .catch((error) => { console.log( JSON.parse(error.data.message) ); console.log(error.status); // 422 });

注意一体化调用示例中直接打印了error.message(此时 message 可能是可直接读的字符串,取决于错误对象的实现),而手动调用与前面示例一致,从error.data.message中JSON.parse解析结构化错误。

从源码看 Midway 生态中的 zod 集成

除 Hooks 的Validate/ValidateHttp之外,zod 在 Midway 生态中还以传统 IoC 组件的形式提供能力,可作参考与印证。

  • 422 默认状态码:在 packages/validate/src/config/config.default.ts 中,校验组件默认配置errorStatus: 422,说明「校验失败返回 422」是 Midway 校验体系的一致约定。
  • 错误码体系:传统校验组件在 packages/validate/src/error.ts 中通过registerErrorCode('validate', { VALIDATE_FAIL: 10000 })注册错误码,并基于MidwayHttpError构造校验异常,最终错误会携带状态码与错误码随响应返回;Hooks 的Validate同样遵循「HTTP 状态码 + 业务错误码(VALIDATION_FAILED)+ 结构化 message」的响应形态。
  • zod 校验服务实现:packages/validation-zod/src/index.ts 提供了基于 zod 的IValidationService实现,从源码结构看,它使用schema.safeParse完成校验(成功取data,失败取error),并使用zod-validation-error的fromError生成人类可读的错误消息;同时通过zod-i18n-map为错误消息提供多语言(zh-CN / en-US 等)支持,这是对「解析并展示错误信息给用户」这一官方建议的工程化实现。

可以看到,无论是 Hooks 的一体化 API,还是传统组件,zod 都已深度融入 Midway 的参数校验链路:Schema 描述规则、校验失败统一收敛为可捕获的 HTTP 错误、错误结构标准化,方便前端统一解析与展示。

小结

  • 安装zod后即可使用Validate(...schemas)按位置校验函数入参,Schema 顺序与入参顺序一一对应;
  • 需要校验 Query / Params / Headers / Body 时改用ValidateHttp({ query, params, headers, data });
  • 校验失败统一返回 422,error.data.code为VALIDATION_FAILED,error.data.message为 JSON 字符串,解析后可按path、message等字段定位具体错误;
  • 利用z.infer让 zod Schema 同时充当运行时校验规则与静态类型定义,一处定义、处处同步;
  • 一体化调用与手动 HTTP 调用(args/query两种封装方式)都能获得一致的错误响应结构,便于前端统一处理。

完整的官方文档位于 site/docs/hooks/validate.md,配套的官方全栈示例可参考 site/example/function。

  • 后端
  • 微服务
  • 云原生

【免费下载链接】midway

🍔 A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 🌈

项目地址:https://gitcode.com/gh_mirrors/mi/midway
点击查看免费下载

相关推荐

上一篇:抖音批量下载终极指南:从单视频到批量自动化的完整解决方案
下一篇:抖音内容采集实战:从零构建高效自动化下载系统的完整指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询