API Gateway Lambda プロキシ統合とは?標準統合との違いとイベントオブジェクトへの影響を徹底解説

API Gateway で Lambda 関数を呼び出す方法を調べると、必ず『プロキシ統合』と『標準統合(非プロキシ統合)』という2つの選択肢に行き当たる。設定画面でチェックボックスひとつの違いに見えるが、Lambda 関数が受け取る event オブジェクトの構造、そしてレスポンスの返し方が根本的に変わる。どちらを選ぶかを誤ると、関数側でリクエストヘッダーが取れない、ステータスコードが固定されてしまうといった問題が本番環境で表面化する。

TL;DR — Lambda プロキシ統合 vs 標準統合

観点Lambda プロキシ統合標準統合(非プロキシ)
マッピングテンプレート不要(API Gateway が自動生成)必須(VTL で自分で定義)
event オブジェクト固定スキーマ(headers, pathParameters, body など)テンプレートで自由に成形
HTTP ステータスコード制御関数の戻り値で指定API Gateway のメソッドレスポンスで設定
レスポンス変換関数が JSON 構造を返す責務を持つAPI Gateway 側でマッピング可能
向いているユースケースREST API の新規開発、マイクロサービス既存バックエンドとの統合、レガシー変換

Lambda プロキシ統合の仕組みを理解する

プロキシ統合を有効にすると、API Gateway は受信した HTTP リクエストをほぼそのまま Lambda に転送する。『ほぼそのまま』というのがポイントで、実際には API Gateway が決められたスキーマの JSON オブジェクトに変換して Lambda を呼び出す。このスキーマが Lambda プロキシ統合イベント と呼ばれる構造だ。

逆方向も同様で、Lambda 関数は API Gateway が期待する特定の JSON 構造をレスポンスとして返さなければならない。この構造を満たさない場合、API Gateway はクライアントに 502 Bad Gateway を返す。

