【AWS】CloudFront Functions を使ったリダイレクト機能の実装方法

はじめに

CCI インフラチームの YMTsan です。

ウェブサイトの移設等でドメインを変更する機会はよくあると思います。

その際、いきなり旧ドメイン削除せず新ドメインにリダイレクトしたりしますよね? 設定方法はいくつか考えられると思います。

今回は AWS CloudFront Functions を活用したリダイレクト設定方法を紹介します。 以前、違うリダイレクト設定方法も紹介してますので、興味がある方はそちらもご覧ください。

【AWS】ELB リスナールールでリダイレクト設定 - CARTA TECH BLOG
【AWS】CloudFront+S3(静的ウェブサイトホスティング)でリダイレクト設定 - CARTA TECH BLOG


構成イメージ

リダイレクト設定前

リダイレクト設定後


やりたいこと
現ドメイン リダイレクト先ドメイン
AAAAA.example.com BBBBB.example.com
ケースナンバー 場合の説明 挙動の説明 アクセス元 アクセス先
1 パスが「/backup/」まで指定されたアクセスの場合 CloudFrontのオリジンで設定しているS3へそのままアクセス https://AAAAA.example.com/backup/xxxxx https://AAAAA.example.com/backup/xxxxx
2 パスが「/backup/」以外でアクセスの場合 パスがそのまま継承されリダイレクト先ドメインへリダイレクト https://AAAAA.example.com/ https://BBBBB.example.com/

あまりこのような構成は無いと思いますが、以下の構成で作っています。

  • 一部のアクセスのみ元の設定を参照させ(ケース1)
  • それ以外は新ドメインへリダイレクトさせる(ケース2)

完全に移設しきれなかった際、一時的にこのようなケースが考えられるかと思います。




CloudFront 設定

今回は Distribution 作成は省略し、Functions 設定のみ紹介します。

[サービス > CloudFront > 関数]
[関数を作成] を押下
ここでは任意の「名前」「説明」を設定するだけ


[構築] - [開発] に下記コードを設定し [変更を保存] を押下

function handler(event) {
    var request = event.request;
    var headers = request.headers;
    var host = request.headers.host.value;
    var uri = request.uri;
    var newurl = `https://BBBBB.example.com`

    if (uri === '/backup' || uri.startsWith('/backup/')) {
        return request;
    }
    else {
        newurl = `${newurl}${uri}`;
        var response = {
            statusCode: 301,
            statusDescription: 'Moved Permanently',
            headers:
                { "location": { "value": newurl } }
        }
        return response;
    }
}

[発行] の [関数を発行] を押下

[関連付けられているディストリビューション] の [関連付けを追加] を押下

ディストリビューション 対象のディストリビューション
イベントタイプ Viewer request
キャッシュビヘイビア 対象のパスパターン

関連付けを追加すると対象のディストリビューションがデプロイステータスになるのでしばらく待ち、対象のディストリビューションのステータスが有効になったら適用完了。

[サービス > CloudFront > ディストリビューション > 対象のディストリビューション > ビヘイビア > 対象のパスパターン]

「関数の関連付け - オプション」からも設定確認可能

設定はこれで完了です。


疎通確認

設定は完了したので、設定どおりアクセスするか確認してみましょう。
まずはパターン1

$ curl -I https://XXXXXXXXXX.cloudfront.net/backup/index.html
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 16316
Connection: keep-alive
Date: Fri, 12 May 2023 05:15:10 GMT
Last-Modified: Fri, 12 May 2023 04:04:56 GMT
ETag: "c45cfc149a355d371624c356d6972a0f"
x-amz-server-side-encryption: AES256
x-amz-version-id: FJ5r9DKgHfZgU4BJIgYU02c3G8miSJLZ
Accept-Ranges: bytes
Server: AmazonS3
Vary: Accept-Encoding
X-Cache: Miss from cloudfront
Via: 1.1 xxx.cloudfront.net (CloudFront)
X-Amz-Cf-Pop: NRTxxx
X-Amz-Cf-Id: xxx
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000

「/backup/」パスなので想定通りそのまま S3 にアクセスされました。

続いて、パターン2を試してみましょう。

$ curl -I https://XXXXXXXXXX.cloudfront.net
HTTP/1.1 301 Moved Permanently
Server: CloudFront
Date: Fri, 12 May 2023 05:15:21 GMT
Content-Length: 0
Connection: keep-alive
Location: https://BBBBB.example.com/
X-Cache: FunctionGeneratedResponse from cloudfront
Via: 1.1 xxx.cloudfront.net (CloudFront)
X-Amz-Cf-Pop: NRTxxx
X-Amz-Cf-Id: xxx
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000

こちらも想定通り「https://BBBBB.example.com/」にリダイレクトしました。


最後に

CloudFront Functions は JavaScript での設定になります。

JavaScript に慣れてない方でも、今回の内容であればドキュメントを見ればなんとかなると思います。

JavaScript に慣れてる方であれば、ELB や S3 でのリダイレクト設定より柔軟に設定可能なので、かなり使いやすいのではないでしょうか。

ただし、CloudFront Functions の無料枠が「2,000,000 件の CloudFront Function 呼び出し」のようなので、リクエスト数との兼ね合いは考える必要がありそうです。
料金 - Amazon CloudFront | AWS


余談ですが

今回の記事を執筆するにあたり、ChatGPT(社内用) にブログの書き方を教えてもらいました。

便利なものですね。今回はタイトルだけ拝借させていただきました。