Use Cases (更新: 2026/6/3)

Claude Code×AWS API Gateway実装ガイド:SAMでHTTP APIを作り認証・CORS・ログ・制限までレビューする

API GatewayをClaude Codeで設計・実装。HTTP API、SAM、CORS、ログ、認証、制限を実例で解説。

Claude Code×AWS API Gateway実装ガイド:SAMでHTTP APIを作り認証・CORS・ログ・制限までレビューする

API Gatewayは「外に出すAPIの入口」

API Gatewayは、外部公開するAPIの入口で、認証・制限・ログ・バックエンド接続をまとめる層です。ブラウザやモバイルアプリから来たリクエストを受け、Lambda、HTTPサーバー、AWSサービスなどへ渡し、レスポンスを返します。初心者向けに言うなら「玄関、受付、警備、通行記録、奥の部屋への案内」を一か所に集めたものです。

MasaがAPI Gatewayで一番つまずいたのは、Lambdaのコードではありませんでした。CORSをどこで返すのか、JWT認証をAPI Gateway側で見るのかLambda側で見るのか、ログに何を出せば障害対応できるのか、スロットリングをどの値にするのか。この境界を曖昧にしたままClaude Codeへ「API作って」と頼むと、動くけれど本番運用に弱い構成が出ます。

この記事では、AWS公式ドキュメントを確認しながら、Claude CodeにレビューさせやすいAPI Gateway設計に直します。対象は最初の1本として使いやすいHTTP APIです。より高機能なREST API、双方向通信のWebSocket APIも比較し、Lambda連携、CORS、JWT/IAM認証、ステージログ、レート制限の実例を入れます。

公式情報から見る3種類のAPI

AWS公式の概念説明では、API GatewayはRESTful API、WebSocket API、HTTPやLambdaなどのバックエンド連携を管理するサービスです。API Gatewayには主にREST API、HTTP API、WebSocket APIがあります。

種類向いている用途迷った時の判断
HTTP APISPAやモバイルからLambda/HTTPへつなぐ一般的なJSON API低コスト、低レイテンシ、JWT認証、CORSが中心なら最初に選ぶ
REST APIAPIキー、利用プラン、リクエスト検証、WAF、Private APIなど細かい管理が必要B2B API、顧客別レート制限、厳密なAPI管理が必要なら選ぶ
WebSocket APIチャット、通知、進捗配信など双方向通信クライアントへサーバーから押し返したいなら選ぶ

AWSの比較表でも、REST APIは機能が多く、HTTP APIは必要最小限の機能で低価格に寄せた製品とされています。APIキーや顧客別スロットリング、リクエスト検証、AWS WAF、Private APIが必要ならREST API。JWT認証とLambda連携を早く公開したいならHTTP API、という切り分けが現実的です。

今回のサンプルはHTTP APIで作ります。理由は、Claude Codeと相性がよいからです。ルート、Lambda、CORS、ログ、制限の対応関係がテンプレートにまとまり、初学者でも差分レビューしやすいです。REST APIが悪いわけではなく、要件が増えた時の移行先として残しておくのが良いです。

公式リンク:

ユースケースを先に決める

API Gatewayの記事で薄くなりやすいのは、いきなりテンプレートを書くことです。先に「どの入口を守るのか」を決めると、Claude Codeの出力が急に現実的になります。

1つ目はLambda連携です。問い合わせフォーム、予約フォーム、社内ツールのWebhookなど、リクエストを受けて軽い検証をし、DBやメール送信に渡すAPIです。API Gatewayは公開URLとルーティングを担当し、Lambdaはビジネスロジックを担当します。

2つ目はCORSです。フロントエンドが https://example.com、APIが https://xxxx.execute-api.ap-northeast-1.amazonaws.com のように別オリジンになると、ブラウザは安全のために制限します。AWS公式では、HTTP APIでCORSを設定するとAPI GatewayがプリフライトOPTIONSへ応答し、統合先から返したCORSヘッダーを無視する場合があると説明されています。つまり「LambdaにもCORSを書いたから大丈夫」ではなく、API Gateway側の設定を本命にする必要があります。

