Cloudflare Workers + KV で301リダイレクトをサーバレスに実装してみる

2021.12.10

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

どうも、ベルリンオフィスの小西です。

WEBサイトの特定のURLへのアクセスに対してリダイレクトを行いたい場合、色々方法がありますが、アプリ側の実装と切り離したリダイレクト処理が欲しい、かつリダイレクト元/先のURLが今後も更新されうる場合、Workers + KVを使ってサーバレスに実装するのが便利です。

Cloudflare KVとは

Cloudflareが提供する、サーバーレスの Key-Value ストレージです。

世界中のCloudflareのネットワークで低レイテンシーに実行・更新が可能なKey-Value Storeへ、Workersから簡単にアクセスが可能になります。

ダッシュボード上で作成・追加・削除が行えますし、APIによる詳細な操作も可能です。

やろうとしていること

今回はこのKVにリダイレクト元、リダイレクト先のURLのリストを追加し、そのリストを元にWorkersでリダイレクト処理を行いたいと思います。

手順1: KVへリダイレクトリストの登録

まずはKVの namespace を作成します。namespaceはKey-Valueを登録するデータベースの単位です。

namespaceの登録

Cloudflareダッシュボード > [Workers] > [KV] に進み、[Namespace Name] に redirect-list-sample で追加します。

サンプルのリダイレクト対応表を登録

  • Keyとしてリダイレクト元のパス(例: /redirect-from/
  • Valueとしてリダイレクト先のURL(例: https://konishi.classmethod.cf/redirect-to/

を入力します。

件数が増えてくるとダッシュボード上での作業は難しくなってくる(特に、値の検索ができない)ため、APIで作業をしましょう。 Keyの一覧取得、Key指定によるValueの取得、新規作成、削除が柔軟に行えます。 https://developers.cloudflare.com/workers/runtime-apis/kv

手順2: Workersコードの実装

次にWorkersです。

Cloudflareダッシュボード > [Workers] > [Create a Service]から新規追加します。

[Service Name ]として redirect-kv-sample と入力し、[Create service]で作成します。

作成が完了したら、[Quick Edit]をクリックします。

コードエディターが開きます。

コード部分を下記コードに置き換えます。

async function handleRequest(request) {
  const url = new URL(request.url)
  const { pathname } = url

  const redirect_target = await REDIRECT_LIST_SAMPLE.get(pathname);

  if (redirect_target) {
	  return new Response(null, {
		  'status': 301,
		  'headers': {
		  	'Location': redirect_target,
		  }
	  });
  }else{
    return fetch(request)
  }
}

addEventListener("fetch", async event => {
  event.respondWith(handleRequest(event.request))
})

上記WorkersはリクエストをCloudflareで受けてから(オリジンにフェッチするまでの間で)発火します。

受け取ったリクエストURLのパスを読み取り、それがKVにKeyとして登録されている場合はValueのURLへリダイレクト、そうでなければそのまま元のリクエストを通すという形にしています。

KVのnamespaceからValueを取得するには get メソッドを使います。

NAMESPACE.get(key) で、あるnamespace内の指定したKeyに対応するValueを返します。

もし指定したKeyが見つからなかった場合はnullが返ります。

また、あるkeyが最近読み込まれていた場合、他のエッジで行われたkeyに対する変更が反映されるまでに最大60秒かかることがあります。

ちなみにこの時点でWorkersに対してテストリクエストを投げても500エラーが返ってきます。

コード内の REDIRECT_LIST_SAMPLE は読み込むKVの変数を指しますが、次の手順3でKVとWorkersの紐付けを行う必要があります。

手順3: KVとWorkersの紐付け

Cloudflareダッシュボード > [Workers] > [Settings] > [Variables] > [Add binding]

  • Variable name として REDIRECT_LIST_SAMPLE
  • KV Namespace として 先ほど作成したKV redirect-list-sample

を入力して [Save] を押します。

これで設定は完了ですので、リクエストのテストをしてみます。

手順4: Workersのテスト

Workersのエディターで、実際にリクエストを送ってどの様なレスポンスが返るかテストを行えます。エディターを再度開き、URLの末尾に /redirect-to/ をつけてGETリクエストを投げてみます。

301 Moved Permanently が返ってきました。

逆にパスを変更して再度GETリクエスを行うと、Workers上にその様なオブジェクトが存在しないため、404レスポンスが返ってくるはずです。


以上、簡単にリダイレクト処理を実装してみました。

2021年12月14日追記: バルクリダイレクト機能がリリースされました!

一括でリダイレクト設定を行うバルクリダイレクト機能が、この記事公開後にリリースされました!

Cloudflare全てのプランに開放された機能で、コードを書かずにダッシュボード上で設定が可能、かつcsvアップロードにも対応しているようですので、シンプルな用途ではこちらのほうが使い勝手が良さそうです。 詳しくは下記をご覧ください。 https://blog.cloudflare.com/maximum-redirects-minimum-effort-announcing-bulk-redirects/

KVの料金プランについて

無料プランのままでは下記をサポートします。

  • 1日あたり10万件の読み込み操作
  • 1日あたり1,000件の書き込み操作、削除操作、列挙操作
  • 最大1GBのストレージ

より大きなキャパシティが必要な場合は従量課金プランがあります。

詳しくは https://www.cloudflare.com/ja-jp/plans/developer-platform/#overview をご覧ください。