Express.js неожиданное поведение

#javascript #node.js #express

Вопрос:

я получаю какое-то неожиданное поведение в своем приложении. Мой app.js код выглядит так:

 app.use(bodyParser.urlencoded({
    extended: true
}));
app.use(bodyParser.json());

app.use(bodyParser.xml({
    xmlParseOptions: {
        normalize: true,
        normalizeTags: false,
        explicitArray: true
    }
}));

//app.use(bodyParser.raw({ inflate: true, limit: '5000kb', type: 'text' }));



app.get(constants.APP_NAME_URL   constants.VERSION_URL   '/version', function (request, response) {
    response.sendFile('version.json', {root: path.join('./files')});
});


app.use(constants.APP_NAME_URL   constants.VERSION_URL   '/accounts', accountsRouter);
app.use(constants.APP_NAME_URL   constants.VERSION_URL   '/consents', consentsRouter,
    function (request,response) {
        console.log("hi");
    });

app.use(constants.APP_NAME_URL   constants.VERSION_URL   '/funds-confirmations', fundsConfirmationRouter);

app.use(constants.APP_NAME_URL   constants.VERSION_URL   '/periodic-payments', paymentsRouter);
app.use(constants.APP_NAME_URL   constants.VERSION_URL   '/payments', paymentsRouter);
app.use(constants.APP_NAME_URL   constants.VERSION_URL   '/bulk-payments', paymentsRouter);

app.use(constants.APP_NAME_URL   constants.VERSION_URL   '/redirect', redirectRouter);

app.use(constants.APP_NAME_URL   constants.VERSION_URL   '/e2e-status', e2eRouter);

app.use(function(err, req, res, next) {
    var businessErrorMessage = err.errorMessage ? err.errorMessage : constants.ERROR_MESSAGE_UNEXPECTED_ERROR;
    var businessErrorCode = err.errorCode ? err.errorCode : constants.ERROR_CODE_UNEXPECTED_ERROR;
    var errorResponse = errorHandler.errorResponse(constants.ERROR_CATEGORY_ERROR,
        businessErrorCode,
        businessErrorMessage);
    debug(err.stack);
    responseBuilder.respond(req, res, errorResponse, 400, constants.CONTENT_TYPE_APPLICATION_JSON);
});
 

Когда я отправляю запрос на конечную точку /согласия с телом JSON и типом содержимого application/xml в заголовке, он напрямую направляется в промежуточное программное обеспечение для бизнес-ошибок, а не на маршрутизатор согласия при отладке приложения.

Я имею в виду такую просьбу:

 POST /sandbox/v1/consents HTTP/1.1
Host: localhost:33589
X-Request-ID: 9a906a04-0610-4e94-9f6b-1bcf25f05214
Content-Type: application/xml
TPP-Redirect-Preferred: false
User-Agent: PostmanRuntime/7.19.0
Accept: */*
Cache-Control: no-cache
Host: localhost:33589
Accept-Encoding: gzip, deflate
Content-Length: 192
Connection: keep-alive
cache-control: no-cache

{
 "access": {
  "availableAccountsWithBalance": "allAccounts"
 },
 "recurringIndicator": true,
 "validUntil": "2021-09-08",
 "frequencyPerDay": 4,
 "combinedServiceIndicator": false
}
 

Если я отправлю этот запрос через почтальона, я получу промежуточное программное обеспечение для бизнес-ошибок вместо маршрутизатора согласия. Если я изменю тип содержимого на application/json или что-то бессмысленное, например «привет», я попаду на маршрутизатор согласия, как я могу объяснить такое поведение?

Комментарии:

1.Пожалуйста, добавьте код для consentsRouter и каковы значения constants.APP_NAME_URL constants.VERSION_URL ?

2. К чему ты клонишь bodyParser.xml() ? Это не является частью стандартного модуля bodyparer. Пожалуйста, укажите ссылку на модуль, из которого вы это получаете. Похоже, что вы используете его неправильно.

3. @jfriend00 этот npmjs.com/package/body-parser-xml

4. @jfriend00 Я не думаю, что это должно что-то делать с моими константами, потому что, если я использую приложение/json в качестве типа контента, все работает так, как должно быть

5. Итак, вы настраиваете Content-Type: application/xml , но ваш контент не является XML. Содержимое выглядит как JSON. Это было бы серьезной проблемой. Это также объясняет, почему он работает, когда вы устанавливаете Content-Type: application/json . Итак, почему бы вам просто не использовать тип содержимого JSON?

Ответ №1:

Если все , что вы пытаетесь сделать, — это отправить сообщение об ошибке, если кто-то отправит вам сообщение Content-Type: application/xml , то вы можете сделать это с помощью простого промежуточного программного обеспечения, подобного этому:

 app.use((req, res, next) => {
    if (req.get('Content-Type') === "application/xml") {
        res.status(415).send("Unsupported content-type");
    } else {
        next();
    }
});
 

И поставьте это перед любым из ваших обработчиков запросов, чтобы он получил первую трещину по запросу. Если вы хотите, чтобы это действовало только для запросов на публикацию, вы также можете проверить, действует ли req.method === "POST" это .

И удалите промежуточное программное обеспечение для этого типа контента здесь:

 app.use(bodyParser.xml({...}));
 

Если вы не собираетесь использовать этот тип контента, то вам не нужно его анализировать.

Комментарии:

1. Ладно, я забыл упомянуть, у меня есть несколько конечных точек, где я использую XML, так что я не могу сделать это так, я думаю

2. @YasinEraslan — Ну, на самом деле вы не раскрываете здесь всю проблему. Вы можете упорядочить маршруты так, чтобы те, которые используют application/xml, находились ДО этого промежуточного программного обеспечения, а те, которые вы хотите запретить, — ПОСЛЕ этого промежуточного программного обеспечения. Или вы можете превратить это промежуточное программное обеспечение в функцию многократного использования и применить его только к тем маршрутам, которые вы хотите защитить.