Сбой проверки схемы, хотя параметр доступен - PullRequest
3 голосов
/ 22 марта 2019

Я создал REST API и хочу проверить тело и параметры перед вызовом логики контроллера. Для проверки я использую Joi (https://www.npmjs.com/package/joi).

Допустим, у меня есть маршрут с одним параметром url и несколькими переменными тела. Объект params содержит этот параметр url, но Joi по-прежнему возвращает 400. Подробное сообщение

Требуется идентификатор пользователя

Я попытался создать минималистичный пример, показывающий мой код. Чтобы воспроизвести ошибку, создайте файл app.js

const express = require('express');
const bodyParser = require('body-parser');
const morgan = require('morgan');
const cors = require('cors');

const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cors());

app.use('/users', require('./routes/users.js'));

app.listen(3000);

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

const express = require('express');
const router = express.Router();

const usersController = require('../controllers/users.js');
const usersControllerPolicy = require('../policies/users.js');

router.get('/:userId', usersControllerPolicy.getUserById, usersController.getUserById);

module.exports = router;

А это users.js файл контроллера

exports.getUserById = async (req, res, next) => {
    const { userId } = req.params;
    return res.status(200).json("everything is fine");
};

Когда дело доходит до политики, я создал политику users.js , которая добавляет необходимую схему в промежуточное ПО

const joi = require('joi');

const schemaValidation = require('../middleware/schemaValidation.js');

module.exports = {
    getUserById: (req, res, next) => {
        schemaValidation({
            params: {
                userId: joi.string().guid().required()
            },
            body: {}
        }, req, res, next);
    }
}

и тогда схема проверяется моим schemaValidation.js

const joi = require('joi');

module.exports = (schema, req, res, next) => {
    const { error } = joi.validate(req, schema);

    if (error)
        return res.status(400).json("something went wrong");

    next(); // execute the controller logic
}

Как видите, я пропускаю весь объект req. Я делаю это, потому что иногда мне нужно проверить тело и параметры. Параметр url userId не найден Джои, поэтому мне возвращается код состояния 400.

Как я могу исправить мою проверку промежуточного программного обеспечения для проверки обоих объектов в пределах объекта req?

1 Ответ

2 голосов
/ 25 марта 2019

На самом деле Джой имеет доступ к userId и может правильно его проверить или нет, вот почему:

// replace this
const { error } = joi.validate(req, schema);
// by this
console.log(req.params.userId);
const { error } = joi.validate(req, schema);
console.log(error.toString());

вывод на консоль при посещении localhost:3000/users/10:

10
ValidationError: child "params" fails because [child "userId" fails because ["userId" must be a valid GUID]]

и при посещении URL-адреса, содержащего действительный идентификатор GUID в параметрах, например ``:

ad3756ae-2661-4d8c-aeda-dd51deef5ea9
ValidationError: "_readableState" is not allowed. "readable" is not allowed. "_events" is not allowed. "_eventsCount" is not allowed. "_maxListeners" is not allowed. "socket" is not allowed. "connection" is not allowed. "httpVersionMajor" is not allowed. "httpVersionMinor" is not allowed. "httpVersion" is not allowed. "complete" is not allowed. "headers" is not allowed. "rawHeaders" is not allowed. "trailers" is not allowed. "rawTrailers" is not allowed. "aborted" is not allowed. "upgrade" is not allowed. "url" is not allowed. "method" is not allowed. "statusCode" is not allowed. "statusMessage" is not allowed. "client" is not allowed. "_consuming" is not allowed. "_dumped" is not allowed. "next" is not allowed. "baseUrl" is not allowed. "originalUrl" is not allowed. "_parsedUrl" is not allowed. "query" is not allowed. "res" is not allowed. "route" is not allowed

Так что Джой имеет доступ ко всему, что ему нужно, и работает как положено. ?


Так почему ошибка 400?

Что ж, после входа в консоль, Джой не проходит проверку для req. Это потому, что по умолчанию Джой не принимает неизвестные параметры в объекте. Вы можете изменить это с помощью .unknown(true), который проверяет объект, даже если включены неизвестные параметры.

Итак, в вашем случае вы должны заменить код policies/users.js следующим:

const joi = require('joi');

const schemaValidation = require('../middleware/schemaValidation.js');

module.exports = {
    getUserById: (req, res, next) => {

        // properly defines a schema with optional parameters
        const schema = joi.object({
            params: joi.object({
                userId: joi.string().guid().required()
            }).unknown(true),
        }).unknown(true);

        schemaValidation(schema, req, res, next);
    }
}

Теперь, когда вы снова посещаете URL-адрес, содержащий действительный идентификатор GUID (например, http://localhost:3000/users/ad3756ae-2661-4d8c-aeda-dd51deef5ea9),, все происходит, как ожидалось, и ""everything is fine" отправляется сервером! ?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...