Порты и безопасные целые

Валидация числовых значений в схемах Joi строится вокруг строгого контроля диапазонов, формата и семантики числа. Особое место занимают два связанных аспекта: работа с сетевыми портами и ограничение значений безопасным диапазоном целых чисел JavaScript.


Целые числа и их базовая проверка

Числа в JavaScript представлены форматом IEEE-754, что накладывает ограничения на точность. Для исключения ошибок округления и некорректных значений Joi предоставляет базовые методы:

const schema = Joi.number().integer();

Данная схема гарантирует, что значение является целым числом. Любые дробные значения будут отклонены.

Дополнительно применяются ограничения диапазона:

const schema = Joi.number().integer().min(0).max(100);

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


Безопасные целые числа (safe integers)

JavaScript способен корректно представлять целые числа только в пределах:

-(2^53 - 1) ... (2^53 - 1)

Эти значения определяются как безопасные целые числа (Number.isSafeInteger).

В Joi используется проверка безопасного диапазона:

const schema = Joi.number().integer().safe();

Семантика safe integer

Метод .safe() гарантирует:

  • значение является целым числом
  • значение не выходит за пределы Number.MIN_SAFE_INTEGER и Number.MAX_SAFE_INTEGER
  • исключаются потенциальные ошибки потери точности

Применение важно в следующих сценариях:

  • идентификаторы сущностей в базе данных
  • финансовые расчёты в целых единицах
  • криптографические или хэш-значения, представленные числами

Порты как специализированный диапазон чисел

Сетевые порты представляют собой ограниченный диапазон целых чисел от 0 до 65535. Joi предоставляет специализированную валидацию для этого случая:

const schema = Joi.number().port();

Поведение .port()

Метод .port() эквивалентен проверке:

  • число является целым
  • значение находится в диапазоне 0–65535
  • исключаются отрицательные значения и дробные числа

Практическая структура порта в валидации

Порты часто используются вместе с конфигурационными объектами:

const configSchema = Joi.object({
  host: Joi.string().hostname().required(),
  port: Joi.number().port().required()
});

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


Ограничения и поведение при ошибках

При нарушении правил валидации Joi возвращает детализированное описание ошибки:

  • port вне диапазона → ошибка типа validation
  • дробное число → нарушение integer constraint
  • слишком большое значение → выход за пределы safe integer или port range

Пример результата:

{
  message: '"port" must be a valid port',
  path: ['port'],
  type: 'number.port'
}

Комбинирование safe integer и дополнительных ограничений

Несмотря на наличие .safe(), часто требуется дополнительная бизнес-логика:

const schema = Joi.number()
  .integer()
  .safe()
  .min(1)
  .max(9007199254740991);

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


Пограничные случаи и особенности числовой модели JavaScript

Joi работает поверх особенностей языка, поэтому важно учитывать:

  • Number.MAX_VALUE не равен максимальному безопасному целому
  • экспоненциальная форма записи может приводить к потере точности
  • значения, полученные из JSON, могут приходить как строки и требовать преобразования
const schema = Joi.number().integer().safe().strict();

Флаг strict() отключает автоматическое приведение типов, что критично при работе с внешними источниками данных.


Валидация портов в серверных конфигурациях

В серверных приложениях порты являются одним из наиболее частых источников ошибок конфигурации. Joi позволяет централизовать контроль:

const serverSchema = Joi.object({
  port: Joi.number().port().default(3000)
});

Здесь дополнительно используется значение по умолчанию, что снижает вероятность некорректного запуска сервиса.


Сравнение safe integer и port

Несмотря на схожесть (оба работают с целыми числами), их смысл различается:

  • safe integer — математическое ограничение точности JavaScript
  • port — доменное ограничение сетевого уровня

Их пересечение возможно, но не обязательно:

  • порт всегда является safe integer
  • safe integer не обязательно является валидным портом

Типовые ошибки при работе с числами

На практике часто встречаются следующие проблемы:

  • передача порта строкой "3000" без преобразования
  • использование дробных значений в конфигурации
  • выход за пределы safe integer при работе с идентификаторами
  • отсутствие .integer() при использовании .port() в сложных схемах

Композиция числовых правил в Joi

Joi позволяет строить сложные числовые ограничения через цепочку методов:

const schema = Joi.number()
  .integer()
  .safe()
  .port()
  .required();

В реальных сценариях .port() уже включает проверку целочисленности и диапазона, поэтому дополнительные методы используются только при нестандартных расширениях схем.


Применение в микросервисной архитектуре

В распределённых системах числовая валидация играет роль первого уровня защиты:

  • порты сервисов
  • идентификаторы запросов
  • лимиты ресурсов
  • внутренние числовые ключи

Использование .safe() снижает риск некорректной интерпретации чисел при сериализации между сервисами.


Поведение при сериализации JSON

При получении данных из JSON:

{
  "port": "8080"
}

валидация без strict() может привести к автоматическому преобразованию строки в число. Это удобно, но может скрывать ошибки входных данных.

Joi.number().port().strict();

В строгом режиме любое несоответствие типу приводит к ошибке валидации.


Итоговая модель числовой безопасности Joi

Комбинация механизмов Joi формирует многоуровневую защиту:

  • типовая проверка (number)
  • структурная проверка (integer)
  • семантическая проверка (port)
  • аппаратная безопасность языка (safe)

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