© 2026 Hedgehog Software, LLC

TwitterGitHubDiscord
More
CommunitiesDocsAboutTermsPrivacy
Search
Star
Setup for Free
Cloudflare DevelopersCD
Cloudflare Developers•3y ago
Shirokawa

Using Cache API with gzipped R2 object

Hi!

I am trying to use the Cache API for a response that contains a gzip encoded html file (persisted in R2) as the response body.

The Worker uses a custom domain.

The problem is, when trying to return the body as a
ReadableStream
ReadableStream
(see code below), cache match stops returning anything and the full code evaluates every time.

I have verified that the Cache works as expected when I decompress the body before returning it as the response body.

The code looks roughly like this (some business logic removed for brevity):

export interface Env {
  R2: R2Bucket;
}

interface CustomExportedHandler extends Omit<ExportedHandler, "fetch"> {
  fetch: ExportedHandlerFetchHandler<Env, unknown>;
}

const handler: CustomExportedHandler = {
  async fetch(request, { R2 }, ctx): Promise<Response> {
    try {
      const url = new URL(request.url);

      const cacheKey = `https://${url.hostname}${url.pathname}`;
      const cacheMaxAge = 60 * 15; // 15 min
      const cache = caches.default;

      const cachedPage = await cache.match(cacheKey);

      let response = new Response(cachedPage?.body, cachedPage);
      // Set Cache-Control headers (otherwise default from Cloudflare is 4h)
      response.headers.set("Cache-Control", `s-maxage=${cacheMaxAge}`);

      if (!response) {
        const r2Object = await R2.get(url.pathname);
        if (!r2Object) throw Error("No page data.");

        response = new Response(r2Object.body, {
          ...response,
          encodeBody: "manual",
        });
        response.headers.set("content-encoding", "gzip");
        response.headers.set("content-type", "text/html;charset=utf-8");

        ctx.waitUntil(cache.put(cacheKey, response.clone()));
      }
      return response;
    } catch (e: unknown) {
      if (e instanceof Error) {
        console.error(`Error requesting: ${request.url}\n -> ${e.message}`);
      }
      return new Response("Not found", { status: 404 });
    }
  },
};

export default handler;
export interface Env {
  R2: R2Bucket;
}

interface CustomExportedHandler extends Omit<ExportedHandler, "fetch"> {
  fetch: ExportedHandlerFetchHandler<Env, unknown>;
}

const handler: CustomExportedHandler = {
  async fetch(request, { R2 }, ctx): Promise<Response> {
    try {
      const url = new URL(request.url);

      const cacheKey = `https://${url.hostname}${url.pathname}`;
      const cacheMaxAge = 60 * 15; // 15 min
      const cache = caches.default;

      const cachedPage = await cache.match(cacheKey);

      let response = new Response(cachedPage?.body, cachedPage);
      // Set Cache-Control headers (otherwise default from Cloudflare is 4h)
      response.headers.set("Cache-Control", `s-maxage=${cacheMaxAge}`);

      if (!response) {
        const r2Object = await R2.get(url.pathname);
        if (!r2Object) throw Error("No page data.");

        response = new Response(r2Object.body, {
          ...response,
          encodeBody: "manual",
        });
        response.headers.set("content-encoding", "gzip");
        response.headers.set("content-type", "text/html;charset=utf-8");

        ctx.waitUntil(cache.put(cacheKey, response.clone()));
      }
      return response;
    } catch (e: unknown) {
      if (e instanceof Error) {
        console.error(`Error requesting: ${request.url}\n -> ${e.message}`);
      }
      return new Response("Not found", { status: 404 });
    }
  },
};

export default handler;
Cloudflare Developers banner
Cloudflare DevelopersJoin
Welcome to the official Cloudflare Developers server. Here you can ask for help and stay updated with the latest news
85,042Members
Resources
Was this page helpful?

Similar Threads

Recent Announcements

Similar Threads

Caching R2 using worker cache api
Cloudflare DevelopersCDCloudflare Developers / workers-and-pages-help
3y ago
Should you use the cache API when requesting from R2?
Cloudflare DevelopersCDCloudflare Developers / workers-and-pages-help
3y ago
Using `R2 + image transformation API` vs the `Images` service
Cloudflare DevelopersCDCloudflare Developers / workers-and-pages-help
2y ago
Confused with how to use R2 S3 API.
Cloudflare DevelopersCDCloudflare Developers / workers-and-pages-help
2y ago