概要
CloudflareのR2にてカスタムドメインでパブリックなバケットを作成する方法を体験した。
オブジェクトが無いURLにアクセスしたときにCloudflareが用意した404が返るのだが、これを独自の404を返すようにしたので簡単に方法をまとめる。
Cloudflareが用意した404画面の例↓(ロボットの目が動いていてかわいい。)
前提
下記の内容が完了していること。
R2のパブリックアクセス用カスタムドメインはpublic.www.miriwo.work
であり、miriwo.workは下記の記事でDNSをRoute53からCloudflare DNSに移管している。
方法
-
Cloudflareにブラウザからログインし、Workers & Pagesのページに遷移し「作成」をクリック
-
「ワーカーの作成」をクリック
-
「custom-404」という名前をつけて保存をクリック
-
右下の「終了」をクリック
-
「コードを編集する」をクリック
-
エディタが開いたら下記のコードを記載
addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)) }) async function handleRequest(request) { const url = new URL(request.url) const response = await fetch(request) if (response.status === 404) { return new Response('Custom 404', { status: 404, headers: { 'Content-Type': 'text/html' } }) } return response }
-
右上の「デプロイ」をクリック
-
ワーカー名をクリックしてワーカーの詳細画面に戻る
-
ワーカー詳細の「設定」の「トリガー」を開き「ルートを追加」をクリック
-
「ルート」を
public.www.miriwo.work/*
(R2のパブリックカスタムドメイン)のように設定し、「ゾーン」をmiriwo.work
を選択し、「ルートを追加」をクリック -
これで準備は完了、R2のパブリックカスタムドメインのオブジェクトが存在しないパスにブラウザからアクセスして、下記のように返されれば完了
簡単な解説
おそらく図で表したほうがわかりやすいので図解する。
簡略図ではあるが、今までは下記のようにR2に直接アクセスして、オブジェクトがあればそのオブジェクトファイルを、なければCloudflareのデフォルト404を返していた。
これが今回途中にCloudflare Workers & Pagesのワーカーが挟まることで下記のようになった。
スクショ内部のふきだしにも書いてあるとおり、リクエストは素通り、特段何もせず受け取ったリクエストを受け流しているだけ。
一方でレスポンスは異なり、追加したワーカーはR2からのレスポンスを確認し、ステータスが404の場合は独自のレスポンスを返し、それ以外の場合はそのままレスポンスを返している。
今回追加したワーカーをミドルウェア的に使っている感じっぽい。
ちなみに当たり前だが、単純にワーカーを作成して本記事内で紹介したコードをただ記載するだけではR2のパブリック用カスタムドメインに来たリクエストがワーカーを経由するようにはならない。
今回の「方法」の中の「 「ルート」をpublic.www.miriwo.work/*
(R2のパブリックカスタムドメイン)のように設定し、「ゾーン」をmiriwo.work
を選択し、「ルートを追加」をクリック」の手順が「R2のパブリック用カスタムドメインに来たリクエストがワーカーを経由するように」するための設定である。
ようは、「public.www.miriwo.work
にリクエストが来たら追加したワーカーを起動する」という設定が下記である。
ちなみに下記の赤枠内のリンクをクリックしても今回追加したワーカーは動作してしまう。気になるようなら右の三点リーダーから当該のルートを無効にしてもよいだろう。
余談
今回のレスポンスは文字列だけだったが、下記のように記載することで、スタイルも込レスポンスを返すことができる。
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
const url = new URL(request.url)
const response = await fetch(request)
if (response.status === 404) {
const custom404Page = `
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>404 Not Found</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
padding: 50px;
}
h1 {
font-size: 50px;
}
p {
font-size: 20px;
}
a {
color: #007BFF;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<h1>404 Not Found</h1>
<p>お探しのページは見つかりませんでした。</p>
<p><a href="/">トップページに戻る</a></p>
</body>
</html>
`;
return new Response(custom404Page, {
status: 404,
headers: { 'Content-Type': 'text/html' }
})
}
return response
}