graph LR Client["クライアント
HTTP リクエスト"] --> APIGW["API Gateway
プロキシ統合"] APIGW -->|"固定スキーマ event
(headers, body, pathParams)"| Lambda["Lambda 関数"] Lambda -->|"statusCode + headers + body
(JSON 文字列)"| APIGW APIGW -->|"HTTP レスポンス"| Client style APIGW fill:#FF9900,color:#fff style Lambda fill:#527FFF,color:#fff style Client fill:#2d9e6b,color:#fff
  1. クライアント → API Gateway:HTTP リクエスト(メソッド、パス、ヘッダー、ボディ)が到着する。
  2. API Gateway → Lambda(プロキシ統合):API Gateway が固定スキーマの event オブジェクトを生成し、Lambda を同期呼び出しする。マッピングテンプレートは介在しない。
  3. Lambda → API Gateway:関数は statusCodeheadersbody を含む JSON を返す。
  4. API Gateway → クライアント:Lambda の戻り値をそのまま HTTP レスポンスとして返す。

プロキシ統合の event オブジェクト構造

REST API(API Gateway v1)でプロキシ統合を使った場合、Lambda が受け取る event の主要フィールドは以下の通り。

🔽 プロキシ統合 event オブジェクトの例(クリックで展開)
{
  "resource": "/users/{userId}",
  "path": "/users/42",
  "httpMethod": "GET",
  "headers": {
    "Accept": "application/json",
    "Authorization": "Bearer eyJ...",
    "Host": "abc123.execute-api.us-east-1.amazonaws.com"
  },
  "multiValueHeaders": {
    "Accept": ["application/json"]
  },
  "queryStringParameters": {
    "verbose": "true"
  },
  "multiValueQueryStringParameters": {
    "verbose": ["true"]
  },
  "pathParameters": {
    "userId": "42"
  },
  "stageVariables": null,
  "requestContext": {
    "resourceId": "abc123",
    "resourcePath": "/users/{userId}",
    "httpMethod": "GET",
    "requestId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "stage": "prod",
    "identity": {
      "sourceIp": "203.0.113.1",
      "userAgent": "Mozilla/5.0"
    },
    "path": "/prod/users/42"
  },
  "body": null,
  "isBase64Encoded": false
}

重要なフィールドを整理する。

  • pathParameters:API Gateway のリソースパスで定義した {userId} などのパスパラメータが展開される。
  • queryStringParameters:クエリ文字列の最後の値のみ。同名パラメータが複数ある場合は multiValueQueryStringParameters を使う。
  • headers:HTTP ヘッダー。同名ヘッダーが複数ある場合は multiValueHeaders を参照する。
  • body:リクエストボディは文字列として渡される。JSON の場合は関数内で JSON.parse() が必要。
  • isBase64Encoded:バイナリペイロードの場合 true になる。
  • requestContext:ステージ、リクエスト ID、呼び出し元 IP など API Gateway が付加するメタデータ。

プロキシ統合で Lambda が返すべきレスポンス形式

プロキシ統合では、Lambda 関数がレスポンス全体の責任を持つ。API Gateway が期待する構造を返さないと、クライアントは 502 を受け取る。

// Node.js の例
exports.handler = async (event) => {
  const userId = event.pathParameters?.userId;

  return {
    statusCode: 200,
    headers: {
      'Content-Type': 'application/json',
      'X-Custom-Header': 'value'
    },
    body: JSON.stringify({ userId: userId, name: 'Taro Yamada' }),
    isBase64Encoded: false
  };
};

statusCode は数値型で必須。body は文字列型で必須(オブジェクトをそのまま返すと 502 になる)。headers は省略可能だが、CORS を扱う場合は明示的に設定する必要がある。

標準統合(非プロキシ)との比較 — マッピングテンプレートの役割

標準統合では、API Gateway のマッピングテンプレート(Velocity Template Language / VTL)がリクエストとレスポンスの変換を担う。Lambda が受け取る event の形は、テンプレートで完全に制御できる。

graph LR Client2["クライアント
HTTP リクエスト"] --> APIGW2["API Gateway"] APIGW2 --> ReqTpl["リクエスト
マッピングテンプレート
(VTL)"] ReqTpl -->|"カスタム JSON event"| Lambda2["Lambda 関数"] Lambda2 -->|"任意の戻り値"| ResTpl["レスポンス
マッピングテンプレート
(VTL)"] ResTpl --> MethodRes["メソッドレスポンス
(ステータスコード管理)"] MethodRes -->|"HTTP レスポンス"| Client2 style APIGW2 fill:#FF9900,color:#fff style Lambda2 fill:#527FFF,color:#fff style ReqTpl fill:#666,color:#fff style ResTpl fill:#666,color:#fff style Client2 fill:#2d9e6b,color:#fff
  1. リクエストマッピングテンプレート:受信した HTTP リクエストを VTL で任意の JSON に変換して Lambda に渡す。
  2. Lambda 呼び出し:テンプレートが生成した JSON が event として渡される。構造は自由。
  3. レスポンスマッピングテンプレート:Lambda の戻り値を VTL で変換し、HTTP レスポンスを構築する。
  4. メソッドレスポンス:HTTP ステータスコードは API Gateway 側のメソッドレスポンス設定で管理する。

標準統合の利点は柔軟性だ。既存のバックエンドが特定の JSON スキーマを期待している場合や、Lambda 関数を HTTP の概念から切り離してドメインロジックだけに集中させたい場合に有効。ただし VTL の習熟コストは高く、デバッグも難しい。

プロキシ統合は『API Gateway をただのパイプにする』設計思想。標準統合は『API Gateway をアダプターにする』設計思想。どちらが正しいかではなく、変換ロジックをどこに置くかの選択だ。

HTTP API(v2)のペイロードフォーマット

API Gateway には REST API(v1)と HTTP API(v2)がある。HTTP API でも Lambda プロキシ統合が使えるが、event オブジェクトのスキーマが異なる点に注意が必要だ。HTTP API では ペイロードフォーマットバージョン として 2.0 が推奨されており、v1 とはフィールド構造が変わっている。

🔽 HTTP API ペイロードフォーマット 2.0 の event 例(クリックで展開)
{
  "version": "2.0",
  "routeKey": "GET /users/{userId}",
  "rawPath": "/users/42",
  "rawQueryString": "verbose=true",
  "headers": {
    "accept": "application/json",
    "authorization": "Bearer eyJ..."
  },
  "queryStringParameters": {
    "verbose": "true"
  },
  "requestContext": {
    "accountId": "123456789012",
    "apiId": "abc123",
    "http": {
      "method": "GET",
      "path": "/users/42",
      "sourceIp": "203.0.113.1",
      "userAgent": "Mozilla/5.0"
    },
    "requestId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "routeKey": "GET /users/{userId}",
    "stage": "$default"
  },
  "pathParameters": {
    "userId": "42"
  },
  "body": null,
  "isBase64Encoded": false
}

v1 との主な差異:httpMethodrequestContext.http.method に移動、multiValueHeaders がなくなり同名ヘッダーはカンマ区切りで結合、resource フィールドがなく代わりに routeKey が使われる。既存の v1 用コードをそのまま HTTP API に移植すると、フィールドが見つからずに undefined になるケースが多い。

実際の障害パターン — 502 の原因を誤診しやすいケース

本番で頻繁に遭遇するのが、Lambda 関数自体は正常終了しているのに API Gateway が 502 Bad Gateway を返すケースだ。CloudWatch Logs を見ると Lambda の実行ログは REPORT で正常終了している。エラーは Lambda 側にない。

原因は Lambda の戻り値が API Gateway の期待する構造を満たしていないことがほとんどだ。よくあるパターンを挙げる。

  • body がオブジェクトのままbody: { userId: 42 } と返すと 502。body: JSON.stringify({ userId: 42 }) が正しい。
  • statusCode が文字列statusCode: '200' ではなく statusCode: 200(数値)が必要。
  • 戻り値が null または undefined:非同期関数で return を忘れた場合。

この誤診が起きる理由は、CloudWatch の Lambda ログだけを見て『関数は動いている』と判断してしまうから。API Gateway 側の実行ログ(Execution Log)を有効にすると、Endpoint response body before transformations というログエントリで Lambda の生の戻り値が確認できる。ここを見れば構造の問題はすぐわかる。

# API Gateway の実行ログを確認する(CloudWatch Logs グループ名の例)
# ロググループ: API-Gateway-Execution-Logs_{restApiId}/{stageName}
aws logs filter-log-events \
  --log-group-name 'API-Gateway-Execution-Logs_abc12345/prod' \
  --filter-pattern 'Endpoint response body' \
  --region us-east-1

API Gateway の実行ログはデフォルトで無効になっている。ステージ設定でログレベルを INFO または ERROR に設定し、CloudWatch Logs への書き込み権限を持つ IAM ロールを API Gateway アカウント設定に紐付ける必要がある。

Lambda プロキシ統合を設定する — CLI 手順

既存の API Gateway REST API にプロキシ統合を設定する手順を示す。リソースとメソッドが作成済みであることを前提とする。

# 1. Lambda 統合を PUT する(プロキシ統合は type=AWS_PROXY)
aws apigateway put-integration \
  --rest-api-id abc12345 \
  --resource-id xyz98765 \
  --http-method GET \
  --type AWS_PROXY \
  --integration-http-method POST \
  --uri 'arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:MyFunction/invocations' \
  --region us-east-1
# 2. API Gateway から Lambda を呼び出す権限を付与する
aws lambda add-permission \
  --function-name MyFunction \
  --statement-id apigateway-prod-get \
  --action lambda:InvokeFunction \
  --principal apigateway.amazonaws.com \
  --source-arn 'arn:aws:execute-api:us-east-1:123456789012:abc12345/prod/GET/users/*' \
  --region us-east-1
# 3. デプロイして変更を反映する
aws apigateway create-deployment \
  --rest-api-id abc12345 \
  --stage-name prod \
  --region us-east-1

integration-http-method は Lambda 呼び出しなので常に POST を指定する。これは API Gateway が Lambda の Invoke API を POST で呼び出すためであり、クライアントが使う HTTP メソッドとは独立している。ここを GET にすると統合が失敗するが、エラーメッセージが直感的でないため混乱しやすい。

IAM ポリシー — 最小権限の設定

Lambda 関数が CloudWatch Logs に書き込むための基本的な実行ロールポリシーを示す。

🔽 Lambda 実行ロールポリシー例(クリックで展開)
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:us-east-1:123456789012:log-group:/aws/lambda/MyFunction:*"
    }
  ]
}

