You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
For identical response bodies, the ETag should remain stable across requests, regardless of how the body is chunked.
What do you see instead?
When combining the etag() and cache() middleware on Cloudflare Workers, the ETag value changes on every request—even when the response body remains the same. This breaks 304 behavior and prevents effective caching.
Additional information
Suspected Cause
On Cloudflare Workers, responses returned from the cache expose .body as a ReadableStream. The chunk structure of this stream is not consistent across requests.
Native use of DigestStream in Cloudflare Workers for consistent hashing
Better semantic clarity: digesting a stream should take a stream, not a fully merged Uint8Array
Avoids confusion: the current (body: Uint8Array) => ArrayBuffer signature suggests that Hono reads the full body first, which it doesn’t. The chunked-digest logic is hidden from users and may cause incorrect assumptions.
The text was updated successfully, but these errors were encountered:
SubtleCrypto does not support incremental digest generation, so Hono's cache middleware is currently designed as it is.
In general, responses that are divided into multiple chunks are often better generated in advance at an appropriate time before the etag middleware.
In your application's case, generating the ETag before the cache middleware would be advantageous as it would allow the generated ETag value to be cached along with the response.
diff --git i/src/index.ts w/src/index.ts
index 9a97ad7..4b3d9d1 100644
--- i/src/index.ts+++ w/src/index.ts@@ -12,6 +12,19 @@ app.use(
cacheControl: "max-age=3600",
})
);
+app.use("*", async (c, next) => {+ const body = c.res.clone().body;+ if (body) {+ const digestStream = new crypto.DigestStream("SHA-256");+ body.pipeTo(digestStream);+ const digest = await digestStream.digest;+ const hexString = [...new Uint8Array(digest)]+ .map((b) => b.toString(16).padStart(2, "0"))+ .join("");+ c.res.headers.set("ETag", `W/"${hexString}"`);+ }+ next();+});
// Generate a payload of the given size
function generatePayload(size: number) {
Given this situation, we do not anticipate changes to the etag middleware API until SubtleCrypto supports incremental generation.
What version of Hono are you using?
4.7.6
What runtime/platform is your app running on? (with version if possible)
Cloudflare Workers
What steps can reproduce the bug?
Repository: https://github.com/rwv/hone-etag-large-payload-test
Live demo: https://hono-etag-large-payload-test.rwv.dev/
Steps:
ETag
header changes each timeWhat is the expected behavior?
For identical response bodies, the ETag should remain stable across requests, regardless of how the body is chunked.
What do you see instead?
When combining the
etag()
andcache()
middleware on Cloudflare Workers, the ETag value changes on every request—even when the response body remains the same. This breaks 304 behavior and prevents effective caching.Additional information
Suspected Cause
On Cloudflare Workers, responses returned from the cache expose
.body
as aReadableStream
. The chunk structure of this stream is not consistent across requests.This breaks the assumption made in #3604:
The above is speculative, based on observed behavior.
Suggestion
PR #3832 introduced the
generateDigest(body: Uint8Array)
option, which is useful but not sufficient in this case.This would:
DigestStream
in Cloudflare Workers for consistent hashingUint8Array
(body: Uint8Array) => ArrayBuffer
signature suggests that Hono reads the full body first, which it doesn’t. The chunked-digest logic is hidden from users and may cause incorrect assumptions.The text was updated successfully, but these errors were encountered: