验证
Hono 仅提供了一个非常轻量的 Validator。 但是,当与第三方 Validator 结合使用时,它可以变得非常强大。 此外,RPC 功能允许你通过类型与你的客户端分享 API 规范。
手动验证器
首先,介绍一种在不使用第三方 Validator 的情况下验证传入值的方法。
从 hono/validator
导入 validator
。
import { validator } from 'hono/validator'
要验证 form data,指定 form
作为第一个参数,回调函数作为第二个参数。 在回调函数中,验证值并在最后返回验证后的值。 validator
可以用作 middleware。
app.post(
'/posts',
validator('form', (value, c) => {
const body = value['body']
if (!body || typeof body !== 'string') {
return c.text('Invalid!', 400)
}
return {
body: body,
}
}),
//...
在 handler 中,你可以使用 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
时,请求 必须 包含 Content-Type: application/json
header,否则请求体将不会被解析,并且你会收到警告。
当使用 app.request()
进行测试时,设置 content-type
header 非常重要。
假设有如下应用。
const app = new Hono()
app.post(
'/testing',
validator('json', (value, c) => {
// 透传 validator
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) // undefined
// ✅ 这样是可以的
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
header,你需要使用 idempotency-key
作为键。
// ❌ 这样是行不通的
app.post(
'/api',
validator('header', (value, c) => {
// idempotencyKey 始终是 undefined
// 所以这个 middleware 总是返回 400,这不是预期的结果
const idempotencyKey = value['Idempotency-Key']
if (idempotencyKey == undefined || idempotencyKey === '') {
throw HTTPException(400, {
message: 'Idempotency-Key is required',
})
}
return { idempotencyKey }
}),
(c) => {
const { idempotencyKey } = c.req.valid('header')
// ...
}
)
// ✅ 这样是可以的
app.post(
'/api',
validator('header', (value, c) => {
// 可以按预期检索 header 的值
const idempotencyKey = value['idempotency-key']
if (idempotencyKey == undefined || idempotencyKey === '') {
throw HTTPException(400, {
message: 'Idempotency-Key is required',
})
}
return { idempotencyKey }
}),
(c) => {
const { idempotencyKey } = c.req.valid('header')
// ...
}
)
多个验证器
你也可以包含多个 validator 来验证请求的不同部分:
app.post(
'/posts/:id',
validator('param', ...),
validator('query', ...),
validator('json', ...),
(c) => {
//...
}
使用 Zod
你可以使用 Zod,一个第三方 validator。 我们推荐使用第三方 validator。
从 Npm 仓库安装。
npm i zod
yarn add zod
pnpm add zod
bun add zod
从 zod
导入 z
。
import { z } from 'zod'
编写你的 schema。
const schema = z.object({
body: z.string(),
})
你可以在回调函数中使用 schema 进行验证,并返回验证后的值。
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 Validator Middleware
你可以使用 Zod Validator Middleware 使其更加容易。
npm i @hono/zod-validator
yarn add @hono/zod-validator
pnpm add @hono/zod-validator
bun 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')
// ... 使用你验证后的数据
}
)