Бинарные данные: binary()

Валидация бинарных данных в Joi основана на работе с типом Buffer, который используется в Node.js для представления сырых байтов. Такой тип данных применяется при обработке файлов, изображений, криптографических ключей, потоков данных и любых случаев, где важна работа не с текстом, а с последовательностью байтов.

Базовый валидатор binary() предназначен для строгой проверки содержимого как бинарного буфера и предоставляет набор инструментов для ограничения размера, формата и допустимых значений.


Основы Joi.binary()

Конструктор binary() создаёт схему, которая ожидает на входе объект типа Buffer или значение, которое может быть приведено к бинарному виду в зависимости от настроек.

import Joi from 'joi';

const schema = Joi.binary();

const result = schema.validate(Buffer.from('hello'));

По умолчанию проверяется, что входные данные являются экземпляром Buffer.


Проверка типа данных

Основная задача binary() — убедиться, что переданное значение является бинарным:

const schema = Joi.binary();

schema.validate(Buffer.from([0x01, 0x02, 0x03]));
schema.validate('text'); // ошибка валидации

Если требуется строгая проверка без преобразований, важно учитывать тип входных данных заранее.


Работа с кодировками

Одной из ключевых возможностей является работа с различными кодировками входных данных. Joi может интерпретировать строку как бинарные данные при указании encoding().

Base64

const schema = Joi.binary().encoding('base64');

schema.validate('aGVsbG8='); // Buffer("hello")

Hex

const schema = Joi.binary().encoding('hex');

schema.validate('68656c6c6f');

При использовании encoding() строка автоматически преобразуется в Buffer перед проверкой остальных правил.


Ограничение длины данных

Для бинарных данных критически важно контролировать размер.

Минимальная длина

const schema = Joi.binary().min(5);

schema.validate(Buffer.from('12345'));

Максимальная длина

const schema = Joi.binary().max(1024);

Точная длина

const schema = Joi.binary().length(16);

Такие ограничения часто используются при работе с хешами, UUID в бинарном виде или фиксированными структурами данных.


Обязательные и необязательные значения

Как и в других типах Joi, бинарные данные могут быть обязательными или опциональными.

const schema = Joi.binary().required();

Если значение отсутствует:

schema.validate(undefined); // ошибка

Также можно явно разрешить отсутствие значения:

const schema = Joi.binary().optional();

Разрешённые и запрещённые значения

Иногда требуется ограничить допустимые бинарные значения:

const schema = Joi.binary().valid(Buffer.from([1, 2, 3]));

Или наоборот исключить конкретные значения:

const schema = Joi.binary().invalid(Buffer.from([0x00]));

Обработка пустых значений

Пустые буферы могут быть либо разрешены, либо запрещены:

const schema = Joi.binary().empty();

или

const schema = Joi.binary().min(1);

Во втором случае пустой Buffer будет считаться ошибкой.


Преобразование входных данных

При использовании encoding() Joi автоматически преобразует строку в Buffer, что упрощает работу с API, где данные приходят в текстовом виде.

const schema = Joi.binary().encoding('base64');

const { value } = schema.validate('aGVsbG8=');
// value -> Buffer("hello")

Без указания encoding() строка будет отклонена.


Использование в реальных сценариях

Загрузка файлов

const fileSchema = Joi.binary().max(5 * 1024 * 1024);

Используется для ограничения размера загружаемых файлов (например, изображений или PDF).


Криптографические ключи

const keySchema = Joi.binary().length(32);

Часто применяется для AES-ключей фиксированной длины.


Хеши

const hashSchema = Joi.binary().encoding('hex').length(64);

Подходит для SHA-256 в hex-представлении.


Совмещение с объектными схемами

Бинарные данные часто используются внутри сложных структур:

const schema = Joi.object({
  file: Joi.binary().max(2 * 1024 * 1024),
  signature: Joi.binary().encoding('base64').required()
});

Ошибки валидации

Типичные причины ошибок:

  • передана строка без encoding()
  • превышен лимит max()
  • несоответствие length()
  • передан null при отсутствии allow(null)
  • передан не-Buffer тип

Кастомные сообщения об ошибках

const schema = Joi.binary()
  .min(10)
  .messages({
    'binary.min': 'Данные слишком короткие',
    'binary.base': 'Неверный формат бинарных данных'
  });

Joi позволяет детализировать ошибки для удобства обработки на уровне API.


Особенности работы с Buffer

Важно учитывать, что:

  • Buffer не является JSON-совместимым типом
  • при сериализации данные могут теряться или преобразовываться в base64
  • сравнение происходит по содержимому байтов, а не по ссылке

Частые ошибки проектирования схем

Некорректное использование binary() часто связано с:

  • попыткой валидировать текст без указания encoding()
  • смешиванием строк и Buffer без явного преобразования
  • отсутствием ограничений размера для файловых данных
  • ожиданием автоматического декодирования без настройки схемы

Сравнение с string().base64()

Иногда вместо binary().encoding('base64') используют строковый тип:

Joi.string().base64()

Различие заключается в том, что:

  • binary() приводит данные к Buffer
  • string().base64() оставляет значение строкой

Выбор зависит от того, на каком этапе требуется работа с байтами.


Композиция правил

binary() поддерживает комбинирование правил:

const schema = Joi.binary()
  .encoding('base64')
  .min(100)
  .max(5000)
  .required();

Такие цепочки позволяют точно описывать формат входных бинарных данных, особенно в API с загрузкой файлов или криптографическими операциями.