API Gatewayのモック統合でHTMLページを表示
Posted On 2024-12-28
API GatewayだけでHTMLページをホストする方法を、Terraformのモック統合で実践する手順を紹介しています。 文字化けを防ぐために、Content-TypeヘッダーやHTML内のcharset指定を正しく設定するポイントも解説しています。
目次
はじめに
- API Gatewayのモック統合を以前試したのだが、これの延長線上でAPI GatewayからHTMLページをホストできることを知ったので試してみた
- DVAを勉強しているときに出てきて面白いなと思ったものなのだが、以前のコードを少し改造したらできた
- Lambdaは不要で、API Gatewayだけでできる
できたもの
API GatewayだけでHTMLページをホストできている。不思議
文字コードの注意点
普通にやるとHTMLが文字化けしてしまうので、以下の点に注意する。
- Content-Type ヘッダーの不足または誤設定:
- ブラウザが受信したコンテンツの文字エンコーディングを正しく認識できていない可能性があります。
Content-Type
ヘッダーに適切なcharset
を指定していないため、デフォルトのエンコーディング(通常は ISO-8859-1)で解釈され、文字化けが発生している可能性があります。
- HTML コンテンツ自体のエンコーディング:
- Terraform ファイル内での HTML コンテンツが適切にエンコードされていない場合、文字化けが発生する可能性があります。
解決策
1. Content-Type ヘッダーに charset
を追加
aws_api_gateway_integration_response
リソースの response_parameters
において、Content-Type
ヘッダーに charset=utf-8
を追加しました。これにより、ブラウザは受信したコンテンツをUTF-8として解釈します。
response_parameters = {
"method.response.header.Content-Type" = "'text/html; charset=utf-8'"
}
2. HTML ドキュメントに <meta charset="UTF-8">
を追加
HTML ドキュメントの <head>
セクションに <meta charset="UTF-8">
を追加することで、ブラウザに対して文書の文字エンコーディングを明示的に指定しています。
<meta charset="UTF-8">
3. response_models
の設定
aws_api_gateway_method_response
リソースにおいて、response_models
を "text/html" = "Empty"
と設定しました。これにより、API Gateway は特定のコンテンツタイプに対してモデルを適用しないようになります。
response_models = {
"text/html" = "Empty"
}
全体のTerraformのコード
locals {
# ランディングページ用の設定
landing_page = {
path_part = "landing"
http_method = "GET"
response_template = <<EOF
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ランディングページ</title>
</head>
<body>
<h1>ようこそ!</h1>
<p>これはAPI Gatewayのモック統合によるランディングページです。</p>
</body>
</html>
EOF
}
}
# API Gatewayの作成
resource "aws_api_gateway_rest_api" "landing_api" {
name = "LandingPageAPI_Mock"
description = "Mock API for landing page"
}
# ランディングページ用リソースの作成
resource "aws_api_gateway_resource" "landing_resource" {
rest_api_id = aws_api_gateway_rest_api.landing_api.id
parent_id = aws_api_gateway_rest_api.landing_api.root_resource_id
path_part = local.landing_page.path_part
}
# ランディングページ用GETメソッドの作成
resource "aws_api_gateway_method" "landing_method" {
rest_api_id = aws_api_gateway_rest_api.landing_api.id
resource_id = aws_api_gateway_resource.landing_resource.id
http_method = local.landing_page.http_method
authorization = "NONE"
}
# ランディングページ用モック統合の設定
resource "aws_api_gateway_integration" "landing_integration" {
rest_api_id = aws_api_gateway_rest_api.landing_api.id
resource_id = aws_api_gateway_resource.landing_resource.id
http_method = aws_api_gateway_method.landing_method.http_method
type = "MOCK"
integration_http_method = "GET"
request_templates = {
"application/json" = <<EOF
{
"statusCode": 200
}
EOF
}
}
# ランディングページ用メソッドレスポンス (200 OK) の設定
resource "aws_api_gateway_method_response" "landing_method_response_200" {
rest_api_id = aws_api_gateway_rest_api.landing_api.id
resource_id = aws_api_gateway_resource.landing_resource.id
http_method = aws_api_gateway_method.landing_method.http_method
status_code = "200"
response_parameters = {
"method.response.header.Content-Type" = true
}
response_models = {
"text/html" = "Empty"
}
}
# ランディングページ用統合レスポンス (200 OK) の設定
resource "aws_api_gateway_integration_response" "landing_integration_response_200" {
rest_api_id = aws_api_gateway_rest_api.landing_api.id
resource_id = aws_api_gateway_resource.landing_resource.id
http_method = aws_api_gateway_method.landing_method.http_method
status_code = aws_api_gateway_method_response.landing_method_response_200.status_code
response_templates = {
"text/html" = local.landing_page.response_template
}
response_parameters = {
"method.response.header.Content-Type" = "'text/html; charset=utf-8'"
}
}
# デプロイメントの作成
resource "aws_api_gateway_deployment" "landing_deployment" {
depends_on = [
aws_api_gateway_integration.landing_integration,
aws_api_gateway_integration_response.landing_integration_response_200
]
rest_api_id = aws_api_gateway_rest_api.landing_api.id
triggers = {
redeployment_resource = sha1(jsonencode(aws_api_gateway_resource.landing_resource))
redeployment_method = sha1(jsonencode(aws_api_gateway_method.landing_method))
redeployment_integration = sha1(jsonencode(aws_api_gateway_integration.landing_integration))
redeployment_method_response = sha1(jsonencode(aws_api_gateway_method_response.landing_method_response_200))
redeployment_integration_response = sha1(jsonencode(aws_api_gateway_integration_response.landing_integration_response_200))
}
lifecycle {
create_before_destroy = true
}
}
# ステージの作成
resource "aws_api_gateway_stage" "landing_stage" {
deployment_id = aws_api_gateway_deployment.landing_deployment.id
rest_api_id = aws_api_gateway_rest_api.landing_api.id
stage_name = "dev"
}
# エンドポイントURLの出力
output "landing_page_endpoint" {
value = "${aws_api_gateway_stage.landing_stage.invoke_url}/${local.landing_page.path_part}"
}
Shikoan's ML Blogの中の人が運営しているサークル「じゅ~しぃ~すくりぷと」の本のご案内
技術書コーナー
北海道の駅巡りコーナー