访问 Cloudflare Workers 站点的压缩数据
Accessing Compressed Data for Cloudflare Workers Sites
我的 cloudflare workers 站点包含 React 应用程序获取的二进制数据。这个二进制数据存储为 gzip 压缩,因为它压缩得非常好(我们谈论的是 20-25 倍的减少,未压缩它太大而无法容纳 10MB KV 限制)。我 运行 遇到的问题是工作人员 return 的数据没有适当的 header:
Content-Encoding: gzip
或者如果我让工作人员添加 header,cloudflare 将加倍压缩响应。那么我如何在 cloudflare KV 中存储 gzip 压缩数据,这样我就可以 return 使用适当的内容编码而不用 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 });
}
上面的工作脚本return是没有内容编码的二进制数据header,所以浏览器不会自动膨胀响应。
然后我尝试通过
手动添加header
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;
}
响应具有正确的 content-encoding 但 cloudflare 压缩了响应,因此现在它在 gzip 中提供 gzip。
有什么方法可以让我可以在 cloudflare KV 中使用正确的 header 提供压缩数据,而无需双重压缩响应?
这是 Service Workers 规范的一个不幸缺陷 -- 它设计用于浏览器,它期望响应主体在 worker 运行之前解压缩,并且不期望它们会再次通过网络传输.为了保持一致,Cloudflare Workers 在传输时必须根据 content-encoding
header 重新压缩数据。但这反过来意味着无法提供已经压缩的数据。
为了解决这个问题,我们 (Cloudflare) 添加了一个名为 encodeBody
的 non-standard Response
选项,可以是 "auto"
(默认值)或 "manual"
(假设 body 已经压缩)。
所以你可以这样写代码:
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;
我的 cloudflare workers 站点包含 React 应用程序获取的二进制数据。这个二进制数据存储为 gzip 压缩,因为它压缩得非常好(我们谈论的是 20-25 倍的减少,未压缩它太大而无法容纳 10MB KV 限制)。我 运行 遇到的问题是工作人员 return 的数据没有适当的 header:
Content-Encoding: gzip
或者如果我让工作人员添加 header,cloudflare 将加倍压缩响应。那么我如何在 cloudflare KV 中存储 gzip 压缩数据,这样我就可以 return 使用适当的内容编码而不用 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 });
}
上面的工作脚本return是没有内容编码的二进制数据header,所以浏览器不会自动膨胀响应。
然后我尝试通过
手动添加headerimport { 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;
}
响应具有正确的 content-encoding 但 cloudflare 压缩了响应,因此现在它在 gzip 中提供 gzip。
有什么方法可以让我可以在 cloudflare KV 中使用正确的 header 提供压缩数据,而无需双重压缩响应?
这是 Service Workers 规范的一个不幸缺陷 -- 它设计用于浏览器,它期望响应主体在 worker 运行之前解压缩,并且不期望它们会再次通过网络传输.为了保持一致,Cloudflare Workers 在传输时必须根据 content-encoding
header 重新压缩数据。但这反过来意味着无法提供已经压缩的数据。
为了解决这个问题,我们 (Cloudflare) 添加了一个名为 encodeBody
的 non-standard Response
选项,可以是 "auto"
(默认值)或 "manual"
(假设 body 已经压缩)。
所以你可以这样写代码:
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;