Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 117 additions & 0 deletions src/content/docs/workers/examples/cache-post-request.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ description: Cache POST requests using the Cache API.

import { TabItem, Tabs } from "~/components";

POST requests can be cached either via Cache API or [Workers KV](/kv/).

## Using Cache API

The Cache API allows for a simple API to cache POST requests. However, Cache API does not [support the use of Tiered Caching or Reserve Reserve](/workers/reference/how-the-cache-works/#cache-api). To increase Cache Hit Rates and offload origin load, consider using Workers KV instead (see below).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The Cache API allows for a simple API to cache POST requests. However, Cache API does not [support the use of Tiered Caching or Reserve Reserve](/workers/reference/how-the-cache-works/#cache-api). To increase Cache Hit Rates and offload origin load, consider using Workers KV instead (see below).
The Cache API allows for a simple API to cache POST requests. However, Cache API does not support the use of [Tiered Caching or Reserve Reserve](/workers/reference/how-the-cache-works/#cache-api). To increase Cache Hit Rates and offload origin load, consider using Workers KV instead (see below).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggested which part of the text was included as the link to prevent potential confusion.


<Tabs syncKey="workersExamples"> <TabItem label="JavaScript" icon="seti:javascript">

```js
Expand Down Expand Up @@ -148,3 +154,114 @@ async def on_fetch(request, _, ctx):
```

</TabItem> </Tabs>


## Using Workers KV

KV allows
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this PR is still a WIP so may get addressed later but this reads as incomplete for now.


<Tabs syncKey="workersExamples"> <TabItem label="JavaScript" icon="seti:javascript">

```js

const serializeResponse() = () => {
// TODO: Implement Request -> JSON/Text
}

const deserializeResponse() = () => {
// TODO: Implement JSON/Text -> Request
}

export default {
async fetch(request, env, ctx) {
async function sha256(message) {
// encode as UTF-8
const msgBuffer = await new TextEncoder().encode(message);
// hash the message
const hashBuffer = await crypto.subtle.digest("SHA-256", msgBuffer);
// convert bytes to hex string
return [...new Uint8Array(hashBuffer)]
.map((b) => b.toString(16).padStart(2, "0"))
.join("");
}
try {
if (request.method.toUpperCase() === "POST") {
const body = await request.clone().text();
// Hash the request body to use it as a part of the cache key
const hash = await sha256(body);
const cacheUrl = new URL(request.url);
// Store the URL in cache by prepending the body's hash
cacheUrl.pathname = "/posts" + cacheUrl.pathname + hash;
// Convert to a GET to be able to cache
const cacheKey = new Request(cacheUrl.toString(), {
headers: request.headers,
method: "GET",
});

// Find the cache key in KV
let response = deserializeResponse(await env.KV.get());
// Otherwise, fetch response to POST request from origin
if (!response) {
response = await fetch(request);
// TODO: Add expiry
ctx.waitUntil(env.KV.put(cacheKey, serializeResponse()));
}
return response;
}
return fetch(request);
} catch (e) {
return new Response("Error thrown " + e.message);
}
},
};
```

</TabItem> <TabItem label="TypeScript" icon="seti:typescript">

```ts
interface Env {}
export default {
async fetch(request, env, ctx): Promise<Response> {
async function sha256(message) {
// encode as UTF-8
const msgBuffer = await new TextEncoder().encode(message);
// hash the message
const hashBuffer = await crypto.subtle.digest("SHA-256", msgBuffer);
// convert bytes to hex string
return [...new Uint8Array(hashBuffer)]
.map((b) => b.toString(16).padStart(2, "0"))
.join("");
}
try {
if (request.method.toUpperCase() === "POST") {
const body = await request.clone().text();
// Hash the request body to use it as a part of the cache key
const hash = await sha256(body);
const cacheUrl = new URL(request.url);
// Store the URL in cache by prepending the body's hash
cacheUrl.pathname = "/posts" + cacheUrl.pathname + hash;
// Convert to a GET to be able to cache
const cacheKey = new Request(cacheUrl.toString(), {
headers: request.headers,
method: "GET",
});

const cache = caches.default;
// Find the cache key in the cache
let response = await cache.match(cacheKey);
// Otherwise, fetch response to POST request from origin
if (!response) {
response = await fetch(request);
ctx.waitUntil(cache.put(cacheKey, response.clone()));
}
return response;
}
return fetch(request);
} catch (e) {
return new Response("Error thrown " + e.message);
}
},
} satisfies ExportedHandler<Env>;
```

</TabItem></Tabs>
6 changes: 3 additions & 3 deletions src/content/docs/workers/reference/how-the-cache-works.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ Conceptually, there are two ways to interact with Cloudflare’s Cache using a W

* Caching responses generated by the Worker itself through `cache.put()`.

:::caution[Tiered caching]
:::caution[Tiered caching & Cache Reserve]


The Cache API is not compatible with tiered caching. To take advantage of tiered caching, use the [fetch API](/workers/runtime-apis/fetch/).
The Cache API is not compatible with tiered caching and Cache Reserve. To take advantage of tiered caching, use the [fetch API](/workers/runtime-apis/fetch/).


:::
Expand Down Expand Up @@ -118,7 +118,7 @@ This [template](/workers/examples/cache-api/) shows ways to use the cache API. F

:::caution[Tiered caching and the Cache API]

Cache API within Workers does not support tiered caching. Tiered Cache concentrates connections to origin servers so they come from a small number of data centers rather than the full set of network locations. Cache API is local to a data center, this means that `cache.match` does a lookup, `cache.put` stores a response, and `cache.delete` removes a stored response only in the cache of the data center that the Worker handling the request is in. Because these methods apply only to local cache, they will not work with tiered cache.
Cache API within Workers does not support tiered caching or use with Cache Reserve. Consider using [Workers KV](/kv/) instead. Tiered Cache concentrates connections to origin servers so they come from a small number of data centers rather than the full set of network locations. Cache API is local to a data center, this means that `cache.match` does a lookup, `cache.put` stores a response, and `cache.delete` removes a stored response only in the cache of the data center that the Worker handling the request is in. Because these methods apply only to local cache, they will not work with tiered cache.
:::

## Related resources
Expand Down