如何在 Google Cloud Function 中获取原始请求正文?

Posted

技术标签:

【中文标题】如何在 Google Cloud Function 中获取原始请求正文?【英文标题】:How can I get the raw request body in a Google Cloud Function? 【发布时间】:2017-08-14 12:04:29 【问题描述】:

我需要原始请求正文能够对其进行 SHA-1 消化,以验证与请求一起传递给我的 Firebase 函数(在 Google Cloud Functions 上运行)的 Facebook webhook X-Hub-Signature 标头。

问题在于,在这种情况下(带有Content-Type: application/json 标头),GCF 使用bodyParser.json() 自动解析主体,它使用流中的数据(意味着它不能在 Express 中间件链中再次使用)并且仅将解析的 javascript 对象提供为 req.body。原始请求缓冲区被丢弃。

我试图向functions.https.onRequest() 提供一个 Express 应用程序,但这似乎是作为子应用程序运行的,或者请求正文已经被解析的东西,就像你将一个普通的请求-响应回调传递给 @987654326 @。

有什么方法可以禁止 GCF 为我解析正文?或者我可以以某种方式指定我自己的verify 回调到bodyParser.json()?还是有其他方法?

PS:一周前我第一次联系了 Firebase 支持,但由于那里没有回复,我现在在这里尝试。

【问题讨论】:

我的情况和你一样。我试图“重新生成”原始请求有效负载,但这是不可行的。一种安全解决方法是使用随机字符部署函数,以使端点不可猜测。我在我的文章here中详细阐述 现在您可以从 req.rawBody 获取原始正文。 【参考方案1】:

现在您可以从req.rawBody 获取原始正文。它返回Buffer。详情请见documentation。

感谢 Nobuhito Kurose 在comments 发帖。

【讨论】:

如果从functions.https.Request 导入,Typescript 将识别 rawBody,但如果从functions.Request 导入,它将无法识别该字段【参考方案2】:

不幸的是,默认中间件目前无法获取原始请求正文。请参阅:Access to unparsed JSON body in HTTP Functions (#36252545)。

【讨论】:

那太糟糕了。我为该问题加注了星标,并希望尽快添加对此的某种形式的支持。这可能会导致我们部分或完全切换回亚马逊,但到目前为止,我真的很喜欢 Firebase。感谢您提供信息和链接! 已经进行了讨论(超出了公开票),包括我自己在内的几位 Google 员工都为此感到痛苦。我不能承诺时间表,但这必须解决,因为网络挂钩是我们的关键故事之一。不幸的是,它没有进入测试版。【参考方案3】:
 const escapehtml = require('escape-html');

/**
 * Responds to an HTTP request using data from the request body parsed according
 * to the "content-type" header.
 *
 * @param Object req Cloud Function request context.
 * @param Object res Cloud Function response context.
 */
exports.helloContent = (req, res) => 
  let name;

  switch (req.get('content-type')) 
    // '"name":"John"'
    case 'application/json':
      (name = req.body);
      break;

    // 'John', stored in a Buffer
    case 'application/octet-stream':
      name = req.body.toString(); // Convert buffer to a string
      break;

    // 'John'
    case 'text/plain':
      name = req.body;
      break;

    // 'name=John' in the body of a POST request (not the URL)
    case 'application/x-www-form-urlencoded':
      (name = req.body);
      break;
  

  res.status(200).send(`Hello $escapeHtml(name || 'World')!`);
;

【讨论】:

嗨,您可能还想解释一下您的代码,以便更清楚一点

以上是关于如何在 Google Cloud Function 中获取原始请求正文?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Python 中运行 Google Cloud Function 中的子进程

如何修改后台 Cloud Function 的 Google Cloud Pub/Sub 订阅确认截止日期

如何从 Firebase Cloud Function 在 Google Pub/Sub 中发布消息?

如何解决 Google Cloud Function 上的“No module named 'frontend'”错误消息

如何从Google Cloud Function(Cheerio,Node.js)发出多个http请求

在 Google Cloud Function 中设置环境变量