
- はじめに
- 従来の構成:S3の静的サイト
- API GatewayとLambdaの仕組み
- Lambdaの設定とコード
- CloudFrontの設定
- API Gatewayの設定(CORSとMapping Template込み)📄
- 結果
- まとめ
- 参照資料
はじめに
ゼネットシステム事業部の方です。
AWSでWebサイトを公開する場合、最もシンプルな方法はAmazon S3に静的サイトをホスティングすることです。
しかし、S3は静的コンテンツのみを提供するため、ユーザーごとに動的に内容を変えたい場合は工夫が必要です。
そこで今回は、API Gateway + Lambda を利用して動的にHTMLを生成する方法を紹介します。
実際の業務では、この仕組みを応用して ユーザーごとに異なるQuickSightダッシュボードを表示する仕組みを構築しました。
従来の構成:S3の静的サイト
S3の静的サイトホスティングは簡単ですが、動的処理はできません。
例えば、以下のような課題があります。
-
HTMLファイルは事前に用意する必要がある
-
ユーザーの入力に応じた動的コンテンツを返せない
-
外部データベースやAPIとの連携ができない

これを解決するために、API GatewayとLambdaを組み合わせるとサーバーレスで動的なWebサイトが実現できます。
API GatewayとLambdaの仕組み
今回の構成では、S3 だけでは実現できない「ユーザーごとに異なるページや回答表示」を API Gateway と Lambda で補っています。
-
S3:基本のHTMLやCSS、JavaScriptを配信
-
API Gateway:ブラウザからのリクエストを受け付ける
-
Lambda:リクエスト内容に応じて動的にHTMLを生成
-
CloudFront:全体を統合するフロント。キャッシュ・セキュリティ・HTTPS対応を提供
この構成により、以下の役割分担が可能です:
-
静的要素(CSS/JS/画像)は S3 + CloudFront で高速配信
-
動的要素(ユーザーごとに異なるダッシュボードHTMLなど)は API Gateway + Lambda で柔軟に生成
といった役割分担が可能になります。

特に、動的HTMLでも一部要素(CSS/JS)はキャッシュ可能なので、パフォーマンス改善に効果的です。
Lambdaの設定とコード
LambdaはHTMLを生成して返す役割を担います。
今回はシンプルにPythonでHTMLを返すサンプルを紹介します。
from datetime import datetime
def lambda_handler(event, context):
body = event['body']
dob_str = body.get('dob')
try:
# 入力された生年月日を取得
dob = datetime.strptime(dob_str, "%Y-%m-%d")
# 星座と干支を判別
western = get_western_zodiac(dob.month, dob.day)
chinese = get_chinese_zodiac(dob.year)
# 回答HTMLを作成
html = (
f'<h3>あなたの星座:{western}</h3>'
f'<h3>あなたの干支:{chinese}</h3>'
)
return html
except Exception as e:
return {
'statusCode': 400,
'body': f"<p>エラーが発生しました:{str(e)}</p>"
}
# 星座判別関数
def get_western_zodiac(month, day):
if (month == 1 and day >= 20) or (month == 2 and day <= 18): return "みずがめ座"
if (month == 2 and day >= 19) or (month == 3 and day <= 20): return "うお座"
if (month == 3 and day >= 21) or (month == 4 and day <= 19): return "おひつじ座"
if (month == 4 and day >= 20) or (month == 5 and day <= 20): return "おうし座"
if (month == 5 and day >= 21) or (month == 6 and day <= 20): return "ふたご座"
if (month == 6 and day >= 21) or (month == 7 and day <= 22): return "かに座"
if (month == 7 and day >= 23) or (month == 8 and day <= 22): return "しし座"
if (month == 8 and day >= 23) or (month == 9 and day <= 22): return "おとめ座"
if (month == 9 and day >= 23) or (month == 10 and day <= 22): return "てんびん座"
if (month == 10 and day >= 23) or (month == 11 and day <= 21): return "さそり座"
if (month == 11 and day >= 22) or (month == 12 and day <= 21): return "いて座"
return "やぎ座"
# 干支判別関数
def get_chinese_zodiac(year):
animals = [
"子(ねずみ)", "丑(うし)", "寅(とら)", "卯(うさぎ)", "辰(たつ)", "巳(へび)",
"午(うま)", "未(ひつじ)", "申(さる)", "酉(とり)", "戌(いぬ)", "亥(いのしし)"
]
base_year = 1900
index = (year - base_year) % 12
return animals[index]
CloudFrontの設定
CloudFrontをAPI Gatewayの前段に置くことで、以下のメリットが得られます。
-
世界中のエッジロケーションからの高速配信
-
WAF連携によるセキュリティ強化
-
キャッシュによるレスポンス高速化
ディストリビューション作成
-
CloudFrontの管理コンソールにアクセス
-
[ディストリビューションを作成] をクリック
-
配信プロトコルは HTTPS を選択
オリジン作成
-
オリジンに指定するリソースを選択
-
例1: S3バケット を指定(静的ファイル配信用)
-
例2: API Gatewayのエンドポイント を指定(動的API呼び出し用)
-
- 保存してディストリビューションを作成
API Gatewayの設定(CORSとMapping Template込み)📄
1. リソースとメソッドの作成
まず、API Gatewayで新規REST APIを作成し、対象のリソースに POSTメソッド を追加します。

2. CORS設定
ブラウザからAPIを呼び出す場合、CORS対応 が必須です。
API Gatewayの「CORSの有効化」 から設定します。
以下のヘッダーを有効にすることで、ブラウザから安全に呼び出せるようになります。
-
Access-Control-Allow-Origin: * -
Access-Control-Allow-Methods: POST, OPTIONS -
Access-Control-Allow-Headers: Content-Type

もし特定の環境だけに限定したい場合は、次のように CloudFrontのURL を指定します。
-
Access-Control-Allow-Origin: https://xxxxxxx.cloudfront.net
3. マッピングテンプレート設定
(1) 統合リクエストのマッピングテンプレート
クライアントから送られたクエリパラメータを、Lambdaに渡す際にJSONへ変換します。
Content-Type: application/json
結果
実際にブラウザからサイトにアクセスし、APIゲートウェイを呼び出すボタンを押下すると、Lambdaが生成したHTMLが返り、動的に表示されました。


まとめ
今回の仕組のメリット:
-
動的なHTML生成が可能(ユーザーごとに異なるページを提供できる)
-
完全サーバーレス構成で運用コスト削減
-
CloudFront連携によりグローバルに高速配信
-
セキュアな認証制御を組み込みやすい(CORSやMapping Templateと連携可能)
S3の静的サイトと違い、サーバーを立てずに動的コンテンツを実現できるのは大きなメリットです。
今後は、この仕組みに DynamoDB や外部APIを組み合わせることで、よりリッチなWebアプリケーションへの応用も可能です。
参照資料






