すぐに始めたい場合は、下のボタンを選びます。
GitHub アカウントにリポジトリが作成され、アプリケーションが Cloudflare Workers にデプロイされます。
export default {
async fetch(request) {
const url = new URL(request.url);
// Only use the path for the cache key, removing query strings
// and always store using HTTPS, for example, https://www.example.com/file-uri-here
const someCustomKey = `https://${url.hostname}${url.pathname}`;
let response = await fetch(request, {
cf: {
// Always cache this fetch regardless of content type
// for a max of 5 seconds before revalidating the resource
cacheTtl: 5,
cacheEverything: true,
//Enterprise only feature, see Cache API for other plans
cacheKey: someCustomKey,
},
});
// Reconstruct the Response object to make its headers mutable.
response = new Response(response.body, response);
// Set cache control headers to cache on browser for 25 minutes
response.headers.set("Cache-Control", "max-age=1500");
return response;
},
};export default {
async fetch(request): Promise<Response> {
const url = new URL(request.url);
// Only use the path for the cache key, removing query strings
// and always store using HTTPS, for example, https://www.example.com/file-uri-here
const someCustomKey = `https://${url.hostname}${url.pathname}`;
let response = await fetch(request, {
cf: {
// Always cache this fetch regardless of content type
// for a max of 5 seconds before revalidating the resource
cacheTtl: 5,
cacheEverything: true,
//Enterprise only feature, see Cache API for other plans
cacheKey: someCustomKey,
},
});
// Reconstruct the Response object to make its headers mutable.
response = new Response(response.body, response);
// Set cache control headers to cache on browser for 25 minutes
response.headers.set("Cache-Control", "max-age=1500");
return response;
},
} satisfies ExportedHandler;import { Hono } from 'hono';
type Bindings = {};
const app = new Hono<{ Bindings: Bindings }>();
app.all('*', async (c) => {
const url = new URL(c.req.url);
// Only use the path for the cache key, removing query strings
// and always store using HTTPS, for example, https://www.example.com/file-uri-here
const someCustomKey = `https://${url.hostname}${url.pathname}`;
// Fetch the request with custom cache settings
let response = await fetch(c.req.raw, {
cf: {
// Always cache this fetch regardless of content type
// for a max of 5 seconds before revalidating the resource
cacheTtl: 5,
cacheEverything: true,
// Enterprise only feature, see Cache API for other plans
cacheKey: someCustomKey,
},
});
// Reconstruct the Response object to make its headers mutable
response = new Response(response.body, response);
// Set cache control headers to cache on browser for 25 minutes
response.headers.set("Cache-Control", "max-age=1500");
return response;
});
export default app;from workers import WorkerEntrypoint, Response, fetch
from urllib.parse import urlparse
class Default(WorkerEntrypoint):
async def fetch(self, request):
url = urlparse(request.url)
# Only use the path for the cache key, removing query strings
# and always store using HTTPS, for example, https://www.example.com/file-uri-here
some_custom_key = f"https://{url.hostname}{url.path}"
response = await fetch(
request,
cf={
# Always cache this fetch regardless of content type
# for a max of 5 seconds before revalidating the resource
"cacheTtl": 5,
"cacheEverything": True,
# Enterprise only feature, see Cache API for other plans
"cacheKey": some_custom_key,
},
)
# Reconstruct the Response object to make its headers mutable
new_response = Response(response.body, headers=dict(response.headers))
# Set cache control headers to cache on browser for 25 minutes
new_response.headers["Cache-Control"] = "max-age=1500"
return new_responseuse worker::*;
#[event(fetch)]
async fn fetch(req: Request, _env: Env, _ctx: Context) -> Result<Response> {
let url = req.url()?;
// Only use the path for the cache key, removing query strings
// and always store using HTTPS, for example, https://www.example.com/file-uri-here
let custom_key = format!(
"https://{host}{path}",
host = url.host_str().unwrap(),
path = url.path()
);
let request = Request::new_with_init(
url.as_str(),
&RequestInit {
headers: req.headers().clone(),
method: req.method(),
cf: CfProperties {
// Always cache this fetch regardless of content type
// for a max of 5 seconds before revalidating the resource
cache_ttl: Some(5),
cache_everything: Some(true),
// Enterprise only feature, see Cache API for other plans
cache_key: Some(custom_key),
..CfProperties::default()
},
..RequestInit::default()
},
)?;
let mut response = Fetch::Request(request).send().await?;
// Set cache control headers to cache on browser for 25 minutes
let _ = response.headers_mut().set("Cache-Control", "max-age=1500");
Ok(response)
}// Force Cloudflare to cache an asset
fetch(event.request, { cf: { cacheEverything: true } });キャッシュレベルを Cache Everything にすると、アセットのデフォルトのキャッシュ可否が上書きされます。TTL(有効期間)については、Cloudflare は引き続きオリジンがセットしたヘッダーに従います。
リクエストのキャッシュキーは、キャッシュの目的で 2 つのリクエストが同じかどうかを決めるものです。あるリクエストのキャッシュキーが以前のリクエストと同じなら、Cloudflare は両方に同じキャッシュ済みレスポンスを返せます。キャッシュキーの詳細は、カスタムキャッシュキーの作成 を参照してください。
// Set cache key for this request to "some-string".
fetch(event.request, { cf: { cacheKey: "some-string" } });通常、Cloudflare はリクエストの URL からキャッシュキーを計算します。ただし、キャッシュの目的では、異なる URL を同じものとして扱いたい場合があります。たとえば、ウェブサイトのコンテンツを Amazon S3 と Google Cloud Storage の両方から配信している場合です。同じ内容が両方にあり、Worker でランダムに振り分けられます。ただし、同じ内容を 2 コピーキャッシュしたくはありません。カスタムキャッシュキーを使い、サブリクエスト URL ではなく元のリクエスト URL でキャッシュできます。
export default {
async fetch(request) {
let url = new URL(request.url);
if (Math.random() < 0.5) {
url.hostname = "example.s3.amazonaws.com";
} else {
url.hostname = "example.storage.googleapis.com";
}
let newRequest = new Request(url, request);
return fetch(newRequest, {
cf: { cacheKey: request.url },
});
},
};export default {
async fetch(request): Promise<Response> {
let url = new URL(request.url);
if (Math.random() < 0.5) {
url.hostname = "example.s3.amazonaws.com";
} else {
url.hostname = "example.storage.googleapis.com";
}
let newRequest = new Request(url, request);
return fetch(newRequest, {
cf: { cacheKey: request.url },
});
},
} satisfies ExportedHandler;import { Hono } from 'hono';
type Bindings = {};
const app = new Hono<{ Bindings: Bindings }>();
app.all('*', async (c) => {
const originalUrl = c.req.url;
const url = new URL(originalUrl);
// Randomly select a storage backend
if (Math.random() < 0.5) {
url.hostname = "example.s3.amazonaws.com";
} else {
url.hostname = "example.storage.googleapis.com";
}
// Create a new request to the selected backend
const newRequest = new Request(url, c.req.raw);
// Fetch using the original URL as the cache key
return fetch(newRequest, {
cf: { cacheKey: originalUrl },
});
});
export default app;異なるゾーンのために動く Worker 同士は、互いのキャッシュに影響できません。キャッシュキーを上書きできるのは、自分のゾーン内へのリクエスト(上の例では event.request.url が保存されるキー)か、Cloudflare 上にないホストへのリクエストだけです。別の Cloudflare ゾーン(別の Cloudflare 顧客のものなど)へリクエストする場合、そのゾーンが Cloudflare 内でのコンテンツのキャッシュ方法を完全に制御します。上書きはできません。
オリジンが Vary ヘッダーを返し、Worker のサブリクエストで想定するバリアントをキャッシュしたい場合は cf.vary を使います。この設定は、セットした fetch() リクエストにだけ適用されます。
Vary の動作の詳細は Vary を参照してください。リクエスト init オブジェクト全体は cf.vary を参照してください。
export default {
async fetch(request) {
return fetch(request, {
cf: {
vary: {
default: { action: "bypass" },
headers: {
accept: {
action: "normalize",
media_types: ["text/html", "application/json"],
},
"accept-language": {
action: "normalize",
languages: ["en", "fr", "de"],
},
},
},
},
});
},
};export default {
async fetch(request): Promise<Response> {
return fetch(request, {
cf: {
vary: {
default: { action: "bypass" },
headers: {
accept: {
action: "normalize",
media_types: ["text/html", "application/json"],
},
"accept-language": {
action: "normalize",
languages: ["en", "fr", "de"],
},
},
},
},
});
},
} satisfies ExportedHandler;// Force response to be cached for 86400 seconds for 200 status
// codes, 1 second for 404, and do not cache 500 errors.
fetch(request, {
cf: { cacheTtlByStatus: { "200-299": 86400, 404: 1, "500-599": 0 } },
});このオプションは cacheTtl 機能の一種で、レスポンスのステータスコードに基づいて TTL を選び、cacheEverything: true は自動ではセットしません。このリクエストへのレスポンスのステータスコードが一致すると、Cloudflare は指示された時間キャッシュし、オリジンが送ったキャッシュディレクティブを上書きします。cacheTtl 機能の詳細は Request のページ で確認できます。
カスタムキャッシュキーとレスポンスコードに基づく上書きを使うと、オリジンのレスポンスステータスコードとリクエストのファイル種類に応じて TTL をセットする Worker を書けます。
次の例は、ストリーミングメディアアセットのリクエストをキャッシュする方法の一例です。
export default {
async fetch(request) {
// Instantiate new URL to make it mutable
const newRequest = new URL(request.url);
const customCacheKey = `${newRequest.hostname}${newRequest.pathname}`;
const queryCacheKey = `${newRequest.hostname}${newRequest.pathname}${newRequest.search}`;
// Different asset types usually have different caching strategies. Most of the time media content such as audio, videos and images that are not user-generated content would not need to be updated often so a long TTL would be best. However, with HLS streaming, manifest files usually are set with short TTLs so that playback will not be affected, as this files contain the data that the player would need. By setting each caching strategy for categories of asset types in an object within an array, you can solve complex needs when it comes to media content for your application
const cacheAssets = [
{
asset: "video",
key: customCacheKey,
regex:
/(.*\/Video)|(.*\.(m4s|mp4|ts|avi|mpeg|mpg|mkv|bin|webm|vob|flv|m2ts|mts|3gp|m4v|wmv|qt))/,
info: 0,
ok: 31556952,
redirects: 30,
clientError: 10,
serverError: 0,
},
{
asset: "image",
key: queryCacheKey,
regex:
/(.*\/Images)|(.*\.(jpg|jpeg|png|bmp|pict|tif|tiff|webp|gif|heif|exif|bat|bpg|ppm|pgn|pbm|pnm))/,
info: 0,
ok: 3600,
redirects: 30,
clientError: 10,
serverError: 0,
},
{
asset: "frontEnd",
key: queryCacheKey,
regex: /^.*\.(css|js)/,
info: 0,
ok: 3600,
redirects: 30,
clientError: 10,
serverError: 0,
},
{
asset: "audio",
key: customCacheKey,
regex:
/(.*\/Audio)|(.*\.(flac|aac|mp3|alac|aiff|wav|ogg|aiff|opus|ape|wma|3gp))/,
info: 0,
ok: 31556952,
redirects: 30,
clientError: 10,
serverError: 0,
},
{
asset: "directPlay",
key: customCacheKey,
regex: /.*(\/Download)/,
info: 0,
ok: 31556952,
redirects: 30,
clientError: 10,
serverError: 0,
},
{
asset: "manifest",
key: customCacheKey,
regex: /^.*\.(m3u8|mpd)/,
info: 0,
ok: 3,
redirects: 2,
clientError: 1,
serverError: 0,
},
];
const { asset, regex, ...cache } =
cacheAssets.find(({ regex }) => newRequest.pathname.match(regex)) ?? {};
const newResponse = await fetch(request, {
cf: {
cacheKey: cache.key,
polish: false,
cacheEverything: true,
cacheTtlByStatus: {
"100-199": cache.info,
"200-299": cache.ok,
"300-399": cache.redirects,
"400-499": cache.clientError,
"500-599": cache.serverError,
},
cacheTags: ["static"],
},
});
const response = new Response(newResponse.body, newResponse);
// For debugging purposes
response.headers.set("debug", JSON.stringify(cache));
return response;
},
};addEventListener("fetch", (event) => {
return event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
// Instantiate new URL to make it mutable
const newRequest = new URL(request.url);
// Set `const` to be used in the array later on
const customCacheKey = `${newRequest.hostname}${newRequest.pathname}`;
const queryCacheKey = `${newRequest.hostname}${newRequest.pathname}${newRequest.search}`;
// Set all variables needed to manipulate Cloudflare's cache using the fetch API in the `cf` object. You will be passing these variables in the objects down below.
const cacheAssets = [
{
asset: "video",
key: customCacheKey,
regex:
/(.*\/Video)|(.*\.(m4s|mp4|ts|avi|mpeg|mpg|mkv|bin|webm|vob|flv|m2ts|mts|3gp|m4v|wmv|qt))/,
info: 0,
ok: 31556952,
redirects: 30,
clientError: 10,
serverError: 0,
},
{
asset: "image",
key: queryCacheKey,
regex:
/(.*\/Images)|(.*\.(jpg|jpeg|png|bmp|pict|tif|tiff|webp|gif|heif|exif|bat|bpg|ppm|pgn|pbm|pnm))/,
info: 0,
ok: 3600,
redirects: 30,
clientError: 10,
serverError: 0,
},
{
asset: "frontEnd",
key: queryCacheKey,
regex: /^.*\.(css|js)/,
info: 0,
ok: 3600,
redirects: 30,
clientError: 10,
serverError: 0,
},
{
asset: "audio",
key: customCacheKey,
regex:
/(.*\/Audio)|(.*\.(flac|aac|mp3|alac|aiff|wav|ogg|aiff|opus|ape|wma|3gp))/,
info: 0,
ok: 31556952,
redirects: 30,
clientError: 10,
serverError: 0,
},
{
asset: "directPlay",
key: customCacheKey,
regex: /.*(\/Download)/,
info: 0,
ok: 31556952,
redirects: 30,
clientError: 10,
serverError: 0,
},
{
asset: "manifest",
key: customCacheKey,
regex: /^.*\.(m3u8|mpd)/,
info: 0,
ok: 3,
redirects: 2,
clientError: 1,
serverError: 0,
},
];
// the `.find` method is used to find elements in an array (`cacheAssets`), in this case, `regex`, which can passed to the .`match` method to match on file extensions to cache, since they are many media types in the array. If you want to add more types, update the array. Refer to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find for more information.
const { asset, regex, ...cache } =
cacheAssets.find(({ regex }) => newRequest.pathname.match(regex)) ?? {};
const newResponse = await fetch(request, {
cf: {
cacheKey: cache.key,
polish: false,
cacheEverything: true,
cacheTtlByStatus: {
"100-199": cache.info,
"200-299": cache.ok,
"300-399": cache.redirects,
"400-499": cache.clientError,
"500-599": cache.serverError,
},
cacheTags: ["static"],
},
});
const response = new Response(newResponse.body, newResponse);
// For debugging purposes
response.headers.set("debug", JSON.stringify(cache));
return response;
}fetch のオプションで cache モードをセットできます。
現在、Workers がキャッシュ制御に対応しているのは no-store と no-cache モードだけです。
no-store を指定すると、オリジンへの経路でキャッシュをバイパスし、リクエストはキャッシュされません。
no-cache を指定すると、キャッシュは現在キャッシュしているレスポンスをオリジンに対して再検証します。
fetch(request, { cache: 'no-store'});
fetch(request, { cache: 'no-cache'});