【问题标题】:Azure Function doesn't respond if Content-Type application/json如果 Content-Type 应用程序/json,Azure 函数不响应
【发布时间】:2018-04-26 13:04:07
【问题描述】:

简介

我正在运行 Azure Function,它是作为 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 函数调用无法正常处理具有 Content-Type: application/json 的 POST 请求。谢谢

【问题讨论】:

  • 是否在 Azure Functions 端启用了 CORS?
  • @Kamo,是的。我确实找到了核心问题,忘记在这里分享。我会尽快发布带有解释的解决方案。

标签: node.js azure azure-functions


【解决方案1】:

使用:

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

允许自定义 json 类型

【讨论】:

  • 感谢@Nurlan,这有帮助。但我仍然不知道为什么 Azure 不能与 app.use(bodyParser.json()) 一起使用。 express 和 azure 函数之间可能会发生覆盖内容类型标头的事情。
  • 其实我觉得content-type有问题,因为type: 'application/json'在标题中看到content-type: application/json时不起作用
【解决方案2】:

深入了解 Azure Function 和正文解析器的工作原理,我找到了问题的根源。

小心request对象

在常规的 expressjs 应用中,我们有 request 对象,它实际上是 Stream 对象的实例,所有传入的数据都通过这个流。

所以,我们有原始数据,我们需要以正确的方式解析它。 bodyParser 中间件有几种方法可以根据流的类型(Content-Type)解析这些数据。
例如bodyParser.json() 方法尝试解析具有application/json 内容类型的JSON 格式的数据。一旦这个函数解析了数据,req.body 就用 JSON 对象实现了。

Azure Functions 不支持流式传输

这就是一切中断的地方:) 是的,它不支持流式传输。并且由于这是真实的数据,因此以不同的方式接受数据。所以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 Functions 不支持流式传输,bodyParser.json() 会尝试从流式传输中获取数据,这就是应用卡住的地方。结果函数执行以超时结束。

希望它对所有在 Azure 中苦苦挣扎的人有所帮助...祝你好运 :)

【讨论】:

    猜你喜欢
    • 2020-10-05
    • 2016-07-16
    • 1970-01-01
    • 1970-01-01
    • 2011-11-01
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 2011-02-03
    相关资源
    最近更新 更多