В коде ниже данные от пользователей принимаются и сохраняются как есть. То есть мы полагаем, что пользователи вводят данные корректно:
app.post('/users', (req, res) => {
const {
name,
email,
password,
passwordConfirmation,
} = req.body
const user = {
name,
email,
password,
}
state.users.push(user)
res.redirect('/users')
})
На практике такого не бывает. Данные могут быть неполными, ошибочными или неподходящими для нашей системы. В этом уроке мы научимся работать с такими данными.
Что такое валидация
Получив данные от пользователя, мы должны их проверить. Такая проверка называется валидацией. Валидация включает два основных элемента:
- Проверка входных данных на корректность — например, заполнены ли обязательные поля или совпадает ли пароль и его подтверждения
- Проверка возможности выполнить операцию — например, мы не сможем зарегистрировать нового пользователя, если он пытается ввести почту, связанную с уже существующим аккаунтом
Как проверить корректность данных
Проверить корректность введенного пароля можно простым сравнением:
const {
password,
passwordConfirmation,
} = req.body
if (password !== passwordConfirmation) {
// Что-то делаем, если пароли не совпали
}
Что делать дальше? Будет логично, если мы отобразим ту же форму с двумя важными дополнениями:
- Нужно сохранить введенные данные, чтобы пользователю не пришлось заполнять все поля заново
- Нужно вывести сообщения об ошибках — например, списком над формой.
В Fastify есть встроенный механизм валидации данных. Дополнительно к нему мы подключим библиотеку yup
, которая облегчит задачу:
npm i yup
Посмотрим сразу на готовый код обработчика, а потом разберем его.
app.post('/users', {
attachValidation: true,
schema: {
body: yup.object({
name: yup.string().min(2, 'Имя должно быть не меньше двух символов'),
email: yup.string().email(),
password: yup.string().min(5),
passwordConfirmation: yup.string().min(5),
}),
},
validatorCompiler: ({ schema, method, url, httpPart }) => (data) => {
if (data.password !== data.passwordConfirmation) {
return {
error: Error('Password confirmation is not equal the password'),
}
}
try {
const result = schema.validateSync(data)
return { value: result }
}
catch (e) {
return { error: e }
}
},
}, (req, res) => {
const { name, email, password, passwordConfirmation } = req.body
if (req.validationError) {
const data = {
name, email, password, passwordConfirmation,
error: req.validationError,
}
res.view('src/views/users/new', data)
return
}
const user = {
name,
email,
password,
}
state.users.push(user)
res.redirect('/users')
})
Вторым параметром в метод post()
передаются параметры в виде объекта. Для работы валидации нам достаточно три свойства в этом объекте:
attachValidation
— этот параметр позволяет включить обработчик запроса, если данные не валидны. По умолчанию, если валидация не проходит, ответ на запрос с ошибкой валидации отправляется сразу, наш обработчик не выполняется. Это не всегда нужно. Например, мы хотим отобразить ошибки и повторно отрисовать форму. Для этого мы можем установить этот параметр в значениеtrue
schema
— здесь мы задаем схему данных. Данные будут сопоставляться схеме, и если где-то будет несоответствие, валидация выдаст ошибку, текст которой можно задать дополнительным параметром. Например, для проверки минимальной длины имени задан текст'Имя должно быть не меньше двух символов'
. Если текст не задать, то yup выведет свой текст ошибки. В примере выше мы указали требования для тела запроса (body
). Оно должно содержать несколько полей. Для каждого поля мы описали требования с помощью методов yup. Например, пароль должен быть строкой и содержать как минимум пять символов. Библиотека yup содержит множество различных инструментов для валидации, ознакомиться с ними можно в документацииvalidatorCompiler
— здесь формируется функция валидации. В свойстве мы должны указать функцию, которая в свою очередь возвращает функцию валидации. В общем случае нам достаточно вызывать метод валидацииvalidateSync()
и перехватить ошибки. Функция валидации должна вернуть объект. Если ошибки найдены, то их нужно поместить в свойствоerror
. Дополнительно мы можем указать любые проверки. На примере выше мы добавили проверку поля подтверждения пароля, что значение равно полю самого пароля. Здесь могут быть любые другие проверки. Например, мы можем проверять существует ли пользователь с такими же данными и многое другое
Следующим шагом нам остается добавить отображение ошибок на форму:
html
body
if error
p= error.message
form(action = '/users', method = 'post')
div
label Имя:
input(type = 'text', name = 'name', value = name)
div
label Email:
input(type = 'email', name = 'email', value = email, required = true)
div
label Пароль:
input(type = 'password', name = 'password', value = password, required = true)
div
label Подтверждение пароля:
input(type = 'password', name = 'passwordConfirmation', value = passwordConfirmation, required = true)
input(type = 'submit', value = 'Зарегистрировать')
Фреймворк позволяет гибко настраивать валидацию, создавать различные схемы и переиспользовать их в разных обработчиках, добавлять общую валидацию для всех запросов. В этом уроке мы разобрали базовое использование, но уже его достаточно для решения основных задач.
Самостоятельная работа
- Выполните у себя на компьютере все шаги из урока. Модифицируйте форму для добавления нового пользователя и обработчик так, чтобы происходила валидация данных, введенных пользователем
- Сделайте то же самое для курсов. При добавлении нового курса должна происходить валидация названия и описания курса. Название курса должно быть не короче 2 символов, а описание должно содержать не менее 10 символов.
- Запустите приложение и попробуйте добавлять новые сущности. Проверьте, что при вводе некорректных данных форма остается заполненной и отображаются сообщения об ошибках
- Залейте изменения на GitHub
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.