Zum Inhalt springen

Validierung ​

Hono bietet nur einen sehr schlanken Validator. In Kombination mit einem Validator von Drittanbietern kann er jedoch leistungsfähig sein. Darüber hinaus kannst du mit der RPC-Funktion API-Spezifikationen über Typen mit deinen Clients teilen.

Manueller Validator ​

Zunächst stellen wir eine Methode vor, um eingehende Werte ohne einen Drittanbieter-Validator zu prüfen.

Importiere validator aus hono/validator.

ts
import { validator } from 'hono/validator'

Um Formulardaten zu validieren, gib form als erstes Argument und einen Callback als zweites Argument an. Prüfe den Wert im Callback und gib am Ende die validierten Werte zurück. Der validator kann als Middleware verwendet werden.

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,
    }
  }),
  //...

Im Handler kannst du den validierten Wert mit c.req.valid('form') abrufen.

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

Neben form können auch json, query, header, param und cookie validiert werden.

Achtung

Wenn du json oder form validierst, muss die Anfrage einen passenden Header content-type enthalten, etwa Content-Type: application/json für json. Andernfalls wird der Anfragekörper nicht geparst, und du erhältst ein leeres Objekt ({}) als Wert im Callback.

Bei Tests mit der folgenden Methode ist es wichtig, den Header content-type zu setzen: app.request().

Angenommen, es gibt diese Anwendung.

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)
  }
)

Deine Tests können so geschrieben werden.

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' }

Achtung

Wenn du header validierst, musst du als Schlüssel einen Namen in Kleinbuchstaben verwenden.

Wenn du den Header Idempotency-Key validieren möchtest, musst du idempotency-key als Schlüssel verwenden.

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')
    // ...
  }
)

Mehrere Validatoren ​

Du kannst auch mehrere Validatoren verwenden, um unterschiedliche Teile einer Anfrage zu prüfen:

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

Mit Zod ​

Du kannst Zod verwenden, einen der Validatoren von Drittanbietern. Wir empfehlen die Verwendung eines Validators von Drittanbietern.

Installiere ihn aus der npm-Registry.

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

Importiere z aus zod.

ts
import * as z from 'zod'

Schreibe dein Schema.

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

Du kannst das Schema im Callback zur Validierung verwenden und den validierten Wert zurückgeben.

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-Validator-Middleware ​

Mit der Zod-Validator-Middleware wird es noch einfacher.

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

Importiere anschließend zValidator.

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

Schreibe den Code dann wie folgt.

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 ​

Standard Schema ist eine Spezifikation, die TypeScript-Validierungsbibliotheken eine gemeinsame Schnittstelle bereitstellt. Sie wurde von den Betreuern von Zod, Valibot und ArkType entwickelt, damit Werkzeuge im Ökosystem mit beliebigen Validierungsbibliotheken zusammenarbeiten können, ohne individuelle Adapter zu benötigen.

Mit der Standard-Schema-Validator-Middleware kannst du jede mit Standard Schema kompatible Validierungsbibliothek in Hono verwenden. So kannst du deinen bevorzugten Validator wählen und gleichzeitig eine konsistente Typsicherheit bewahren.

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

Importiere sValidator aus dem Paket:

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

Mit Zod ​

Du kannst Zod mit dem Standard-Schema-Validator verwenden:

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

Mit Valibot ​

Valibot ist eine leichtgewichtige Alternative zu Zod mit modularem 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}`,
  })
})

Mit ArkType ​

ArkType bietet TypeScript-native Syntax für die Validierung zur Laufzeit:

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}`,
  })
})

Veröffentlicht unter der MIT-Lizenz.