В основе подхода Fastify лежит декларативное описание контрактов между клиентом и сервером. Эти контракты выражаются через схемы, основанные на спецификации JSON Schema, и обеспечиваются высокопроизводительным валидатором Ajv. Такая архитектура позволяет объединить в одном месте валидацию входящих данных, сериализацию ответов и документацию API.
Схема в Fastify — это объект, описывающий структуру данных для различных частей HTTP-запроса и ответа:
body — тело запросаquerystring — параметры строки запросаparams — параметры маршрутаheaders — заголовкиresponse — структура ответаКаждая из этих секций может быть независимо валидирована и оптимизирована.
Схема в контексте маршрута задаётся через поле
schema:
fastify.route({
method: 'POST',
url: '/user/:id',
schema: {
params: {
type: 'object',
properties: {
id: { type: 'string' }
},
required: ['id']
},
body: {
type: 'object',
properties: {
name: { type: 'string' },
age: { type: 'integer', minimum: 0 }
},
required: ['name']
},
response: {
200: {
type: 'object',
properties: {
ok: { type: 'boolean' }
}
}
}
},
handler: async (request, reply) => {
return { ok: true }
}
})
Каждая часть схемы компилируется в отдельную функцию валидатора на основе Ajv, что позволяет достигать высокой производительности за счёт предварительной компиляции.
Ajv используется как основной движок валидации JSON Schema. Fastify не интерпретирует схемы во время запроса — вместо этого он:
Такой подход исключает накладные расходы на парсинг и интерпретацию схемы в рантайме.
Ключевые возможности Ajv, используемые Fastify:
$refFastify делает ставку на минимизацию overhead. Каждая схема проходит этап компиляции:
Это означает, что стоимость валидации запроса после старта сервера становится близкой к вызову обычной функции.
Используется для проверки структуры входящего JSON:
body: {
type: 'object',
required: ['email'],
properties: {
email: { type: 'string', format: 'email' }
}
}
Используется для параметров URL:
params: {
type: 'object',
properties: {
id: { type: 'number' }
}
}
Часто требует преобразования типов:
querystring: {
type: 'object',
properties: {
page: { type: 'integer', default: 1 },
limit: { type: 'integer', maximum: 100 }
}
}
Особенность headers — нормализация ключей:
headers: {
type: 'object',
properties: {
'x-api-key': { type: 'string' }
},
required: ['x-api-key']
}
Секция response определяет структуру данных, которые
сервер гарантированно возвращает.
response: {
200: {
type: 'object',
properties: {
data: { type: 'array' }
}
}
}
Fastify использует эту схему не только для валидации, но и для сериализации ответа. Это означает:
Для масштабных приложений критично переиспользование схем. Ajv
поддерживает идентификаторы $id:
const userSchema = {
$id: 'userSchema',
type: 'object',
properties: {
id: { type: 'string' }
}
}
Далее схема может использоваться через $ref:
body: {
$ref: 'userSchema'
}
Fastify автоматически регистрирует и резолвит такие зависимости через внутренний реестр Ajv.
Fastify включает строгую проверку схем, которая предотвращает:
Это снижает вероятность ошибок на этапе разработки, но требует более дисциплинированного описания контрактов.
Ajv позволяет расширять систему типов через форматы:
fastify.addSchema({
$id: 'customEmail',
type: 'string',
format: 'email'
})
Или через runtime-регистрацию:
fastify.addHook('onRoute', (routeOptions) => {
// расширение логики схем
})
Также поддерживаются custom keywords, позволяющие внедрять бизнес-логику прямо в схему.
Fastify может автоматически приводить типы:
querystring: {
type: 'object',
properties: {
page: { type: 'integer' }
}
}
Запрос ?page=1 будет преобразован из строки в число при
включённой опции coerceTypes.
Ajv и Fastify поддерживают стратегию работы с лишними полями:
removeAdditional: true — удаляет лишние поляremoveAdditional: 'all' — более строгая очисткаadditionalProperties: false — запрещает любые
неописанные поляЭто важно для контроля контрактов и защиты API от «грязных» входных данных.
При нарушении схемы Fastify возвращает структурированную ошибку:
instancePath)message)keyword)Это позволяет точно локализовать проблему без ручного парсинга запроса.
Использование схем в Fastify приводит к формированию контрактно-ориентированной архитектуры:
Схемы начинают играть роль центрального описания доменной модели на уровне HTTP-интерфейса.
На основе схем можно автоматически строить OpenAPI-описание. Fastify использует их как источник истины для:
Это устраняет необходимость дублирования контрактов в коде и документации.
Глубоко вложенные объекты и массивы обрабатываются через рекурсивные проверки Ajv. При этом:
$ref заменяются на прямые вызовыЭто обеспечивает стабильную производительность даже при сложных моделях данных.
Часто встречающиеся проблемы:
$refrequired, приводящее к неявным ошибкамobject без
ограничений)Такие ошибки приводят к потере преимуществ декларативного подхода и усложняют поддержку API.