CloudFront+S3で公開HPの更新時エラーをLambdaを使って回避する

2024-08-10-02-49-26.webp
目次

はじめに

この問題の根本となる原因はCloudFrontの設定にあります。

ドメインの一番最初にアクセスしたい場所を、Default Root Objectを「index.html」として指定しています。

ブラウザから指定したドメインにアクセスするとこのような形になります。

https:kokota.com

↓ DNSのドメイン解決

https:xxxxx.cloudfront.net/

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

https:xxxxx.cloudfront.net/index.html

このとき、ルートオブジェクトのリンクであればindex.htmlを取得できるのですが、

https:kokota.com/blog

↓ DNSのドメイン解決

https:xxxxx.cloudfront.net/blog

↓ CloudFrontのオブジェクト取得ができない

https:xxxxx.cloudfront.net/blog

というようになりhtmlファイルが取得できないため403エラーを返すようです。

解決方法

Lambda@EdgeかCloudFront Functionを使えばよいです。

CloudFrontへのリクエストをS3バケットに要求する前に、URLを書き換えてサブディレクトリに対してもindex.htmlを付与するのです。 どちらでもいいのですが、使用料金が安いCloudFront Functionを使いましょう。 機能制限はありますが今回の用途であれば十分です。

CloudFunctionの作成

CloudFrontのコンソール画面をひらき、左にあるメニューから関数を選び、新規作成します。

関数名は何でもよいのでこのように書きました。 やっていることは.htmlを末尾に付与するような関数です。

function handler(event) {
    var request = event.request;
    var uri = request.uri;

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

これでとりあえず動くはずです。 細かい条件があれば追加してください。

画像リンクの修正

画像などをリンクしている場合、拡張子の後ろにhtts://XXXX/XXX/xxx.webp.html というようなアドレスに変換されてしまいます。 こんなアドレスは存在しないため当然、Not Foundに行き着きます。 回避するために主な拡張子のときは.htmlをつけないようにしました。これで解決するはずです。

function handler(event) {
    var request = event.request;
    var uri = request.uri;

    // Check whether the URI is missing a file name.
    if (uri.endsWith('/')) {
        request.uri += 'index.html';
    }else if (!hasFileExtension(uri)) {
        request.uri += '.html'; // Append .html if the URI does not have an extension
    }
    return request;
}

function hasFileExtension(uri) {
    // List of common file extensions to check
    var fileExtensions = ['.html', '.webp', '.png', '.jpg', '.jpeg', '.gif', '.svg', '.mp4', '.mov','css','js'];

    // Check if the URI ends with any of the file extensions
    for (var i = 0; i < fileExtensions.length; i++) {
        if (uri.toLowerCase().endsWith(fileExtensions[i])) {
            return true;
        }
    }

    return false;
}

CloudFront のイベントトリガー設定

AWS マネジメントコンソールで CloudFront サービスにアクセスします。 cloudFrontの該当するディストリビューションを選択してビヘイビアタブを開きます。

ビヘイビアを編集を開き、先ほど作成した関数をこのように追加します。

こんな感じ。

まとめ

cloudFrontでRoot以外のアドレスのときに更新したらエラーになっていた問題はこれにて解決です。 Google Adsenceを追加したり、エスパーニャとか行ったときの記事を追加したりいくつかやりたいことはあるのですがひとまずは形になったかと。

気長にやっていこう。

Related Post

> CloudFront+S3で公開HPの更新時エラーをLambdaを使って回避する
Next.jsでブログを作りなおす。まずは、Zennスタイルを適用してみた
> CloudFront+S3で公開HPの更新時エラーをLambdaを使って回避する
Amazonアフェリエイトリンク生成に必要な、ASINコードと商品名をURLから取得する
> CloudFront+S3で公開HPの更新時エラーをLambdaを使って回避する
AmazonアフェリエイトリンクをHugoブログに追加するShortCodeを書いた
> CloudFront+S3で公開HPの更新時エラーをLambdaを使って回避する
ブログの広告収入向上とRSSフィードの導入
> CloudFront+S3で公開HPの更新時エラーをLambdaを使って回避する
GitHub Actions を使った S3 アップロードと CloudFront キャッシュ削除の自動化
> CloudFront+S3で公開HPの更新時エラーをLambdaを使って回避する
再帰的なウェブサイト内リンクチェッカーをPythonで作成する

おすすめの商品

>