3つ目はJWT/IAM認証です。ユーザー向けAPIならCognitoや外部IdPのJWTをHTTP APIのJWT authorizerで検証します。社内バッチや別AWSアカウントから叩くAPIならIAM認証にして、クライアントにSigV4署名を要求します。AWS公式では、HTTP APIのJWT authorizerはissuer、audience、期限、scopeなどを検証し、IAM認証では execute-api 権限を持つ署名付きリクエストだけを通します。

4つ目はステージ、ログ、レート制限です。CloudWatch Logsへアクセスログを残すと、requestIdrouteKeystatus、IP、時刻を追えます。スロットリングはトークンバケット方式で、超過時は 429 Too Many Requests になります。ただしAWS公式は、スロットリングやクォータは厳密な天井ではなく目標値として考えるべきだと説明しています。過信せず、バックエンド側の保護も合わせます。

コピーして動かすSAMサンプル

以下はAWS SAMでHTTP API、Lambda、CORS、アクセスログ、ステージ単位のスロットリングをまとめた最小構成です。JWT認証は後段で差し込めるよう、まずは公開APIとして動作確認し、Claude Codeに「公開ルートが残っていないか」をレビューさせます。

template.yaml を作成します。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Claude Code Lab HTTP API sample with CORS, logs, throttling, and Lambda proxy

Parameters:
  StageName:
    Type: String
    Default: Prod
  AllowedOrigin:
    Type: String
    Default: https://example.com

Globals:
  Function:
    Runtime: nodejs20.x
    Architectures:
      - arm64
    Timeout: 10
    MemorySize: 256

Resources:
  ApiAccessLogs:
    Type: AWS::Logs::LogGroup
    Properties:
      RetentionInDays: 14

  PublicHttpApi:
    Type: AWS::Serverless::HttpApi
    Properties:
      StageName: !Ref StageName
      CorsConfiguration:
        AllowOrigins:
          - !Ref AllowedOrigin
        AllowHeaders:
          - authorization
          - content-type
          - x-request-id
        AllowMethods:
          - GET
          - POST
          - OPTIONS
        MaxAge: 300
      AccessLogSettings:
        DestinationArn: !GetAtt ApiAccessLogs.Arn
        Format: '{"requestId":"$context.requestId","routeKey":"$context.routeKey","status":"$context.status","ip":"$context.identity.sourceIp","requestTime":"$context.requestTime","responseLength":"$context.responseLength"}'
      DefaultRouteSettings:
        ThrottlingBurstLimit: 20
        ThrottlingRateLimit: 10
      RouteSettings:
        "POST /contacts":
          ThrottlingBurstLimit: 5
          ThrottlingRateLimit: 2
      FailOnWarnings: true

  HealthFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: src/handler.health
      Events:
        Health:
          Type: HttpApi
          Properties:
            ApiId: !Ref PublicHttpApi
            Path: /health
            Method: GET
            PayloadFormatVersion: "2.0"

  ContactFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: src/handler.contact
      Events:
        Contact:
          Type: HttpApi
          Properties:
            ApiId: !Ref PublicHttpApi
            Path: /contacts
            Method: POST
            PayloadFormatVersion: "2.0"
            TimeoutInMillis: 10000

Outputs:
  ApiUrl:
    Description: Invoke URL
    Value: !Sub "https://${PublicHttpApi}.execute-api.${AWS::Region}.${AWS::URLSuffix}/${StageName}/"

package.json を作成します。

{
  "type": "module",
  "scripts": {
    "check": "node --check src/handler.js"
  }
}

src/handler.js を作成します。

const json = (statusCode, body) => ({
  statusCode,
  headers: {
    "content-type": "application/json"
  },
  body: JSON.stringify(body)
});

export const health = async () => {
  return json(200, {
    ok: true,
    service: "claude-code-api-gateway",
    checkedAt: new Date().toISOString()
  });
};

