S3の静的ウェブサイトホスティングのインデックスドキュメントの挙動を、CloudFrontのデフォルトルートオブジェクトをLambda Edgeを使って処理する方法

はじめに

今のブログはAWS S3の静的サイトで運用していますが、サイトの構築には

  • Docker
  • WordPress
  • WP2Static
  • S3
  • Cloud Front
  • AWS Certificate Manager
  • Lambda Edge

となってます。

2つの機能を確認

S3の静的ウェブサイトホスティングのインデックスドキュメントの挙動

AWS ドキュメントはこちらです。

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/IndexDocumentSupport.html

CloudFrontのデフォルトのルートオブジェクトの挙動

AWS ドキュメントはこちらです。

https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/DefaultRootObject.html

WordPressからの静的サイト生成プラグイン「WP2Static」

S3へのアップロードとCloudFrontのInvalidationが欲しかったので下記を使ってます。

アクセスの挙動の整理

こちらのプラグインで静的サイトが生成されます。HTMLのリンク(aタグ)は
https://example.com/hogehoge/
となります。
こちらはwordpress上では当たり前ですが、動きます。

s3だと
https://example.com/hogehoge/
は
https://example.com/hogehoge/index.html
にインデックスドキュメントがあればアクセスされます。

CloudFrontの場合
https://example.com/hogehoge/
にはリダイレクトしません。

Lambda Edgeを使ってリクエストを変換します。

Lambdaでは、/(スラッシュ)で終わってる場合/index.htmlにアクセスするように変換するシンプルなものです。

'use strict';

exports.handler = (event, context, callback) => {
    var request = event.Records[0].cf.request;
    console.log(request.uri)

    if ( request.uri.match(/.*\/$/)) {
        request.uri += "index.html"
    }
    callback(null, request);
}

最後に

ローカル環境でDockerのWordpressを立ち上げ、記事を書き、静的サイトを出力すると、S3にアップしCloudFrontがInvalidationされデプロイが完了します。これで静的サイトが望み通り挙動するようになりました。