概要

AWSのS3CloudFrontで静的ウェブサイトを構築する際、HTMLファイルを拡張子なしのクリーンなURLで公開したい場合には下記のいずれかの手段が有効です。

  • S3に拡張子なしのHTMLファイルを Content-Type: text/html でアップロードする。
  • Lambda@EdgeでリクエストのURLを書き換える。

お手軽なのは前者ですが、HTML以外のファイルも含めて一括アップロードしている場合など、Content-Typeの指定が難しいケースもありそうです。それを踏まえて、本記事では後者のLambda@Edgeでの実現方法をメモします。

前提

  • S3に拡張子ありのHTMLファイルをアップロードしている。
    例: categories.html
  • S3のファイルをCloudFrontを介して公開している。
    例: https://example.com/categories.html
  • 拡張子なしのURLで公開したい。
    例: https://example.com/categories
  • 拡張子ありのURLでリクエストされた場合は拡張子なしのURLにリダイレクトしたい。
    例: https://example.com/categories.html => https://example.com/categories

Lambda関数の作成

では早速、URLを書き換えるためのLambda関数を作成します。この際、リージョンをバージニア北部 (us-east-1) にする必要があります。(2021年3月21日現在)

今回はランタイムにNode.js 12.xを指定します。Lambda@Edgeがサポートするランタイムは日々変動するため、最新の情報に関しては公式ドキュメントをご参照ください。

実行ロールはポリシーテンプレートの「基本的な Lambda@Edge のアクセス権限 (CloudFront トリガーの場合)」をもとに新規作成します。

Lambda関数を作成後、index.jsファイルを下記コードに変更して保存します。

 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
'use strict';

exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;

    if (/\/[^\/]+\.html?$/.test(request.uri)) {
        const response = {
            status: '301',
            headers: {
                location: [
                    {
                        value: request.uri.replace(/(\.html?)+$/, () => {
                            if (!Object.is(request.querystring, '')) {
                                return `?${request.querystring}`;
                            } else {
                                return '';
                            }
                        }),
                    },
                ],
            },
        };
        callback(null, response);
    }

    if (/\/[^\/\.]+$/.test(request.uri)) {
        request.uri += '.html';
    }

    callback(null, request);
};

マネジメントコンソール画面のイメージです。

デプロイ

次に、上記のLambda関数をCloudFrontに適用します。

Lambda関数のアクションから「Lambda@Edge へのデプロイ」をクリックし、デプロイダイアログを表示します。

ダイアログのディストリビューションにCloudFrontのARN、CloudFront イベントにビューアーリクエストを指定し、Lambda@Edge へのデプロイを確認にチェックします。

デプロイボタンを押して完了です。反映まで少々待機し、拡張子なしのURLでアクセスできることを確認します。

まとめ

以上がLambda@Edgeを用いたクリーンなURLの実現方法です。


投稿日

カテゴリ

AWS

タグ