【问题标题】:Accept GZIP-encoded request body as-is in Firebase Functions在 Firebase 函数中按原样接受 GZIP 编码的请求正文
【发布时间】:2021-10-27 09:12:17
【问题描述】:

在 Firebase 函数中,我试图接受一个大字符串并将其存储。

exports.store = functions.https.onRequest(async (req, res) => {
    const body : string = req.body;
    await store(body);
    return req.send(...);
});

我发现使用 GZIP 可以提高性能并将文件大小减少大约 3-4 倍。

问题是,如果客户端发送一个 GZip 编码的字符串,内容编码如下:

header("Content-Encoding", "gzip")

然后对req.body 的调用将“自动”将字符串解码为UTF-8。这既大大降低了性能,又需要我再次压缩字符串以有效地将其存储在服务器中。

如果我没有指定内容编码,那么端点将按预期工作(即它不会解压缩字符串并将其按原样存储,因此运行速度更快)。问题是我无法验证用户是否发送了 gzip 压缩字符串而不是 UTF-8 字符串,除非我实施了一些技巧来检查字符串中的模式。

我相信有一些简单的解决方案,例如

functions.dontInflateTheRequestPleaseThanks();
exports.store = functions.https.onRequest(async (req, res) => {
    if (req.headers["content-encoding"] !== "gzip") return res.status(415).send("gzip please");
    const body : string = req.body;
    await store(body);
    return req.send(...);
});

【问题讨论】:

    标签: node.js express http google-cloud-functions gzip


    【解决方案1】:

    您有一些中间件已经填充了req.body,并在此过程中自动解压缩。相反,您可以自己收集尸体。

    注意:已填充req.body 的中间件使用与下面代码相同的on("data")/on("end") 技术,因此您必须确保此代码与填充中间件。

    为确保这一点,请将整个 express 应用传递给 functions.https.onRequest

    exports.store = functions.https.onRequest(express().use(async (req, res, next) => {
      if (req.headers["content-encoding"] !== "gzip")
        return res.status(415).send("gzip please");
      var buffers = [];
      req.on("data", function(data) {
        buffers.push(data);
      }).on("end", async function() {
        await store(Buffer.concat(buffers));
        res.send(...);
      });
    }));
    

    【讨论】:

    • on("data")on("end") 的主体永远不会被调用,挂起函数、服务器和模拟器。
    • @FudgeFudge,我把它简化得太多了。已编辑我的答案并包含一句警告。
    • 如何禁用中间件?在firebase中甚至有可能吗?
    • 尝试将整个 express 应用程序传递给 functions.https.onRequest,如 here 所述。
    【解决方案2】:

    诀窍是不传递Content-Encoding=gzip,因此 express(底层框架)不会膨胀(解压缩)请求。然后将请求识别为 gzip,传递 ContentType=application/gzip

        if (req.headers["content-encoding"] === "gzip") {
            res.status(415).send("Don't specify gzip as the content-encoding. This trips up firebase.");
            return;
        }
        if (req.headers["content-type"] !== "application/gzip") {
            res.status(415).send("must be compressed using gzip");
            return;
        }
        // Then body is guaranteed to not be fiddled with.
        const body = req.body;
    

    【讨论】:

      猜你喜欢
      • 2018-02-27
      • 2018-06-28
      • 2014-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-27
      相关资源
      最近更新 更多