CloudFrontで参照しているオリジンをLambda@Edgeで変更してみます。
今回はhttp://foo.example.com
でアクセスされたら、CloudFrontがオリジンhttp://example.com/foo/
へリクエストする設定をします。
正直なところあまり需要は無いと思いますがw この設定が生きてくるのは大量に同様の設定をしなければならない時ですね。設定が必要なドメインが2〜3個であればCloudFront側でディストリビューションを必要なだけ作成する方がわかりやすいです。
というわけで先ほどの例の「foo」の部分はどのような文字列が来ても対応可能なよう設定していきます。
基本的な設定の流れ
大きな流れは過去の記事とほぼ同じです。以下を参照ください。IAMの信頼関係などハマりどころも説明しています。 blog.katsubemakito.net
Cloud Front
「代替ドメイン名 (CNAME)」は以下のようにワイルドカードを指定しています。
またCDNにキャッシュは一切しない設定にしておきます。
ACM
AWSの無料証明書(ACM)の方もワイルドカードをドメインに指定しておきます。CloudFrontで利用するのでリージョンを「バージニア北部(us-east-1)」にしておくのをお忘れなく。
Route53
CloudFrontに独自ドメインを付ける際にレコード名の部分はこちらもワイルドカード(*)を指定しています。
これでサブドメインにどのような文字列が指定されたとしても、同じCloudFrontのディストリビューションにたどり着きます。
Lambda@Edge
コード
リクエストされた情報を参照し、それを元にオリジンを書き換えています。ここではオリジンはカスタムドメインが前提となっていますので、S3をHDD的に利用する場合は修正が必要です。
exports.handler = async (event, context, callback) => { const request = event.Records[0].cf.request if ( request.headers['host'] ) { const origin = 'example.com' // 変更先のオリジン const host = request.headers.host[0].value // foo.example.com const path = host.replace('.example.com', '') // foo // オリジンを書き換える request.origin.custom.domainName = origin request.origin.custom.path = '/' + path request.headers['host'] = [ {key:'host', value:origin} ] } return callback(null, request) }
ちなみにrequest.origin.custom.path
で指定するパスはスラッシュで開始する必要があり、もし異なる場合は503エラーが返ってきます。また文字列の末尾にスラッシュを付けることもNGです。……いやその判定できるなら良い感じに動いてくれw
CloudWatch上のエラーは以下のように出力されます。
ERROR Validation error: The Lambda function returned an invalid origin configuration, the value of origin path is invalid, path must start with '/', received path : foo.
デプロイ
CloudFrontのイベントは「オリジンリクエスト」を選択します。