docusaurus + CloudFront + S3で直リンクOKにする
docusaurusをCloudFront + S3
でホスティングしたとき、直リンでアクセスできるパスが制限されています。
- NG:
https://example.com/foo
- OK:
https://example.com/foo/index.html
- OK:
https://example.com
- ※デフォルトルートを設定したときのみ OK
https://example.com/foo
を参照したい場合は、まずhttps://example.com
にアクセスしてページ内リンクからhttps://example.com/foo
へ移動しないといけません。
これが地味に使いにくい。URL をチームに共有するとき、アドレスバーをコピペするとhttps://example.com/foo
となるので、アクセスするときに手間がかかります。
Lambda@edge
を使って解決します。
手順¶
- Lambda を作成する
- Lambda のバージョンを作成する
- IAM ロール周りを修正する
- CloudFront をトリガーに設定する
1. Lambdaを作成する¶
us-east-1
リージョンに Lambda を作成します。
ランタイムはNode.js 16.x
を選択しました。
ロールは基本的な Lambda アクセス権限で新しいロールを作成
で作成しました。
export const handler = async (event, context, callback) => {
const request = event.Records[0].cf.request;
const olduri = request.uri;
if (isExistExtension(oldurl)) {
// 拡張子があれば、そのまま返す
return callback(null, request);
}
// 末尾にindex.htmlを付与する
// - https://example.com/foo → https://example.com/foo/index.html
// - https://example.com/foo/ → https://example.com/foo/index.html
const newuri = (olduri.endsWith("/") ? olduri : olduri + "/") + "index.html";
request.uri = newuri;
return callback(null, request);
};
/**
* 拡張子存在チェック
*/
function isExistExtension(url) {
const ext = url.split(".").pop().trim();
// 拡張子がない場合は、ext = url となる
return ext !== url;
}
2. Lambdaのバージョンを作成する¶
右上にある「アクション」プルダウンや「バージョン」タブから「新しいバージョンを発行」をする。 入力項目は適当でよいです。
3. IAM ロール周りを修正する¶
1. Lambdaを作成する
で作成したロールに対して色々やります。
ポリシーの追加¶
新たに以下のポリシーを追加します。[lambdaの関数名]
には1. Lambda を作成する
作成時の関数名を入力します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:CreateServiceLinkedRole",
"cloudfront:UpdateDistribution"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": ["lambda:GetFunction", "lambda:EnableReplication"],
"Resource": "arn:aws:lambda:us-east-1:371422377734:function:[lambdaの関数名]:*"
}
]
}
信頼関係の変更¶
「信頼関係」タブがあるので、edgelambda.amazonaws.com
を追加します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": ["lambda.amazonaws.com", "edgelambda.amazonaws.com"]
},
"Action": "sts:AssumeRole"
}
]
}
4. CloudFront をトリガーに設定する¶
右上にある「アクション」プルダウンから「Lambda@Edge」へのデプロイを選択します。
item | value |
---|---|
Distribution | 対象の CloudFront |
Cache behavior | * |
CloudFront event | Origin request |
Confirm deploy to Lambda@Edge | On |
これでデプロイすれば完了です。