export const contact = async (event) => {
  let payload;

  try {
    payload = JSON.parse(event.body ?? "{}");
  } catch {
    return json(400, { message: "Request body must be valid JSON." });
  }

  const name = String(payload.name ?? "").trim();
  const email = String(payload.email ?? "").trim();

  if (!name || !email.includes("@")) {
    return json(422, {
      message: "name and a valid email are required.",
      requestId: event.requestContext?.requestId
    });
  }

  return json(202, {
    message: "accepted",
    requestId: event.requestContext?.requestId,
    received: { name, email }
  });
};

Git BashやmacOS/Linuxなら次で確認できます。

npm run check
sam build
sam deploy --guided \
  --stack-name clc-api-gateway-sample \
  --parameter-overrides AllowedOrigin=https://example.com

API_URL=$(aws cloudformation describe-stacks \
  --stack-name clc-api-gateway-sample \
  --query "Stacks[0].Outputs[?OutputKey=='ApiUrl'].OutputValue" \
  --output text)

curl "${API_URL}health"
curl -X POST "${API_URL}contacts" \
  -H "content-type: application/json" \
  -d '{"name":"Masa","email":"masa@example.com"}'

Windows PowerShellならURL取得と疎通だけ次の形にします。

$apiUrl = aws cloudformation describe-stacks `
  --stack-name clc-api-gateway-sample `
  --query "Stacks[0].Outputs[?OutputKey=='ApiUrl'].OutputValue" `
  --output text

curl.exe ($apiUrl + "health")
curl.exe -X POST ($apiUrl + "contacts") `
  -H "content-type: application/json" `
  -d "{\"name\":\"Masa\",\"email\":\"masa@example.com\"}"

認証は後付けではなくレビュー項目にする

サンプルはまず動作確認を優先して公開ルートにしています。本番ではここを放置してはいけません。API Gatewayの認証は、少なくとも次の3パターンで考えます。

JWT authorizerは、ログイン済みユーザーがブラウザやモバイルアプリから叩くAPI向けです。CognitoやOIDCプロバイダーが発行したアクセストークンをAPI Gatewayが検証し、scopeもルート単位で見られます。Lambda側で毎回JWTライブラリを呼ぶより、入口で拒否できるので責務が明確です。

IAM認証は、AWS上のワークロード同士、社内バッチ、管理ツール向けです。HTTP APIでもIAM authorizationを有効にでき、クライアントはSigV4で署名します。認証に失敗したリクエストはLambdaまで届きません。

Lambda authorizerは、独自ルールが必要な時の逃げ道です。既存の会員DB、IP制限、取引先別契約、複雑な権限判定があるなら使います。ただしauthorizer自体の遅延、キャッシュ、障害時の影響も設計対象に入ります。

Claude Codeには次のようにレビューさせます。

このAWS SAMテンプレートのAPI Gateway設定を本番前レビューしてください。
観点:
- 認証なしで公開されているルートがないか
- CORSのAllowOriginsが広すぎないか
- JWT/IAM/Lambda authorizerのどれを選ぶべきか
- AccessLogSettingsに障害対応に必要なrequestId, routeKey, statusが入っているか
- ThrottlingBurstLimitとThrottlingRateLimitが問い合わせフォーム用途として妥当か
- Lambda側に入力検証、タイムアウト、エラーレスポンスがあるか
- REST APIを選ぶべき要件、例えばAPIキーや顧客別利用プランがないか
修正案は差分で出してください。

このプロンプトの良いところは、Claude Codeに「コードを書いて」ではなく「本番事故を探して」と依頼している点です。API Gatewayは入口なので、機能追加より先に穴をふさぐレビューが効きます。

失敗例と落とし穴

失敗例1は、CORSをLambdaだけで返すことです。HTTP APIでCORSを設定している場合、API Gateway側がプリフライト応答やヘッダー付与を担当します。Lambdaのレスポンスに access-control-allow-origin を書いても、期待通りにならないケースがあります。CORSはフロントエンドURL、Cookie利用有無、Authorizationヘッダーの有無とセットで設計します。

失敗例2は、ログを後回しにすることです。LambdaのCloudWatch Logsだけでは、API Gatewayが返した 403404429、統合前のエラーを追いにくいです。アクセスログに requestIdrouteKey を入れると、問い合わせや監視アラートから該当ルートへ戻れます。個人情報やAuthorizationヘッダーをログに出さないことも忘れてはいけません。

失敗例3は、スロットリングを「絶対に超えない上限」と思い込むことです。AWS公式はベストエフォートの目標値として説明しています。大量アクセス時に守るべき順番は、API Gatewayの制限、Lambdaの同時実行数、DBや外部APIの制限、クライアント側のリトライ制御です。429 を受けたクライアントは指数バックオフする前提にします。

失敗例4は、HTTP APIで足りるのにREST APIから始めること、またはREST APIが必要なのにHTTP APIで押し切ることです。APIキー、顧客別利用プラン、リクエスト検証、WAF、Private APIが要件にあるならREST APIを検討します。単純なLambda公開、JWT、CORS、ログならHTTP APIで十分なことが多いです。

Claude Codeで設計品質を上げる流れ

私なら、Claude Codeへ一度に全部作らせません。まずAPIの責務を箇条書きにし、HTTP APIで足りるか、REST APIにすべきかを比較させます。次にSAMテンプレートだけを生成させ、最後にLambdaコードとエラー応答を足します。この順番にすると、CORSや認証が「後で入れるもの」になりにくいです。

おすすめの作業単位は、1回目がルート設計、2回目がSAM、3回目が認証、4回目がログとスロットリング、5回目が運用レビューです。Claude Codeのコンテキストが汚れたら、テンプレートとレビュー結果だけを残して新しいセッションに渡します。このやり方は、API Gatewayのような設定項目が多いAWSサービスで特に効きます。

関連して読むなら、Lambda側の責務は Claude Code AWS Lambda完全ガイド に分け、ログ設計は Claude Code AWS CloudWatch活用、権限設計は Claude Code AWS IAMガイド と合わせて読むと理解しやすいです。

研修・教材CTA

Claude CodeでAWS構成を作る時に大事なのは、プロンプトの上手さだけではありません。レビュー観点、公式ドキュメントの読み方、IAMとログの境界、失敗時に戻れるチェックリストが必要です。ClaudeCodeLabでは、こうした実務向けのClaude Code活用を 研修・教材ページ に整理しています。

特にAPI Gatewayは、記事を読むだけだと「なんとなく設定できた」で止まりやすい領域です。自社のAPI、問い合わせフォーム、管理画面、外部連携Webhookに合わせてレビュー観点を作ると、Claude Codeがかなり頼れる相棒になります。

Masaの手元で試した結果

Masaの手元では、上の構成をベースに node --check でLambdaハンドラの構文を確認し、SAMテンプレートではCORS、アクセスログ、ルート別スロットリングをClaude Codeにレビューさせました。特に効果があったのは、ログ形式に requestIdrouteKey を必ず入れる指摘、POST /contacts だけ制限を強める設計、公開ルートを後で認証付きへ変える作業を別チケット化する流れです。以前のようにLambdaコードから作り始めるより、レビューで見つかる漏れが明らかに減りました。

#claude-code #aws #api-gateway #lambda #typescript #rest-api
無料

無料PDF: Claude Code はじめてのチートシート

まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。

スパムは送りません。登録情報は厳重に管理します。

Claude Codeを仕事で使える形にしませんか?

無料PDFで基礎を固めたあと、すぐ使えるテンプレート集で試し、必要なら業務自動化や導入相談まで進められます。

Masa

この記事を書いた人

Masa

Claude Codeの実務活用、導入設計、収益導線改善を検証しているエンジニア。10言語の技術メディアを運営中。

PR

関連書籍・参考図書

この記事のテーマに関連する書籍を楽天ブックスで探せます。

※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。