Функция Azure не отвечает, если приложение Content-Type / json - PullRequest
0 голосов
/ 26 апреля 2018

Введение

У меня запущена функция Azure, которая написана как приложение Expressjs. У меня есть простые маршруты для проверки

// Test get
router.get('/test', (req, res) => {
  return res.status(200).send({ result: req.query });
});

// Test post
router.post('/test', (req, res) => {
  return res.status(200).send({ result: req.body });
});

Конфигурация приложения следующая

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

Выпуск

Я пытаюсь сделать POST /test запрос.

С Content-Type: application/javascript хорошо работает
С Content-Type: application/json он вызывает функцию, но ничего не выполняется, и возвращается таймаут.

Нет проблем с маршрутом GET /test.
Нет проблем с локальным запуском.

Нужна помощь, чтобы понять, почему вызов функции Azure не работает должным образом для запросов POST с Content-Type: application / json. Спасибо

Ответы [ 2 ]

0 голосов
/ 08 мая 2018

Более подробно о том, как работают функция Azure и анализатор тела, я выяснил корень проблемы.

Будьте осторожны с request объектом

В обычном приложении expressjs у нас есть request объект, который на самом деле является экземпляром объекта Stream, и все входящие данные проходят через эту потоковую передачу.

Итак, у нас есть необработанные данные, и нам нужно правильно их проанализировать. bodyParser Промежуточное ПО имеет несколько методов для анализа этих данных из потока на основе его типа (Content-Type).
Например, метод bodyParser.json() пытается проанализировать данные в формате JSON с типом содержимого application/json. Как только эта функция анализирует данные, req.body выполняется с объектом JSON.

Функции Azure не поддерживают потоковую передачу

Здесь все ломается :) Да, потоковая передача не поддерживается. И поскольку это правда, данные принимаются по-другому. Поэтому объект request больше не является объектом Stream. И req.body уже выполнено с поступающими данными. Для application/json он содержит объект JSON, для других типов контента он содержит необработанные данные, которые необходимо проанализировать. В качестве примера я могу поделиться своим простым кодом промежуточного программного обеспечения для анализа данных с типом x-www-form-urlencoded.

'use strict';

// https://github.com/sindresorhus/query-string
const queryString = require('query-string');

/**
 * Azure body parser
 */
function azureBodyParser() {
  return function(req, res, next) {
    // x-www-form-urlencoded
    if (req.headers['content-type'] === 'application/x-www-form-urlencoded') {
      req.body = queryString.parse(req.body, { arrayFormat: 'bracket' });
    }

    next();
  };
}

module.exports = azureBodyParser;

Тогда используйте это так

const app = require('express')();
const azureBodyParser = require('./middlewares/azureBodyParser');

// ...

app.use(azureBodyParser());

Вы можете изменить его и добавить больше обработчиков для других типов контента.
Также нам нужно указать некоторые условия, запускаем ли мы наше приложение на сервере или как функцию Azure, например, возможно использование переменных ENV. Это твое домашнее задание:)

Проблема

Поскольку функции Azure не поддерживают потоковую передачу, bodyParser.json() пытается получить данные из потока, и в этот момент приложение застревает. В результате выполнение функции заканчивается тайм-аутом.

Надеюсь, это будет полезно всем, кто борется с Azure ... Удачи:)

0 голосов
/ 26 апреля 2018

использование:

app.use(bodyParser.json({ type: 'application/*+json' }));

для разрешения пользовательских типов JSON

...