Меню

Валидация запросов к серверу Express

01.07.2018 - Back-end, NodeJS

Input Validation

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

В нашем конкретном примере, мы имеем дело с простым объектом только с одним свойством — name. Мы напишем логику по валидации. Если name не существует или name.length меньше 3, тогда мы вернем ошибку на клиент. Соглашение RESTful по возвратам, рекомендует вернуть 400 HTTP status code, что означает Bad Request (плохой запрос) — res.status(400). А затем мы можем выслать еще сообщение. Также напишем return чтобы не продолжать выполнение функции. Это самый простой вариант.

app.post('/api/courses/', (req, res) => {

    if (!req.body.name || req.body.name.length < 3) {
        //400 Bad Request
        res.status(400).send("Name is required and should be minimum 3 characters.");
        return;
    }

    const course = {
        id: courses.length + 1,
        name: req.body.name
    };
    courses.push(course);
    console.log(courses);
    res.send(course);
});

В реальном приложении, более вероятно что вы будет работать со сложными объектами. Обратите внимание на пакет, которые сделает валидацию входных данных гораздо проще — npm joi.

Сейчас посмотрим, как заменить нашу логику валидации, на joi.

npm i joi

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

const Joi = require('joi');

У нас есть класс Joi. Теперь вернемся к нашему route handler. У Joi нам в первую очередь надо определить Schema. Schema определяет какие свойства допустимы в объекте. Какой тип каждого свойства. И т.д. и т.п.

Итак, определяем Schema.
Создаем объект schema, указываем свойство name, а в нем Joi.string(). Так мы говорим, что name это строка, далее указываем метод min, где указываем сколько минимально должно быть символов, а также указываем что это поле обязательное — required. Если хотите узнать обо всех возможных методах, смотрите документацию.

Итак, мы настролили схему. Теперь вызовем метод validate, класса Joi, передадим ему тело запроса первым параметром, а вторым — передадим схему. Этот метод вернет объект. Давайте сохраним его в константе result. В нашем примере, мы просто выведем результат в консоль.

Вот что он вернет при верном запросе

{ error: null,
  value: { name: 'new course5' },
  then: [Function: then],
  catch: [Function: catch] }

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

Поэтому у себя в коде проверим на результат свойство error. И в сообщение передадим саму ошибку.

app.post('/api/courses/', (req, res) => {

    const schema = {
        name: Joi.string().min(3).required()
    };

    const result = Joi.validate(req.body, schema);

    if (result.error) {
        //400 Bad Request
        res.status(400).send(result.error.details[0].message);
        return;
    }

    const course = {
        id: courses.length + 1,
        name: req.body.name
    };
    courses.push(course);
    console.log(courses);
    res.send(course);
});
Метки: , , , , ,

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *