CloudFront Functionsでhugoサイトのindex.htmlを補完する
はじめに
静的サイトジェネレータのHugoを使っています。
HugoをCloudFront + S3の構成で動かしアクセスした場合、ルートページ以外にアクセス出来ません。
というのもリンクを押すと以下のようなURLに遷移するからです。(一例です)
https://<domain>/posts/<ページ名>/
はい、index.html
が指定されていません。
そのためアクセスができないというわけです。
今回は
https://<domain>/posts/<ページ名>/index.html
自動的にこのようなURLへ補完してくれるよう、設定を追加したいと思います。
プロビジョニングはTerraformを使用します。
ゴール
index.html
を入力せずにアクセスできたらOKです。
CloudFront Functions未設定
$ curl -I https://<domain>/posts/<ページ名>/
HTTP/2 403
server: AmazonS3
CloudFront Functions設定後
$ curl -I https://<domain>/posts/<ページ名>/
HTTP/2 200
server: AmazonS3
環境
terraform 1.4.6
方針
CloudFront Functions
を使用することでディストリビューションをカスタマイズすることが出来ます。
こいつの機能を使用してindex.html
を補完したいと思います。
CloudFront Functionsとはなに?
コードをCloudFront Distributionに紐付け、それを各エッジロケーションで動作させる実行環境のことです。
cloudfrontを経由するリクエストやレスポンスの操作が可能です。
似たようなサービスであるLambda@Edgeとの違いはこちらに記載があります。
無料枠があるのはいいですね!
あとさばけるリクエスト数もCloudfrontFunctionsに軍配があがるようです。
使用する関数(コード)
function handler(event) {
var request = event.request;
var uri = request.uri;
if (uri.endsWith('/')) {
request.uri += 'index.html';
}
else if (!uri.includes('.')) {
request.uri += '/index.html';
}
return request;
}
まんまドキュメントにあるため、そのまま使用します。
検証
慣れていないため、手動作成とTerraformでの作成を両方試したいと思います。
手動で試す
ここを見ればOKです。
上記の関数を保存後、
- [Publish] タブを選択し、[Publish] ボタンを選択して関数を公開
- cloudfrontディストリビューションに紐付ける前に公開する必要あり
- Associated distributionsから
- 紐づけたいcloudfrontディストリビューション
- Event Typeとして
Viewer Request
- Cache behaviorでデフォルト
- ディストリビューションのステータスが [Deployed] になったら動作確認を行う
のように操作します。
動作確認を行い、URLが補完されればOKです。
環境の削除
Terraformでも試すため、削除します。
- cloudfrontディストリビューションとの関連付けを解除
- ディストリビューションへの適用をしばらく待つ
のようにすればOKです。
Terraformで試す
コードは別ファイルで管理して、file
で参照するようにします。
resource "aws_cloudfront_function" "add-index-function" {
name = "add-index-function"
runtime = "cloudfront-js-1.0"
comment = "Add index.html to the path"
publish = true
code = file("${path.module}/addIndexFunction.js")
}
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";
}
// Check whether the URI is missing a file extension.
else if (!uri.includes(".")) {
request.uri += "/index.html";
}
return request;
}
最後にディストリビューション側で指定する必要があります。
忘れずに行いましょう。
resource "aws_cloudfront_distribution" "hugo_cfront" {
// 略
function_association {
event_type = "viewer-request"
function_arn = aws_cloudfront_function.add-index-function.arn
}
}
あとはplan,applyで設定適用まで待てばOKです。
動作確認
$ curl -I https://<domain>/posts/<ページ名>/
HTTP/2 200
server: AmazonS3
このように、index.html
を指定せずともアクセスできればOKです!
最後に
AWSドキュメントにそのまま答えが書いてあったので楽でした。
ログ設定などは出来ていないため、必要に応じて検討していきます。
参考
Discussion