2026年7月9日
2026年7月9日
AWS Lambda + API Gatewayの設定方法|HTTP APIで作るWordPress用フォーム送信エンドポイント
Lambda 関数を Web から呼び出せるようにするには、API Gateway でエンドポイント(URL)を作り、Lambda と「プロキシ統合」でつなぎます。この記事では、WordPress のお問い合わせフォームから送信内容を受け取る API を例に、HTTP API の作成、ルートと統合、Lambda への呼び出し許可、CORS の設定、WordPress 側からの呼び出し方までを順に説明します。手順を終えると、ブラウザから送った JSON を Lambda で検証して結果を返す API が動く状態になります。
この記事は AWS ドキュメントの内容(2026年10月現在)をもとに説明していますが、API Gateway の種類ごとの機能差やコンソールの表記は更新されることがあります。Lambda 関数そのものの作り方(実行ロールやログの確認)は、別記事「AWS LambdaでServerless関数を作成する方法」で扱っているので、この記事では API として公開する部分に絞ります。
HTTP APIとREST APIのどちらを選ぶか
API Gateway には、主に HTTP API と REST API の2種類があります(ほかに WebSocket API があります)。
- HTTP API: 構成が単純で、Lambda とつなぐだけの用途に向いています。CORS や JWT 認証(Amazon Cognito など)を標準で設定できます。
- REST API: API キーと使用量プラン、リクエストの検証、AWS WAF との直接の連携など、機能が多い代わりに設定項目も多くなります。
フォーム送信や小さなデータ取得のように「Lambda を1つ呼ぶだけ」なら、HTTP API から始めるのが分かりやすい選択です。WAF を API Gateway に直接付けたい、API キーで利用者ごとに上限を管理したい、といった要件があるなら REST API を検討してください。どちらが対応しているかは更新で変わる可能性があるので、要件に関わる機能は最新のドキュメントで確認しましょう。
なお、Lambda には API Gateway を使わずに関数へ直接 URL を割り当てる「関数 URL」という機能もあります。ルートを分けない、細かい制御が不要という場合は、こちらのほうが簡単なこともあります。
手順1:フォームを受け取るLambda関数を用意する
HTTP API の Lambda プロキシ統合(ペイロード形式 2.0)では、リクエストの内容が event に入って関数へ渡されます。本文は event["body"] に文字列で入り、Base64 で符号化されている場合は event["isBase64Encoded"] が true になります。関数は statusCode、headers、body を持つ辞書を返します。
# lambda_function.py(wp-form-handler)
import base64
import json
import re
MAX_BODY = 10000
EMAIL_RE = re.compile(r"^[^@\s]+@[^@\s]+\.[^@\s]+$")
def response(status, payload):
return {
"statusCode": status,
"headers": {"Content-Type": "application/json; charset=utf-8"},
"body": json.dumps(payload, ensure_ascii=False),
}
def lambda_handler(event, context):
body = event.get("body") or ""
if event.get("isBase64Encoded"):
body = base64.b64decode(body).decode("utf-8")
if len(body) > MAX_BODY:
return response(413, {"error": "payload too large"})
try:
data = json.loads(body)
except json.JSONDecodeError:
return response(400, {"error": "invalid json"})
if not isinstance(data, dict):
return response(400, {"error": "invalid json"})
name = str(data.get("name", "")).strip()
email = str(data.get("email", "")).strip()
message = str(data.get("message", "")).strip()
if not name or len(name) > 100:
return response(400, {"error": "invalid name"})
if not EMAIL_RE.match(email) or len(email) > 254:
return response(400, {"error": "invalid email"})
if not message or len(message) > 2000:
return response(400, {"error": "invalid message"})
# ここで Amazon SES での通知や DynamoDB への保存を行う。
# 氏名・メールアドレス・本文などの個人情報はログに出さない。
print(json.dumps({"event": "contact_received", "request_id": context.aws_request_id}))
return response(200, {"ok": True})
外部から誰でも呼べる API なので、入力はすべて信用せず、型と長さを検証してから使います。ログには受付の記録だけを残し、送信内容そのものを出力しないようにしてください。お問い合わせの内容は個人情報に当たるため、保存先・保存期間・利用目的をサイトのプライバシーポリシーに記載しておく必要があります。
手順2:HTTP APIを作成し、ルートと統合を設定する
コンソールでは、API Gateway の画面から HTTP API の作成を選び、統合に Lambda 関数を指定し、ルートとして POST /contact を設定します。ステージは自動デプロイが有効な $default を使うと、変更がすぐ反映されて扱いやすくなります。
CLI で作る場合は、API・統合・ルート・ステージを順に作ります。各コマンドが返す ID を次のコマンドで使います。
# 1. API の作成(CORS もここで設定)
aws apigatewayv2 create-api \
--name wp-form-api \
--protocol-type HTTP \
--cors-configuration '{"AllowOrigins":["https://example.com"],"AllowMethods":["POST"],"AllowHeaders":["content-type"],"MaxAge":600}'
# 2. Lambda プロキシ統合の作成(返ってきた ApiId を使う)
aws apigatewayv2 create-integration \
--api-id abcdef1234 \
--integration-type AWS_PROXY \
--integration-uri arn:aws:lambda:ap-northeast-1:123456789012:function:wp-form-handler \
--payload-format-version 2.0
# 3. ルートの作成(返ってきた IntegrationId を使う)
aws apigatewayv2 create-route \
--api-id abcdef1234 \
--route-key "POST /contact" \
--target integrations/xyz7890
# 4. 自動デプロイのステージを作成
aws apigatewayv2 create-stage \
--api-id abcdef1234 \
--stage-name '$default' \
--auto-deploy
$default ステージを使った場合、エンドポイントは https://abcdef1234.execute-api.ap-northeast-1.amazonaws.com/contact の形になります。独自ドメインで公開したい場合は、API Gateway のカスタムドメイン名と ACM の証明書を組み合わせて設定します。
手順3:API GatewayにLambdaの呼び出しを許可する
CLI で統合を作った場合、API Gateway が Lambda を呼び出す許可(リソースベースポリシー)を別途付ける必要があります。これを忘れると、API を呼んだときに 500 の Internal Server Error が返り、Lambda のログには何も出ない、という分かりにくい症状になります。
aws lambda add-permission \
--function-name wp-form-handler \
--statement-id apigw-wp-form-api \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-arn "arn:aws:execute-api:ap-northeast-1:123456789012:abcdef1234/*/*/contact"
--source-arn で API とルートを限定しておくと、ほかの API から関数を呼ばれることを防げます。コンソールから統合を作った場合は、この許可が自動で追加されることが多いので、Lambda の「設定」にあるアクセス権限の画面で重複していないか確認してください。
手順4:CORSとスロットリングを設定する
WordPress のページ(https://example.com)から別ドメインの API(execute-api.amazonaws.com)を呼ぶため、ブラウザは CORS の確認を行います。Content-Type: application/json で送る場合は、本番のリクエストの前にプリフライト(OPTIONS)が送られます。
HTTP API で CORS を設定しておくと、API Gateway がプリフライトに自動で応答し、レスポンスに CORS ヘッダーを付けます。このとき Lambda が返す CORS ヘッダーは無視されるとされているため、設定は API Gateway 側に一本化します。AllowOrigins には自分のサイトのオリジンだけを指定し、* は避けてください。ただし、CORS はブラウザに対する制限であり、curl などからの直接の呼び出しは防げません。
そこで、呼び出し回数の上限(スロットリング)も設定します。HTTP API ではステージやルートごとに、1秒あたりのリクエスト数とバースト数の上限を指定できます。上限を超えたリクエストには 429 が返り、Lambda は呼ばれません。スパム対策としては、これに加えて CAPTCHA サービスのトークンを Lambda 側で検証する方法がありますが、検証方法はサービスごとに異なるので、各サービスのドキュメントに従ってください。
手順5:WordPressから呼び出す
テーマやプラグインから JavaScript を読み込み、API の URL を渡します。子テーマの functions.php に書く例です。strategy 引数による defer 指定は WordPress 6.3 以降で使えます。
add_action( 'wp_enqueue_scripts', function () {
if ( ! is_page( 'contact' ) ) {
return;
}
wp_enqueue_script(
'wp-form-api',
get_stylesheet_directory_uri() . '/js/contact-api.js',
array(),
'1.0.0',
array(
'in_footer' => true,
'strategy' => 'defer',
)
);
wp_add_inline_script(
'wp-form-api',
'window.wpFormApi = ' . wp_json_encode(
array( 'endpoint' => 'https://abcdef1234.execute-api.ap-northeast-1.amazonaws.com/contact' )
) . ';',
'before'
);
} );
// js/contact-api.js
document.addEventListener('DOMContentLoaded', () => {
const form = document.querySelector('#contact-form');
if (!form) return;
const status = form.querySelector('.form-status');
form.addEventListener('submit', async (e) => {
e.preventDefault();
const data = Object.fromEntries(new FormData(form));
try {
const res = await fetch(window.wpFormApi.endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
status.textContent = res.ok ? '送信しました。' : '送信できませんでした。入力内容を確認してください。';
} catch (err) {
status.textContent = '通信エラーが発生しました。時間をおいて再度お試しください。';
}
});
});
結果の表示に innerHTML ではなく textContent を使っているのは、API の応答に想定外の文字列が含まれても HTML として解釈されないようにするためです。
動作確認とつまずきやすい点
まず curl で API 単体の動作を確認します。
curl -i -X POST https://abcdef1234.execute-api.ap-northeast-1.amazonaws.com/contact \
-H "Content-Type: application/json" \
-d '{"name":"テスト","email":"test@example.com","message":"動作確認です"}'
200 と {"ok": true} が返れば成功です。うまくいかない場合は、よくある順に次を確認します。
- 500 が返り、Lambda のログが無い: 手順3の呼び出し許可が無いか、
--source-arnの API ID が違います。 - 404 Not Found: ルートキー(
POST /contact)とリクエストのメソッド・パスが一致しているか、ステージがデプロイされているかを確認します。 - ブラウザだけ失敗し、curl では成功する: CORS の
AllowOriginsと実際のサイトのオリジン(https://の有無、wwwの有無)が一致しているかを、開発者ツールのコンソールで確認します。 - 502 が返る: Lambda の戻り値の形式が崩れているか、関数内で例外が起きています。CloudWatch Logs でエラー内容を確認します。
まとめ
- Lambda を1つ呼ぶだけなら HTTP API、WAF の直接連携や API キーが必要なら REST API を検討する。
- CLI では API・統合・ルート・ステージを順に作り、
lambda add-permissionで呼び出しを許可する。 - CORS は API Gateway 側で自分のオリジンだけを許可し、スロットリングで呼び出し回数に上限を設ける。
- 公開 API では入力を検証し、個人情報をログに残さず、プライバシーポリシーに取り扱いを書く。
- WordPress 側は
wp_enqueue_scriptとwp_add_inline_scriptで URL を渡し、結果はtextContentで表示する。