Lambda プロキシ統合のまとめと次のステップ

Lambda プロキシ統合は、API Gateway のマッピングテンプレートを排除することで設定を大幅に簡素化する。その代わり、event オブジェクトのスキーマ理解と、正しいレスポンス構造を返す責任が Lambda 関数側に移る。REST API(v1)と HTTP API(v2)でペイロードフォーマットが異なる点は、移植時の落とし穴になりやすいので注意が必要だ。

次のステップとして、以下の公式ドキュメントを参照することを推奨する。

用語集(Glossary)

用語説明
Lambda プロキシ統合API Gateway が HTTP リクエストを固定スキーマの JSON に変換して Lambda に渡す統合方式。マッピングテンプレート不要。
マッピングテンプレート(VTL)標準統合でリクエスト/レスポンスを変換するための Velocity Template Language スクリプト。
ペイロードフォーマットバージョンHTTP API(v2)で Lambda に渡す event の構造バージョン。1.0 と 2.0 が存在し、デフォルトは 1.0。
502 Bad Gatewayプロキシ統合で Lambda の戻り値が期待する構造を満たさない場合に API Gateway がクライアントに返すエラー。
AWS_PROXYAPI Gateway の統合タイプ識別子。Lambda プロキシ統合を指定する際に使用する。

Related Posts

コメント

このブログの人気の投稿

SQS Visibility Timeoutの完全解説:メッセージ二重処理の原因と対策

EC2 SSH接続タイムアウトの原因と修正方法 — セキュリティグループのインバウンドルール完全ガイド

S3パブリックアクセス拒否の原因と解決策:バケットレベルの「Block Public Access」が優先される仕組み