Статьи

hapi.js в действии: знакомство с Джой

Название изображения

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


Люди часто делают ошибки, и в результате системы, которые мы создаем, должны быть готовы к неправильному использованию. Валидация является неотъемлемой частью почти каждой системы, которую мы используем в нашей повседневной жизни. Давайте использовать торговый автомат с закусками, чтобы проиллюстрировать такую ​​систему.

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

Название изображения

Рисунок 1 — Ежедневный пример проверки, которая происходит в торговых автоматах

Мы полагаемся на отзывы, которые мы получаем от проверки, чтобы убедиться, что мы можем использовать системы правильно. Без этого мы не поняли бы, что делаем неправильно.

Мы используем термин « валидация» и в отношении программного обеспечения. В этой статье я расскажу о Joi, узле Node.js для проверки данных.

Представляем Джой

Joi — это Node-модуль для проверки данных. Joi может проверять данные любого типа: от простых скалярных типов данных, таких как строки, числа или логические значения, до сложных значений, состоящих из нескольких уровней вложенных объектов и массивов.

Если вы работаете с некоторыми данными в вашем приложении, которые поступают из неизвестного источника, например, через общедоступный API, Joi может помочь вам убедиться, что данные находятся в требуемом формате. Проверка таких входных данных и соответствующие действия в случае их неправильности помогут сделать ваши приложения более стабильными и надежными. 

Joi можно использовать как отдельный модуль в любом приложении Node. Джой на самом деле используется внутри многих модулей в гапиосистеме именно для этой цели. Если вы ранее использовали какой-либо из API-интерфейсов hapi неправильно и увидели сообщение об ошибке, это сообщение могло быть получено в результате проверки, выполненной Joi.

Хапи был разработан с Джои в виду. Встроенные в платформу функции проверки, такие как проверка заголовков HTTP и полезных нагрузок, предназначены для бесперебойной работы с Joi.

Как это устроено

Работа с Джой включает в себя процесс из четырех этапов. Эти шаги показаны на рисунке 2. Первым шагом является создание схемы. Схема — это объект, который описывает ваши ожидания и то, с чем вы будете проверять свои реальные данные. Вы можете представить схему как описание вашего идеального объекта.

Существует очень распространенная игра-головоломка, предназначенная для младенцев, где они должны помещать блоки различной формы в отверстия соответствующей формы. Эта игра — хорошая аналогия с тем, как работает Джой. В Joi схема похожа на дыру, а объект, который вы хотите проверить, похож на блок. Любой данный объект либо соответствует схеме, либо нет.

Название изображения

Рисунок 2 — Шаги, сделанные при проверке с Joi

Когда у вас есть схема, вы будете использовать Joi для проверки схемы с некоторыми объектами. Если произошла ошибка проверки, Джой точно скажет вам, что пошло не так. Затем вы можете использовать эту обратную связь, чтобы принять решение и соответствующим образом ответить пользователю.

Простой пример: проверка скалярного типа

Часть данных, которую мы обычно должны проверять в наших приложениях, это пароли. В этом простом примере я проверю формат аргумента пароля в функции updatePassword. Если формат не соответствует требуемому формату, будет выдано сообщение об ошибке. Пароль должен быть строкой и иметь длину от шести до десяти символов.

var Joi = require('joi');
var schema = Joi.string().min(6).max(10);//#A

//#A A string between 6 and 10 characters in length

Чтобы проверить схему относительно реального значения, вы можете использовать Joi.assert(value, schema). При использовании этой функции Джой выдаст ошибку при первой ошибке проверки. Зарегистрированное сообщение об ошибке будет содержать некоторую полезную информацию о том, где проверка не удалась.

var Joi = require('joi');

var schema = Joi.string().min(6).max(10);

var updatePassword = function (password) {

    Joi.assert(password, schema);   //#A
    console.log('Validation success!');  //#B
};

updatePassword('password');   //#C
updatePassword('pass');   //#D

//#A An error will be thrown here if validation fails
//#B If we got here, the validation was successful
//#C Valid password (8 characters)
//#D Invalid password (4 characters)

Если вы запустите этот небольшой пример в терминале, вы увидите вывод, похожий на следующий:

$ node index.js

Validation success! //#A

index.js:121 //#B
            throw new Error(message + error.annotate());//#B
                  ^//#B
Error: "pass"//#B

[1] value length must be at least 6 characters long//#C
...

//#A Success message after validating value 'password'
//#B Error thrown for value 'pass'
//#C Details about what went wrong

