※ 当ページには【広告/PR】を含む場合があります。
2021/03/11
サブドメイン付きURLで静的なWebサイトをAWS S3/CloudFront(とCloudFront Functions)/Route53で作成する
[AWS x SEO対応] S3 & CloudFrontで静的ホスティングしたウェブサイトのドメイン移管 ~ 301リダイレクトを仕込む
[Lambda@Edge x ウェブサイト運用] AWS S3で静的ホスティングしたウェブサイトをレスポンス400~500番台の時にエラーページへ誘導する
AWS S3に置いた静的なリソースをAWS CloudFrontからコンテンツ配信するタイプのウェブサイトでは、そのクライアントへ送り出されるhtmlファイルの名前まで指定してアクセスしてあげないと、CloudFrontは何をリクエストされたのか分からずに、以下のようなページを返すようになります。ということで、今回はAWS Lambda@Edgeを利用して、AWS S3の静的ホスティングサイトの構築に則した、ユーザーからのリクエストURLに自動で/index.html
を処理して返すような手法についてメモしておきます。なお、前回の以下の記事では今回の内容を説明しなかったのですが、S3による静的ウェブサイトホスティングでは必須の項目では無かったので、別の技術記事としてそれぞれ切り出した次第です。サブドメイン付きURLで静的なWebサイトをAWS S3/CloudFront(とCloudFront Functions)/Route53で作成するAWS S3/Clounflont/Route53を利用したクラウドネイティブな静的ウェブサイトのホスティングを、サブドメイン付きのURLで構築していきます。
【AWS独習術】AWSをじっくり独学したい人のためのオススメ書籍&教材特集
図解即戦力 Amazon Web Servicesのしくみと技術がこれ1冊でしっかりわかる教科書 「/index.html」を補った/補わなかった場合の比較
まずは改めて、本件の問題点を確認してみます。前回の記事のようにAWS S3/Clounflont/Route53
を組み合わせてS3バケット内のオブジェクトを配信することで、まるでWebサーバーのように扱えるのがS3静的ウェブサイトの魅力でもあります。そのテクニックの核となっているのがCloudFrontなのですが、あくまでもコンテンツ配信ネットワーク(CDN)サービスですので、リクエストされたファイル名の指定が無ければ、どれをクライアントに送り返して良いものは自動で判別なんてしてくれるわけはありません。結果的に、CloudFront単体では供給すべきファイルの名前までは解決できずに、以下のようにファイル名に指定がない場合にはレスポンスエラーが発生してしまいます。もちろん/index.html
をサフィックスとして常に省略しないURLでユーザーにアクセスさせるようにしたら問題はないのですが、サイトへのアクセスしやすさを考えると、/index.html
はやはり冗長です。/index.html
があってもなくても、柔軟にCloudFrontからファイルを供給できるようにするためのひと手間として、今回はLambda@Edgeを使った方法を以下で紹介していきます。
【AWS独習術】AWSをじっくり独学したい人のためのオススメ書籍&教材特集
図解即戦力 Amazon Web Servicesのしくみと技術がこれ1冊でしっかりわかる教科書 Lambda@Edgeの使い方
以下ではステップごとにLambda@Edgeを仕込む手順を説明していきます。Lambda関数の作成
まずはAWS Lambdaコンソールダッシュボードから通常のLambdaで関数を新規作成します。関数名やランタイムは適当に決めてもらうとして、ここではNodejs 12.x
を指定します。実行ロールの割当では既存のロールを使用する
からもっとも一般的なlambda_basic_execution
を追加します。なお、lambda_basic_execution
の内容はLambda@Edgeを利用するための必要最低限のエンティティセットですが、カスタムロールを利用する場合には、以下のような2つのエンティティがロールに付与されているか確認しましょう。関数が作成されたらその関数の中身を設定していきます。以下のコードをindex.jsに編集します。ソースコードは[コード]
タブの左側のツリービューからindex.js
をクリックして、そのまま先ほどの貼り付けます。コードを貼り付けたら、[Deploy]
ボタンを押して変更を適用します。テスト
実際にEdgeへ本番関数を起動させる前に、この関数のテストをしてみましょう。テストを作成するにはまず[テスト]
タブから新しいイベント
で、テンプレートからclouldfront-respose-generation
などを選択します。選択するテンプレートは今回テストするコードに合わせてRecords.cf.request.url
があるものであればなんでもOKです。せっかくですので、以下のようにリクエストの内容も/hoge
にアクセスするようにしてみます。なお、uriプロパティは相対的アクセスURIを取ります。なので例えばhttps://hoge-piyo.com/hoge
へクライアントからアクセスがあった場合には、uriプロパティは/hoge
だけが抽出されます。このテストを適当な名前を付けて[変更を保存]
ボタンで保存し、[呼び出し]
ボタンでうまくレスポンスが返ってきていること確認します。期待通りに/hoge/index.html
というURIのリクエストになっていることが分かります。ログ出力も観てみると、コード内のconsole.logから変換前後のURI出力が確認できます。なお、一度作成したテストはコードタブ側の[Test]
ボタンで以降は便利に呼び出して使えるので、テストタブと画面を切り替えることなく使えるようになります。関数のEdgeへのバージョニング
ではlambda@Edgeにデプロイを行います。コンソール右上の[アクション] > [Lambda@Edgeへのデプロイ]
を押してみます。初回に作成したLambda関数のデプロイではトリガーとなるCloudFrontディストリビューションの設定が聞かれてきます。ウェブサイトのコンテンツを配信しているCloudFrontのディストリビューションを結びつけましょう。ターゲットしたいCloudFrontのディストリビューションを選択し、他の設定はデフォルト値のままにしておいて、Lambda@Edgeへのデプロイを確認
のチェックボックスを入れ、良ければ[デプロイ]
ボタンを押します。その後CloudFrontのダッシュボードで確認するとターゲットのディストリビューションの項目に変更がIn Progress
になっているので、設定が反映されるまで暫く待ちます。Lambda@Edgeによって、リクエストの内容を柔軟に変化させることで、リクエストしたURIに/index.html
が無ければ自動的に補ってくれるようになりました。Lambda@Edgeのバージョンアップについて
おまけで、もしLambda関数のindex.jsのコードの中身を修正した内容で、現在可動しているバージョンを上書きする場合にも触れておきます。既にLambda関数の何らかのバージョンがデプロイされて稼働状態でも、再び[アクション] > [Lambda@Edgeへのデプロイ]
してみると、この関数で既存のCloudFrontトリガーを使用
というオプションが増えています。これで以前のバージョンでトリガーとして利用していたものが引き継ぐことができるようになります。この修正した関数はバージョンで管理されており、新しい関数をデプロイすると、バージョンが上書きされ、最新のバージョンが$LATEST
として即時稼働状態に移行します。また古くなったバージョンのものは機能を休止して自動でアーカイブされます。各バージョンの情報は以下の図のようにバージョン
タブから確認することが可能です。
【AWS独習術】AWSをじっくり独学したい人のためのオススメ書籍&教材特集
図解即戦力 Amazon Web Servicesのしくみと技術がこれ1冊でしっかりわかる教科書 まとめ
今回はLambda@Edgeを使ったクライアント側からのリクエストURIを適切に処理して、AWS CloudFront側から特定の名前を付けたファイルを引き出すためのテクニックに関して詳しく解説していきました。Lambda関数の処理時間も数十ミリ秒程度なので、仮にアクセスが増加しても利用料としてはほぼ無いような金額ですので、コストパフォマンスの意味でもLambda@EdgeとCloudFrontを活用するのは優れたやり方だと言えます。