Skip to content

验证

¥Validation

Hono 只提供了一个非常薄的验证器。但是,当与第三方验证器结合使用时,它会非常强大。此外,RPC 功能允许你通过类型与客户端共享 API 规范。

¥Hono provides only a very thin Validator. But, it can be powerful when combined with a third-party Validator. In addition, the RPC feature allows you to share API specifications with your clients through types.

手动验证器

¥Manual validator

首先,引入一种无需使用第三方验证器即可验证传入值的方法。

¥First, introduce a way to validate incoming values without using the third-party Validator.

hono/validator 导入 validator

¥Import validator from hono/validator.

ts
import { validator } from 'hono/validator'

要验证表单数据,请将 form 指定为第一个参数,并将回调指定为第二个参数。在回调中,验证值并在最后返回验证后的值。validator 可以用作中间件。

¥To validate form data, specify form as the first argument and a callback as the second argument. In the callback, validates the value and return the validated values at the end. The validator can be used as middleware.

ts
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') 获取经过验证的值。

¥Within the handler you can get the validated value with c.req.valid('form').

ts
, (c) => {
  const { body } = c.req.valid('form')
  // ... do something
  return c.json(
    {
      message: 'Created!',
    },
    201
  )
}

除了 form 之外,验证目标还包括 jsonqueryheaderparamcookie

¥Validation targets include json, query, header, param and cookie in addition to form.

警告

验证 jsonform 时,请求必须包含匹配的 content-type 标头(例如,json 必须包含 Content-Type: application/json)。否则,请求正文将不会被解析,你将在回调中收到一个空对象 ({}) 作为值。

¥When you validate json or form, the request must contain a matching content-type header (e.g. Content-Type: application/json for json). Otherwise, the request body will not be parsed and you will receive an empty object ({}) as value in the callback.

使用 app.request() 进行测试时,设置 content-type 标头非常重要。

¥It is important to set the content-type header when testing using app.request().

给定一个这样的应用。

¥Given an application like this.

ts
const app = new Hono()
app.post(
  '/testing',
  validator('json', (value, c) => {
    // pass-through validator
    return value
  }),
  (c) => {
    const body = c.req.valid('json')
    return c.json(body)
  }
)

你的测试可以这样写。

¥Your tests can be written like this.

ts
// ❌ this will not work
const res = await app.request('/testing', {
  method: 'POST',
  body: JSON.stringify({ key: 'value' }),
})
const data = await res.json()
console.log(data) // {}

// ✅ this will work
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' }

警告

验证 header 时,你需要使用小写名称作为键。

¥When you validate header, you need to use lowercase name as the key.

如果要验证 Idempotency-Key 标头,则需要使用 idempotency-key 作为密钥。

¥If you want to validate the Idempotency-Key header, you need to use idempotency-key as the key.

ts
// ❌ this will not work
app.post(
  '/api',
  validator('header', (value, c) => {
    // idempotencyKey is always undefined
    // so this middleware always return 400 as not expected
    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')
    // ...
  }
)

// ✅ this will work
app.post(
  '/api',
  validator('header', (value, c) => {
    // can retrieve the value of the header as expected
    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')
    // ...
  }
)

多个验证器

¥Multiple validators

你还可以包含多个验证器来验证请求的不同部分:

¥You can also include multiple validators to validate different parts of request:

ts
app.post(
  '/posts/:id',
  validator('param', ...),
  validator('query', ...),
  validator('json', ...),
  (c) => {
    //...
  }

使用 Zod

¥With Zod

你可以使用第三方验证器之一 Zod。我们建议使用第三方验证器。

¥You can use Zod, one of third-party validators. We recommend using a third-party validator.

从 Npm 注册表安装。

¥Install from the Npm registry.

sh
npm i zod
sh
yarn add zod
sh
pnpm add zod
sh
bun add zod

zod 导入 z

¥Import z from zod.

ts
import * as z from 'zod'

编写你的模式。

¥Write your schema.

ts
const schema = z.object({
  body: z.string(),
})

你可以在回调函数中使用模式进行验证并返回验证后的值。

¥You can use the schema in the callback function for validation and return the validated value.

ts
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')
    // ... do something
    return c.json(
      {
        message: 'Created!',
      },
      201
    )
  }
)

Zod 验证器中间件

¥Zod Validator Middleware

你可以使用 Zod 验证器中间件 使其更加容易。

¥You can use the Zod Validator Middleware to make it even easier.

sh
npm i @hono/zod-validator
sh
yarn add @hono/zod-validator
sh
pnpm add @hono/zod-validator
sh
bun add @hono/zod-validator

并导入 zValidator

¥And import zValidator.

ts
import { zValidator } from '@hono/zod-validator'

并按如下方式编写。

¥And write as follows.

ts
const route = app.post(
  '/posts',
  zValidator(
    'form',
    z.object({
      body: z.string(),
    })
  ),
  (c) => {
    const validated = c.req.valid('form')
    // ... use your validated data
  }
)

Standard Schema Validator Middleware

标准模式 是一个规范,为 TypeScript 验证库提供通用接口。由 Zod、Valibot 和 ArkType 的维护者创建,旨在使生态系统工具能够与任何验证库配合使用,而无需自定义适配器。

¥Standard Schema is a specification that provides a common interface for TypeScript validation libraries. It was created by the maintainers of Zod, Valibot, and ArkType to allow ecosystem tools to work with any validation library without needing custom adapters.

Standard Schema Validator Middleware 允许你将任何与标准模式兼容的验证库与 Hono 配合使用,从而让你可以灵活地选择所需的验证器,同时保持类型安全性的一致性。

¥The Standard Schema Validator Middleware lets you use any Standard Schema-compatible validation library with Hono, giving you the flexibility to choose your preferred validator while maintaining consistent type safety.

sh
npm i @hono/standard-validator
sh
yarn add @hono/standard-validator
sh
pnpm add @hono/standard-validator
sh
bun add @hono/standard-validator

从包中导入 sValidator

¥Import sValidator from the package:

ts
import { sValidator } from '@hono/standard-validator'

使用 Zod

¥With Zod

你可以将 Zod 与标准 Schema 验证器一起使用:

¥You can use Zod with the Standard Schema validator:

sh
npm i zod
sh
yarn add zod
sh
pnpm add zod
sh
bun add zod
ts
import { 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

¥With Valibot

Valibot 是 Zod 的一个轻量级替代方案,采用模块化设计:

¥Valibot is a lightweight alternative to Zod with a modular design:

sh
npm i valibot
sh
yarn add valibot
sh
pnpm add valibot
sh
bun add valibot
ts
import * 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

¥With ArkType

ArkType 提供 TypeScript 原生语法,用于运行时验证:

¥ArkType offers TypeScript-native syntax for runtime validation:

sh
npm i arktype
sh
yarn add arktype
sh
pnpm add arktype
sh
bun add arktype
ts
import { 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}`,
  })
})

Hono v4.11 中文网 - 粤ICP备13048890号