【问题标题】:Accessing Compressed Data for Cloudflare Workers Sites访问 Cloudflare Workers 站点的压缩数据
【发布时间】:2021-02-26 09:07:31
【问题描述】:

我的 cloudflare workers 站点包含 React 应用程序获取的二进制数据。此二进制数据存储为 gzip 压缩,因为它压缩得非常好(我们谈论的是 20-25 倍的缩减,而未压缩它太大而无法适应 10MB KV 的限制)。我遇到的问题是工作人员返回的数据没有适当的标头:

Content-Encoding: gzip

或者如果我让工作人员添加标头,cloudflare 将加倍压缩响应。那么如何将 gzip 压缩数据存储在 cloudflare KV 中,以便我可以使用正确的内容编码返回它,而无需 cloudflare 双重压缩响应?

参考

为了尽量减少复制:这是我正在使用的两个工作脚本。

import { getAssetFromKV, mapRequestToAsset } from '@cloudflare/kv-asset-handler'

addEventListener('fetch', event => {
  try {
    event.respondWith(handleEvent(event))
  } catch (e) {
    event.respondWith(new Response('Internal Error', { status: 500 }))
  }
})

async function handleEvent(event) {
  const cacheControl = { browserTTL: 60 * 60 * 6 };
  return await getAssetFromKV(event, { mapRequestToAsset, cacheControl });
}

上面的worker脚本返回的二进制数据没有内容编码头,所以浏览器不会自动膨胀响应。

然后我尝试通过手动添加标题

import { getAssetFromKV, mapRequestToAsset } from '@cloudflare/kv-asset-handler'

addEventListener('fetch', event => {
  try {
    event.respondWith(handleEvent(event))
  } catch (e) {
    event.respondWith(new Response('Internal Error', { status: 500 }))
  }
})

async function handleEvent(event) {
  const cacheControl = { browserTTL: 60 * 60 * 6 };
  const resp = await getAssetFromKV(event, { mapRequestToAsset, cacheControl });
  resp.headers.set("Content-Encoding", "gzip");
  return resp;
}

响应具有正确的内容编码,但 cloudflare 会压缩响应,因此现在它在 gzip 中提供 gzip。

有没有什么办法可以让我在 cloudflare KV 中使用正确的标头提供压缩数据,而无需双重压缩响应?

【问题讨论】:

  • 您可以尝试添加Content-Type: application/octet-stream 标头(除了Content-Encoding)吗?这可能会阻止 CF 再次压缩它。 support.cloudflare.com/hc/en-us/articles/…
  • 好主意,我试过了,不幸的是它仍然被双重压缩。似乎添加内容编码标头是在指示 cloudflare 压缩响应,即使它是不受支持的内容类型。

标签: cloudflare cloudflare-workers


【解决方案1】:

这是 Service Workers 规范的一个不幸缺陷——它是为在浏览器中使用而设计的,它希望在工作程序运行之前解压缩响应主体,并且不希望它们再次通过网络传输。为了使事情保持一致,Cloudflare Workers 在传输时必须根据content-encoding 标头重新压缩数据。但这反过来又意味着无法提供已经压缩的数据。

为了解决这个问题,我们(Cloudflare)添加了一个非标准的Response 选项,称为encodeBody,可以是"auto"(默认值)或"manual"(假设主体已经压缩)。

所以你可以这样写代码:

let resp = await getAssetFromKV(event, { mapRequestToAsset, cacheControl });

// Make a new response with the same body but using manual encoding.
resp = new Response(resp.body, {
  status: resp.status,
  headers: resp.headers,
  encodeBody: "manual"
});

// Modify headers and return.
resp.headers.set("Content-Encoding", "gzip");
return resp;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-28
    • 1970-01-01
    • 2012-01-27
    • 2016-02-04
    • 1970-01-01
    • 2012-10-14
    相关资源
    最近更新 更多