S3+CloudFrontで末尾スラッシュがないディレクトリのindex.htmlを表示する

S3+CloudFrontではURLがディレクトリ名までしかない場合は基本的に404エラーとなる。

例として

https://www.example.com/some_dir/index.html

は表示されるが

https://www.example.com/some_dir/

はエラーとなる。

この問題の回避策はいくつかあるが、中でも一番筋が良いと思われるLambda@Edgeを使ってindex.htmlを表示する方法は以下に詳しい。

ただこの方法だとディレクトリと判定するのに末尾スラッシュを用いているので、以下のように末尾スラッシュがない場合は404エラーとなる。

https://www.example.com/some_dir

直近で末尾スラッシュがない場合もindex.htmlを表示したいというケース(すでに末尾スラッシュ無しで外部からリンクが張られている)があったのでスクリプトを以下のものに入れ替えて対応した。

'use strict';

exports.handler = (event, context, callback) => {
  const request = event.Records[0].cf.request;
  // スラッシュで終わらず拡張子がない場合はディレクトリとみなして末尾にスラッシュを付ける
  if (!request.uri.match(/\/$/)) {
    const names = request.uri.split('/');
    // ディレクトリ名に「.」が含まれるケースについては考慮外とする
    if (!names[names.length - 1].match(/.+\..+/)) {
      request.uri = request.uri.replace(/$/, '/');
    }
  }

  // 末尾がスラッシュで終わっている場合はindex.htmlを付加する
  request.uri = request.uri.replace(/\/$/, '/index.html');
   
  return callback(null, request);
};

末尾スラッシュで終わらない場合も、パスの最後の要素に拡張子がついていないならばディレクトリとみなすと言うアプローチ。
ディレクトリ名に「.」が含まれる場合は考慮しないという割り切り。