

# API Gateway での Lambda プロキシ統合
<a name="set-up-lambda-proxy-integrations"></a>

次のセクションでは、Lambda プロキシ統合を使用する方法を示します。

**Topics**
+ [API Gateway Lambda プロキシの統合について理解する](#api-gateway-create-api-as-simple-proxy)
+ [複数値のヘッダーとクエリ文字列パラメータのサポート](#apigateway-multivalue-headers-and-parameters)
+ [プロキシ統合のための Lambda 関数の入力形式](#api-gateway-simple-proxy-for-lambda-input-format)
+ [プロキシ統合のための Lambda 関数の出力形式](#api-gateway-simple-proxy-for-lambda-output-format)
+ [AWS CLI を使用して API Gateway の Lambda プロキシ統合をセットアップする](set-up-lambda-proxy-integration-using-cli.md)
+ [OpenAPI 定義を使用してプロキシリソースに Lambda プロキシ統合をセットアップする](api-gateway-set-up-lambda-proxy-integration-on-proxy-resource.md)

## API Gateway Lambda プロキシの統合について理解する
<a name="api-gateway-create-api-as-simple-proxy"></a>

Amazon API Gateway Lambda プロキシ統合は、単一の API メソッドのセットアップで API を構築するシンプル、強力、高速なメカニズムです。Lambda プロキシ統合は、クライアントが単一の Lambda 関数をバックエンドで呼び出すことを可能にします。この関数は、他の Lambda 関数の呼び出しを含め、AWS のその他サービスのさまざまなリソースや機能にアクセスします。

 Lambda プロキシ統合では、クライアントが API リクエストを送信すると、API Gateway は、統合された Lambda 関数に[イベントオブジェクト](#api-gateway-simple-proxy-for-lambda-input-format)を渡します。ただし、リクエストパラメータの順序は保持されません。この[リクエストデータ](#api-gateway-simple-proxy-for-lambda-input-format)には、リクエストヘッダー、クエリ文字列パラメータ、URL パス変数、ペイロード、および API 設定データが含まれます。設定データには、現在のデプロイステージ名、ステージ変数、ユーザー ID、または承認コンテキスト (存在する場合) を含めることができます。バックエンド Lambda 関数では、受信リクエストデータを解析して、返すレスポンスを決定します。API Gateway が Lambda 出力を API レスポンスとしてクライアントに渡すには、Lambda 関数は結果を[この形式](#api-gateway-simple-proxy-for-lambda-output-format)で返す必要があります。

 API Gateway は Lambda プロキシ統合でクライアントとバックエンド Lambda 関数間にあまり介入しないため、クライアントと統合された Lambda 関数は、API の既存の 統合セットアップを損なうことなく、相互の変更に適応できます。これを有効にするには、クライアントはバックエンド Lambda 関数が制定したアプリケーションプロトコルに従う必要があります。

 任意の API メソッドで Lambda プロキシ統合をセットアップできます。しかし、Lambda プロキシ統合は、汎用的なプロキシリソースが含まれる API メソッドに設定されていると、より強力です。汎用的なプロキシリソースは、特別なテンプレートパス変数である `{proxy+}` 、キャッチオールである `ANY` メソッドプレースホルダー、または両方によって示すことができます。クライアントは、受信リクエストのバックエンド Lambda 関数に、入力をリクエストパラメータまたは適切なペイロードとして渡すことができます。リクエストパラメータには、ヘッダー、URL パス変数、クエリ文字列パラメータ、および適切なペイロードが含まれます。統合された Lambda 関数は、リクエストを処理して、必要な入力がない場合に意味のあるエラーメッセージでクライアントに応答する前に、すべての入力ソースを検証します。

 `ANY` の汎用的な HTTP メソッドと `{proxy+}` の汎用的なリソースと統合されている API メソッドを呼び出す際、クライアントは `ANY` の代わりに特定の HTTP メソッドを持つリクエストを送信します。クライアントはさらに、`{proxy+}` の代わりに特定の URL パスを指定し、要求されるヘッダー、クエリ文字列パラメータ、または適切なペイロードを含めます。

 次のリストは、Lambda プロキシ統合での異なる API メソッドのランタイム動作を要約しています。
+ `ANY /{proxy+}`: クライアントは特定の HTTP メソッドを選択し、特定のリソースパス階層を設定する必要があり、Lambda 関数にデータを入力として渡すために任意のヘッダー、クエリ文字列パラメータ、および適切なペイロードを設定できます。
+ `ANY /res`: クライアントは特定の HTTP メソッドを選択する必要があり、Lambda 関数にデータを入力として渡すために任意のヘッダー、クエリ文字列パラメータ、および適切なペイロードを設定できます。
+ `GET|POST|PUT|... /{proxy+}`: クライアントは特定のリソースパス階層を設定することができ、Lambda 関数にデータを入力として渡すために任意のヘッダー、クエリ文字列パラメータ、および適切なペイロードを設定できます。
+  `GET|POST|PUT|... /res/{path}/...`: クライアントは (`{path}` 変数に) 特定のパスセグメントを選択する必要があり、Lambda 関数に入力データを渡すために任意のリクエストヘッダー、クエリ文字列パラメータ、および適切なペイロードを設定できます。
+  `GET|POST|PUT|... /res`: クライアントは Lambda 関数に入力データを渡すために任意のリクエストヘッダー、クエリ文字列パラメータ、および適切なペイロードを設定できます。

 `{proxy+}` のプロキシリソースと `{custom}` のカスタムリソースの両方が、テンプレートパス変数として表現されています。ただし、`{proxy+}` はパス階層に沿った任意のリソースを参照できますが、`{custom}` は特定のパスセグメントのみを参照します。たとえば、食料品店はオンラインの製品インベントリを部門名、農産物カテゴリ、および製品タイプで整理しています。食料品店のウェブサイトは、カスタムリソースの次のテンプレートパス変数によって、利用可能な製品を表すことができます: `/{department}/{produce-category}/{product-type}`。たとえば、リンゴは `/produce/fruit/apple` で表され、ニンジンは `/produce/vegetables/carrot` で表されます。また、`/{proxy+}` を使用して、顧客がオンラインストアで買い物中に検索できる任意の部門、農産物カテゴリ、または製品タイプを表すことができます。たとえば、`/{proxy+}` は次のいずれかのアイテムを参照できます。
+ `/produce`
+ `/produce/fruit`
+ `/produce/vegetables/carrot`

 顧客が利用可能な製品、その農産物カテゴリ、および関連するストア部門を検索できるようにするには、`GET /{proxy+}` の単一メソッドを読み取り専用アクセス権限で公開することができます。同様に、責任者が `produce` 部門のインベントリをアップデートできるようにするには、別の `PUT /produce/{proxy+}` の単一メソッドを読み取り/書き込みアクセス権限でセットアップできます。レジ係が野菜の合計を更新できるようにするには、`POST /produce/vegetables/{proxy+}` メッセージを読み取り/書き込みアクセス権限でセットアップできます。店長が任意のアクションを任意の利用可能な製品に実行できるようにするには、オンラインストア開発者は `ANY /{proxy+}` メソッドを読み取り/書き込みアクセス権限で公開できます。いずれの場合も、実行時には、顧客または従業員は選択された部門のあるタイプの特定の製品、製品部門の特定の農産物カテゴリ、または特定の部門を選択する必要があります。



API Gateway プロキシ統合のセットアップの詳細については、「[プロキシリソースとのプロキシ統合を設定する](api-gateway-set-up-simple-proxy.md)」を参照してください。

 プロキシ統合は、クライアントがバックエンド要件のより詳細な知識を持っていることを要求します。したがって、最適なアプリケーションパフォーマンスとユーザーエクスペリエンスを確保するために、バックエンド開発者はバックエンドの要件をクライアント開発者に明確に伝え、要件が満たされない場合は堅牢なエラーフィードバックメカニズムを提供する必要があります。

## 複数値のヘッダーとクエリ文字列パラメータのサポート
<a name="apigateway-multivalue-headers-and-parameters"></a>

API Gateway は、同じ名前を持つ複数のヘッダーやクエリ文字列パラメータをサポートするようになりました。複数値ヘッダーや単一値ヘッダー、およびパラメータを、同じリクエストとレスポンスで組み合わせることができます。詳細については、「[プロキシ統合のための Lambda 関数の入力形式](#api-gateway-simple-proxy-for-lambda-input-format)」および「[プロキシ統合のための Lambda 関数の出力形式](#api-gateway-simple-proxy-for-lambda-output-format)」を参照してください。

## プロキシ統合のための Lambda 関数の入力形式
<a name="api-gateway-simple-proxy-for-lambda-input-format"></a>

Lambda プロキシ統合では、API Gateway がクライアントリクエスト全体をバックエンド Lambda 関数の入力 `event` パラメータにマップします。次の例は、API Gateway が Lambda プロキシ統合に送信するイベントの構造を示しています。

この例では、API Gateway への呼び出しが次のようになっていることを前提としています。

```
curl 'https://a1b2c3.execute-api.us-east-1.amazonaws.com/my/path?parameter1=value1&parameter2=value1&parameter2=value2&parameter3=value1,value2' -H 'header1: value1' -H 'header2: value1' -H 'header2: value2' -H 'header3: value1,value2'
```

出力は次のようになります。

```
{
  "resource": "/my/path",
  "path": "/my/path",
  "httpMethod": "GET",
  "headers": {
      "header1": "value1",
      "header2": "value2",
      "header3": "value1,value2"
  },
  "multiValueHeaders": {
    "header1": ["value1"],
    "header2": ["value1","value2"],
    "header3": ["value1,value2"]
  },
  "queryStringParameters": {
      "parameter1": "value1",
      "parameter2": "value2",
      "parameter3": "value1,value2"
  },
  "multiValueQueryStringParameters": {
    "parameter1": ["value1"],
    "parameter2": ["value1","value2"],
    "parameter3": ["value1,value2"]
  },
  "requestContext": {
    "accountId": "123456789012",
    "apiId": "id",
    "authorizer": {
      "claims": null,
      "scopes": null
    },
    "domainName": "id.execute-api.us-east-1.amazonaws.com",
    "domainPrefix": "id",
    "extendedRequestId": "request-id",
    "httpMethod": "GET",
    "identity": {
      "accessKey": null,
      "accountId": null,
      "caller": null,
      "cognitoAuthenticationProvider": null,
      "cognitoAuthenticationType": null,
      "cognitoIdentityId": null,
      "cognitoIdentityPoolId": null,
      "principalOrgId": null,
      "sourceIp": "IP",
      "user": null,
      "userAgent": "user-agent",
      "userArn": null,
      "clientCert": {
        "clientCertPem": "CERT_CONTENT",
        "subjectDN": "www.example.com",
        "issuerDN": "Example issuer",
        "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1",
        "validity": {
          "notBefore": "May 28 12:30:02 2019 GMT",
          "notAfter": "Aug  5 09:36:04 2021 GMT"
        }
      }
    },
    "path": "/my/path",
    "protocol": "HTTP/1.1",
    "requestId": "id=",
    "requestTime": "04/Mar/2020:19:15:17 +0000",
    "requestTimeEpoch": 1583349317135,
    "resourceId": null,
    "resourcePath": "/my/path",
    "stage": "$default"
  },
  "pathParameters": null,
  "stageVariables": null,
  "body": "Hello from Lambda!",
  "isBase64Encoded": false
}
```

**注記**  
入力値は、次のようになります。  
`headers` キーには、単一値のヘッダーのみを含めることができます。
`multiValueHeaders` キーには、複数値のヘッダーや単一値のヘッダーを含めることができます。
`headers` と `multiValueHeaders` の両方の値を指定した場合、API Gateway はそれらを単一のリストにマージします。同じキーと値のペアが両方で指定された場合にのみ、`multiValueHeaders` の値が、マージされたリストに表示されます。

バックエンド Lambda 関数への入力では、`requestContext` オブジェクトはキーと値のペアのマップです。各ペアにおいて、キーは [$context](api-gateway-mapping-template-reference.md#context-variable-reference) 変数プロパティの名前であり、値はそのプロパティの値です。API Gateway は、マップに新しいキーを追加する場合があります。

有効になっている機能に応じて、`requestContext` マップは API ごとに異なる場合があります。たとえば、前述の例では、認可タイプが指定されていないため、`$context.authorizer.*` や `$context.identity.*` プロパティは存在しません。認可タイプが指定されると、API Gateway は、認可されたユーザー情報を `requestContext.identity` オブジェクト内の統合エンドポイントに次のように渡します。
+ 認可タイプが `AWS_IAM` の場合、認可されるユーザー情報には `$context.identity.*` プロパティが含まれます。
+ 認可タイプが `COGNITO_USER_POOLS` (Amazon Cognito オーソライザー) の場合、認可されるユーザー情報には `$context.identity.cognito*` および `$context.authorizer.claims.*` プロパティが含まれます。
+ 認可タイプが `CUSTOM` (Lambda オーソライザー) の場合、認可されるユーザー情報には `$context.authorizer.principalId` およびその他の該当する `$context.authorizer.*` プロパティが含まれます。

## プロキシ統合のための Lambda 関数の出力形式
<a name="api-gateway-simple-proxy-for-lambda-output-format"></a>

Lambda プロキシ統合では、以下の JSON 形式に従って出力を返すために、API Gateway はバックエンドの Lambda 関数を必要とします。

```
{
    "isBase64Encoded": {{true|false}},
    "statusCode": {{httpStatusCode}},
    "headers": { "{{headerName}}": "{{headerValue}}", ... },
    "multiValueHeaders": { "{{headerName}}": ["{{headerValue}}", "{{headerValue2}}", ...], ... },
    "body": "{{...}}"
}
```

出力では、次のようになります。
+ 余分なレスポンスヘッダーが返されない場合、`headers` および `multiValueHeaders` キーは指定されません。
+ `headers` キーには、単一値のヘッダーのみを含めることができます。
+ `multiValueHeaders` キーには、複数値のヘッダーや単一値のヘッダーを含めることができます。`multiValueHeaders` キーを使用して、単一値のヘッダーを含めて、すべてのヘッダーを指定することができます。
+ `headers` と `multiValueHeaders` の両方の値を指定した場合、API Gateway はそれらを単一のリストにマージします。同じキーと値のペアが両方で指定された場合にのみ、`multiValueHeaders` の値が、マージされたリストに表示されます。

Lambda プロキシ統合に対して CORS を有効にするには、`Access-Control-Allow-Origin:{{domain-name}}` を出力 `headers` に追加する必要があります。`{{domain-name}}` は、任意のドメイン名に対して `*` にすることができます。出力 `body` は、メソッドレスポンスペイロードとしてフロントエンドにマーシャリングされます。`body` がバイナリ BLOB の場合、`isBase64Encoded` を `true` に設定し、`*/*` を [**バイナリメディアタイプ**] に設定することで、Base64 エンコード文字列としてエンコードできます。それ以外の場合は、`false` に設定するか、指定しないでおくことができます。

**注記**  
バイナリサポートの有効化に関する詳細については、[API Gateway コンソールを使用したバイナリサポートの有効化](api-gateway-payload-encodings-configure-with-console.md) を参照してください。サンプルの Lambda 関数については、「[API Gateway のLambda プロキシ統合からバイナリメディアを返す](lambda-proxy-binary-media.md)」を参照してください。

関数出力が別の形式である場合、API Gateway は `502 Bad Gateway` エラーレスポンスを返します。

Node.js での Lambda 関数でレスポンスを返すには、次のようなコマンドを使用できます。
+ 成功した場合の結果を返すには、`callback(null, {"statusCode": 200, "body": "results"})` を呼び出します。
+ 例外をスローするには、`callback(new Error('internal server error'))` を呼び出します。
+ クライアント側エラーの場合 (必要なパラメータがない場合など)、`callback(null, {"statusCode": 400, "body": "Missing parameters of ..."})` を呼び出して、例外をスローせずにエラーを返すことができます。

Node.js の Lambda `async` 関数では、同等の構文は次のようになります。
+ 成功した場合の結果を返すには、`return {"statusCode": 200, "body": "results"}` を呼び出します。
+ 例外をスローするには、`throw new Error("internal server error")` を呼び出します。
+ クライアント側エラーの場合 (必要なパラメータがない場合など)、`return {"statusCode": 400, "body": "Missing parameters of ..."}` を呼び出して、例外をスローせずにエラーを返すことができます。