Этот предыдущий пример показывает, как проверить простое скалярное значение, но Джой способен на гораздо большее. Часто значения, которые вы хотите проверить, являются более сложными, составными значениями, такими как объекты и массивы.

Более сложный пример: проверка типа соединения

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

Каждый прогноз погоды, отправляемый станциями, должен соответствовать стандартному формату. Отчеты состоят из нескольких полей и могут быть представлены в виде объекта JavaScript. Прогноз погоды из Тайбэя в полдень июля может выглядеть примерно так:

var report = {
    station: 'Taipei',
    datetime: new Date('Wed Jul 22 2015 12:00:00 GMT+0000 (GMT)'),
    temp: 93,
    humidity: 95,
    precipitation: false,
    windDirection: 'E'
};

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

Название изображения

Рисунок 3 — Проверка входящих запросов помогает обеспечить целостность ваших данных  

Понять ваши данные

Первый шаг — подумать об ограничениях, которые я хочу наложить на каждое поле в отчете. Я изложил свои требования к отчетам о погоде в следующей таблице.

Имя поля Тип данных необходимые Другие ограничения
станция строка да максимум 100 символов
Дата и время Дата да
Temp (F) число да От -140 до 140
влажность число да От 0 до 100
осадки логический нет
направление ветра строка нет Один из N, NE, E, SE, S, SW, W, NW

Создать схему

В предыдущем подразделе вы видели, что мы можем указать строку JavaScript в схеме, используя Joi.string(). Тогда не удивительно, что эквивалент для объекта есть Joi.object(). Так же , как Joi.string(), Joi.Object()также имеют методы , которые вы можете цепи на него для дальнейшего расширения схемы. Один из этих методов заключается в том keys(), что он позволяет вам добавлять подсхемы для каждого из свойств объекта. Вот пример создания схемы для объекта с ключами:

var schema = Joi.object().keys({             //#A
       prop1: Joi.string(),                  //#B
       ...
});

//#A Top level schema validates an object
//#B Property prop1 validates a string

Создание схем для объектов с ключами настолько распространено, что Joi также предлагает удобное сокращение для вышеупомянутого. Вы можете заменить Joi.object().keys({...})просто {...}:

var schema = {                               //#A
       prop1: Joi.string(),                  //#B
       ...
};

//#A Top level schema validates an object
//#B Property prop1 validates a string

В листинге ниже приведена полная схема проверки отчетов о погоде.

var schema = {
    station: Joi.string().max(100).required(),//#A
    datetime: Joi.date().required(),//#B
    temp: Joi.number().min(-140).max(140).required(),    //#C
    humidity: Joi.number().min(0).max(100).required(),//#D
    precipitation: Joi.boolean(),//#E
    windDirection: Joi.string()
        .valid(['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'])//#F
};

//#A A required string of max 100 character length
//#B A required date
//#C A required number between -140 and 140
//#D A required number between 0 and 100
//#E An optional boolean
//#F An optional string with a whitelist of values

Мы можем использовать эту схему для проверки некоторых реальных отчетов о погоде сейчас. Мы можем запустить следующий сценарий, чтобы проверить пример отчета по этой схеме:

var Joi = require('joi');

var report = {
    station: 'Taipei',
    datetime: new Date('Wed Jul 22 2015 12:00:00 GMT+0000 (GMT)'),
    temp: 93,
    humidity: 95,
    precipitation: false,
    windDirection: 'E'
};

var schema = {
    station: Joi.string().max(100).required(),
    datetime: Joi.date().required(),
    temp: Joi.number().min(-140).max(140).required(),
    humidity: Joi.number().min(0).max(100).required(),
    precipitation: Joi.boolean(),
    windDirection: Joi.string()
        .valid(['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'])
};

Joi.assert(report, schema);

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

var report = {
    station: 'Taipei',
    datetime: new Date('Wed Jul 22 2015 12:00:00 GMT+0000 (GMT)'),
    temp: 34,
    humidity: 93,
    precipitation: false,
    windDirection: 'WE'//#A
};

//#A Oops, there’s no such direction as WE

Если вы снова запустите скрипт с измененным отчетом, вы должны увидеть ошибку. Сообщение об ошибке будет содержать некоторые полезные выходные данные, чтобы точно определить, что вызвало сбой проверки:

$ node index.js

Error: {
  "station": "Taipei",
  "datetime": "2015-07-22T12:00:00.000Z",
  "temp": 93,
  "humidity": 95,
  "precipitation": false,
  "windDirection" [1]: "WE"
}

[1] windDirection must be one of N, NE, E, SE, S, SW, W, NW

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

Используйте код 39harrison, чтобы получить скидку 39% сегодня!