验证
Hono 仅提供了一个非常轻量的验证器。 但是,当与第三方验证器结合使用时,它会变得非常强大。 此外,RPC 功能允许你通过类型与客户端共享 API 规范。
手动验证器
首先,介绍一种不使用第三方验证器来验证传入值的方法。
从 hono/validator 导入 validator。
import { validator } from 'hono/validator'要验证表单数据,将 form 指定为第一个参数,回调函数作为第二个参数。 在回调中,验证值并在最后返回验证后的值。 validator 可以作为中间件使用。
app.post(
'/posts',
validator('form', (value, c) => {
const body = value['body']
if (!body || typeof body !== 'string') {
return c.text('Invalid!', 400)
}
return {
body: body,
}
}),
//...在处理程序中,你可以使用 c.req.valid('form') 获取验证后的值。
, (c) => {
const { body } = c.req.valid('form')
// ... 执行某些操作
return c.json(
{
message: 'Created!',
},
201
)
}除了 form 之外,验证目标还包括 json、query、header、param 和 cookie。
WARNING
当你验证 json 或 form 时,请求 必须 包含匹配的 content-type 请求头(例如,对于 json 为 Content-Type: application/json)。否则,请求体将无法被解析,你在回调中接收到的值将是一个空对象({})。
在使用 app.request() 进行测试时,设置 content-type 请求头很重要。
给定这样一个应用。
const app = new Hono()
app.post(
'/testing',
validator('json', (value, c) => {
// 直通验证器
return value
}),
(c) => {
const body = c.req.valid('json')
return c.json(body)
}
)你的测试可以这样写。
// ❌ 这将不起作用
const res = await app.request('/testing', {
method: 'POST',
body: JSON.stringify({ key: 'value' }),
})
const data = await res.json()
console.log(data) // {}
// ✅ 这将起作用
const res = await app.request('/testing', {
method: 'POST',
body: JSON.stringify({ key: 'value' }),
headers: new Headers({ 'Content-Type': 'application/json' }),
})
const data = await res.json()
console.log(data) // { key: 'value' }WARNING
当你验证 header 时,你需要使用 小写 名称作为键。
如果你想验证 Idempotency-Key 请求头,你需要使用 idempotency-key 作为键。
// ❌ 这将不起作用
app.post(
'/api',
validator('header', (value, c) => {
// idempotencyKey 始终为 undefined
// 所以此中间件总是返回 400,不符合预期
const idempotencyKey = value['Idempotency-Key']
if (idempotencyKey == undefined || idempotencyKey === '') {
throw new HTTPException(400, {
message: 'Idempotency-Key is required',
})
}
return { idempotencyKey }
}),
(c) => {
const { idempotencyKey } = c.req.valid('header')
// ...
}
)
// ✅ 这将起作用
app.post(
'/api',
validator('header', (value, c) => {
// 可以按预期获取请求头的值
const idempotencyKey = value['idempotency-key']
if (idempotencyKey == undefined || idempotencyKey === '') {
throw new HTTPException(400, {
message: 'Idempotency-Key is required',
})
}
return { idempotencyKey }
}),
(c) => {
const { idempotencyKey } = c.req.valid('header')
// ...
}
)多个验证器
你还可以包含多个验证器来验证请求的不同部分:
app.post(
'/posts/:id',
validator('param', ...),
validator('query', ...),
validator('json', ...),
(c) => {
//...
}使用 Zod
你可以使用 Zod,它是第三方验证器之一。 我们推荐使用第三方验证器。
从 Npm 注册表安装。
npm i zodyarn add zodpnpm add zodbun add zod从 zod 导入 z。
import * as z from 'zod'编写你的模式。
const schema = z.object({
body: z.string(),
})你可以在回调函数中使用模式进行验证并返回验证后的值。
const route = app.post(
'/posts',
validator('form', (value, c) => {
const parsed = schema.safeParse(value)
if (!parsed.success) {
return c.text('Invalid!', 401)
}
return parsed.data
}),
(c) => {
const { body } = c.req.valid('form')
// ... 执行某些操作
return c.json(
{
message: 'Created!',
},
201
)
}
)Zod 验证器中间件
你可以使用 Zod 验证器中间件 使其更加简单。
npm i @hono/zod-validatoryarn add @hono/zod-validatorpnpm add @hono/zod-validatorbun add @hono/zod-validator然后导入 zValidator。
import { zValidator } from '@hono/zod-validator'并按如下方式编写。
const route = app.post(
'/posts',
zValidator(
'form',
z.object({
body: z.string(),
})
),
(c) => {
const validated = c.req.valid('form')
// ... 使用你验证后的数据
}
)标准模式验证器中间件
Standard Schema 是一个规范,为 TypeScript 验证库提供通用接口。它由 Zod、Valibot 和 ArkType 的维护者创建,允许生态系统工具与任何验证库一起工作,而无需自定义适配器。
Standard Schema 验证器中间件 允许你在 Hono 中使用任何兼容 Standard Schema 的验证库,让你在保持一致的类型安全性的同时,灵活选择首选的验证器。
npm i @hono/standard-validatoryarn add @hono/standard-validatorpnpm add @hono/standard-validatorbun add @hono/standard-validator从包中导入 sValidator:
import { sValidator } from '@hono/standard-validator'使用 Zod
你可以将 Zod 与 Standard Schema 验证器一起使用:
npm i zodyarn add zodpnpm add zodbun add zodimport * as z from 'zod'
import { sValidator } from '@hono/standard-validator'
const schema = z.object({
name: z.string(),
age: z.number(),
})
app.post('/author', sValidator('json', schema), (c) => {
const data = c.req.valid('json')
return c.json({
success: true,
message: `${data.name} is ${data.age}`,
})
})使用 Valibot
Valibot 是 Zod 的轻量级替代品,具有模块化设计:
npm i valibotyarn add valibotpnpm add valibotbun add valibotimport * as v from 'valibot'
import { sValidator } from '@hono/standard-validator'
const schema = v.object({
name: v.string(),
age: v.number(),
})
app.post('/author', sValidator('json', schema), (c) => {
const data = c.req.valid('json')
return c.json({
success: true,
message: `${data.name} is ${data.age}`,
})
})使用 ArkType
ArkType 为运行时验证提供 TypeScript 原生语法:
npm i arktypeyarn add arktypepnpm add arktypebun add arktypeimport { type } from 'arktype'
import { sValidator } from '@hono/standard-validator'
const schema = type({
name: 'string',
age: 'number',
})
app.post('/author', sValidator('json', schema), (c) => {
const data = c.req.valid('json')
return c.json({
success: true,
message: `${data.name} is ${data.age}`,
})
})