4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

API GatewayのLambdaプロキシ統合とは

Posted at

概要

API Gateway作成時にあるLambdaプロキシ統合というものが気になったので、少しまとめてみました。
image.png

Lambdaプロキシ統合とは

ざっくりいうと、API Gatewayが受け取ったHTTPリクエスト全体を、evantパラメータとしてLambda関数に渡し、Lambda関数のレスポンスをそのままHTTPレスポンスとしてクライアントに返す統合方式です。
API Gatewayでは、レスポンスの形式を指定する方法として「マッピングテンプレート」がありますが、その設定も不要になっています。

実際に使ってみる

今回はデフォルトのLambda関数で試してみようと思います。また、APIGatewayも2種類作成して比較しました。

  • プロキシ統合有効
    image.png

  • プロキシ統合無効
    image.png

import json

def lambda_handler(event, context):
    # TODO implement
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

Lambda統合プロキシの有無でそれぞれ以下のようにレスポンスが変化します。

Lambda統合プロキシがなしの場合
image.png

Lambda統合プロキシありの場合

image.png

これは冒頭で示した公式ドキュメントにあるように、body部の値をレスポンス部分として返してくれるようになっているからです。今回は'Hello from Lambda!'の部分がそのまま返ってきてくれたわけですね。

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

プロキシ統合のための Lambda 関数の出力形式

入力時の形式はあるのか

プロキシ統合を有効にすればあとはなんでもおっけ~というわけでもなく、Lambda入力時のお作法的なものも一応ありました。

{
 "resource": "/my/path",
 "path": "/my/path",
 "httpMethod": "GET",
 "headers": {
   "header1": "value1",
   "header2": "value1,value2"
 },
 "multiValueHeaders": {
   "header1": [
     "value1"
   ],
   "header2": [
     "value1",
     "value2"
   ]
 },
 "queryStringParameters": {
   "parameter1": "value1,value2",
   "parameter2": "value"
 },
 "multiValueQueryStringParameters": {
   "parameter1": [
     "value1",
     "value2"
   ],
   "parameter2": [
     "value"
   ]
 },
 "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
}

プロキシ統合のための Lambda 関数の入力形式

ここで実際に値の受け渡しをしているのは"queryStringParameters"ですね。これ含めて、eventオブジェクトとしてLambdaにこれらのパラメータを渡しているようです。ではこれを踏まえて実際に試してみようと思います。

queryStringParametersに値を渡してみる

以下のように'input_text'をeventオブジェクトとして受け取るように関数を変更します。

import json

def lambda_handler(event, context):
    # TODO implement
    return {
        'statusCode': 200,
        'body': json.dumps(event['queryStringParameters']['input_text'])
    }

プロキシ統合有効時

  • エンドポイント指定→?input_text=hello
    image.png

プロキシ統合無効時

  • エンドポイント指定→?input_text=hello
{
  "errorMessage": "'queryStringParameters'",
  "errorType": "KeyError",
  "requestId": "55f41ab8-9120-4ca4-8d25-608fd343bb5a",
  "stackTrace": [
    "  File \"/var/task/lambda_function.py\", line 7, in lambda_handler\n    'body': json.dumps(event['queryStringParameters']['input_text'])\n"
  ]
}

ここで言われているのは、'queryStringParameters'なんてキーないよと言われてしまっています。プロキシ統合を有効にすることでeventへのマッピングはすべてやってくれていたのですが、無効にしてしまうとやってくれないのでこのようなエラーが発生します。

マッピングテンプレートを使用する

プロキシ統合を使用せずにレスポンスを取得するにはマッピングテンプレートを使用するのも一つの手です。
プロキシ統合使用時はeventオブジェクトとして構造化して使用していましたが、マッピングテンプレートにレスポンスの形を明示的に示すことで構造を作ることができます。

今回は以下のように'input_text'を受け取れるようにしたいと思います。
image.png

再デプロイ後同様にリクエストを送ったところ、queryStringParametersの値にマッピングテンプレートを使用してアクセスできました。
image.png

まとめ

LambdaやAPI Gatewayは普段あまり触らないですが、学びなおすいい機会になりました。
最近全然ブログ書けてなかったのでもう少し頻度上げていきたい...

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?