التحقق
يوفّر Hono مدقّقًا رفيعًا جدًا فقط. ومع ذلك، يمكن أن يكون قويًا عند دمجه مع مدقق (Validator) من جهة خارجية. بالإضافة إلى ذلك، تتيح لك ميزة RPC مشاركة مواصفات API مع عملائك من خلال الأنواع (types).
مُدقّق يدوي
أولًا، قدّم طريقة للتحقق من القيم الواردة دون استخدام أداة التحقق (Validator) من طرف ثالث.
استيراد validator من hono/validator.
import { validator } from 'hono/validator'
للتحقق من بيانات النموذج، حدّد form كوسيط أول ورد نداء (callback) كوسيط ثانٍ.
في دالة الاستدعاء (callback)، يتم التحقق من القيمة وإرجاع القيم التي تم التحقق منها في النهاية.
الـ 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')
// ... do something
return c.json(
{
message: 'Created!',
},
201
)
}
تشمل أهداف التحقق json, query, header, param و cookie بالإضافة إلى form.
عندما تتحقق من json أو form، يجب أن يحتوي الطلب بالضرورة على مطابق content-type الترويسة (على سبيل المثال Content-Type: application/json لـ json). وإلا، فلن يتم تحليل جسم الطلب وستتلقى كائنًا فارغًا ({}) كقيمة في دالة الاستدعاء.
من المهم تعيين content-type الترويسة عند الاختبار باستخدام
app.request().
بالنظر إلى تطبيق كهذا.
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)
}
)
يمكن كتابة اختباراتك هكذا.
// ❌ 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، تحتاج إلى استخدام اسم بحروف صغيرة كمفتاح.
إذا أردت التحقق من Idempotency-Key الترويسة، تحتاج إلى استخدام idempotency-key كمفتاح.
// ❌ 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')
// ...
}
)
مُدقّقات متعددة
يمكنك أيضًا تضمين عدة أدوات تحقق (validators) للتحقق من أجزاء مختلفة من الطلب:
app.post(
'/posts/:id',
validator('param', ...),
validator('query', ...),
validator('json', ...),
(c) => {
//...
}
)
مع Zod
يمكنك استخدام Zod، وهو أحد المدقّقات الخارجية.
نوصي باستخدام مدقّق خارجي.
التثبيت من سجل Npm.
npm i zod
yarn add zod
pnpm add zod
bun add zod
استيراد z من zod.
import * as z from 'zod'
اكتب مخططك.
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')
// ... do something
return c.json(
{
message: 'Created!',
},
201
)
}
)
برمجية وسيطة للتحقق بـ Zod
يمكنك استخدام وسيط التحقق Zod لجعله أسهل.
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')
// ... use your validated data
}
)
برمجية وسيطة للتحقق بـ Standard Schema
المخطط القياسي (Standard Schema) هي مواصفة توفر واجهة مشتركة لمكتبات التحقق في TypeScript. أنشأها القائمون على صيانة Zod و Valibot و ArkType للسماح لأدوات النظام البيئي بالعمل مع أي مكتبة تحقق دون الحاجة إلى محولات مخصصة.
الـ برمجية Standard Schema Validator الوسيطة يتيح لك استخدام أي مكتبة تحقق متوافقة مع Standard Schema مع Hono، مما يمنحك المرونة لاختيار أداة التحقق المفضلة لديك مع الحفاظ على أمان الأنواع بشكل متسق.
npm i @hono/standard-validator
yarn add @hono/standard-validator
pnpm add @hono/standard-validator
bun add @hono/standard-validator
استيراد sValidator من الحزمة:
import { sValidator } from '@hono/standard-validator'
مع Zod
يمكنك استخدام Zod مع مُدقّق Standard Schema:
npm i zod
yarn add zod
pnpm add zod
bun add zod
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}`,
})
})
مع Valibot
Valibot بديل خفيف الوزن لـ Zod بتصميم معياري (modular):
npm i valibot
yarn add valibot
pnpm add valibot
bun add valibot
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
ArkType يوفّر صيغة أصلية في TypeScript للتحقق في وقت التشغيل:
npm i arktype
yarn add arktype
pnpm add arktype
bun add arktype
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}`,
})
})