以前、Lambda@Edgeを使って、静的サイトのサブディレクトリのアクセスをindex.htmlを参照する設定を書きましたが、 CloudFront Functionsを使えばLambda@Edgeがなくても実現できることを知りましたので共有します。 Lambda@EdgeよりもCloufFront Functionsのほうが良かったところは、なんと言っても関数の反映がめちゃくちゃ早いです!

やりたいこと

  1. CloudFrontのサブディレクトリにアクセスが来たらindex.htmlを参照する
  2. URLに /index.html があれば、/index.html URLにリダイレクトさせる
  3. URLの末尾に「/」があれば取る(remove trailing slash)

CloudFront 関数を作成

CloudFrontにアクセスして、左のメニューから 関数 を選んで、右上にある 関数を作成 ボタンをクリックします。

関数の名前を記入して 関数を作成 ボタンをクリックします。

関数を書き換えます

関数コード > 開発 からJavaScriptコードを下記のコードに書き換えます。

https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/example-function-add-index.html

このサンプルを参考にしてますが、やりたいことの 1「CloudFrontのサブディレクトリにアクセスが来たらindex.htmlを参照する」 は実現できますが、 2「URLに /index.html があれば、/index.html URLにリダイレクトさせる」, 3「URLの末尾に「/」があれば取る(remove trailing slash)」 はできないので少しアレンジを加えてます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
function handler(event) {
    var request = event.request;
    var uri = request.uri;
    var newuri = uri;
    var response = {};
    var params = '';

    // remove path name index.html
    if (uri.includes('index.html')) {
        newuri = uri.replace('index.html', '');

        response = {
          statusCode: 302,
          statusDescription: 'Found',
          headers: { "location": { "value": newuri } }
        }

        return response;
    }
    // remove Trailing Slash
    else if(request.uri !== '/' && uri.endsWith('/')) {
        if(('querystring' in request) && (request.querystring.length > 0)) {
            params = '?'+request.querystring;
        }

        response = {
          statusCode: 302,
          statusDescription: 'Found',
          headers: { "location": { "value": request.uri.slice(0, -1) + params } }
        };

        return response;
    }
    // Check whether the URI is missing a file name.
    else if (uri.endsWith('/')) {
        request.uri += 'index.html';
    }
    // Check whether the URI is missing a file extension.
    else if (!uri.includes('.')) {
        request.uri += '/index.html';
    }

    return request;
}

関数を発行

先に 関数を発行 ボタンをクリックしてからCFディストリビューションを関連付けします。

ポップアップが出ますので、ディストリビューションに関連付けしたいディストリビューションIDを入力、 イベントタイプViewer Request を選択、キャッシュビヘイビアを Default(*) を選択します。

関連付けされたディストリビューションIDが追加されました。

CloudFront Functionsのトップページに戻って、追加した関数のステータスが デプロイ済み になれば反映されます。

以上で設定は終わりです。Lambda@Edgeと比べてシンプルに設定でき、テストのUIもわかりやすく、かつ関数の反映がとても早いです。 Lambda@Edgeを使わないとできなかったことが、CloudFront内だけで完結するのはめっちゃ嬉しいですね!