1. ホーム
  2. amazon-web-services

[解決済み] aws LambdaでAPIゲートウェイを経由してjsonボディを取得する。

2022-11-09 10:47:54

質問

現在、NodeJSを使用してAWS Api Gateway経由でAWS lambda上にボットを構築していますが、POSTリクエストとJSONデータで問題に遭遇しています。私のAPIは'Use Lambda Proxy integration'を使用しており、プロキシがcontent-typeをApplication/jsonにし、ボディにjsonを送信するテストをしても、例えば {"foo":"bar"} 私は最初にそれをパースすることなく、オブジェクトにアクセスすることはできません。

  var json = JSON.parse(event.body);
  console.log(json.foo);

さて、JSON.parseを通すだけでは大したことがないように見えると思いますが、そうではない例を他にもいくつか見てきました。 https://github.com/pinzler/fb-messenger-bot-aws-lambda/blob/master/index.js

これを正しく処理するために、APIゲートウェイに何かを追加する必要がありますか? 私の「post method request」セクションの「request body」ステップには、リクエストボディのcontent-typeがapplication/jsonに設定されています。

上記の例のreadmeは、私が見る限りプロキシ統合を使用していないようなので、私はここで何をすべきかわかりません。

どのように解決するのですか?

API Gatewayで設定できるLambda統合は、Lambda統合とLambdaプロキシ統合の2種類です。それぞれ Lambda統合 では、ペイロードでLambdaに渡す内容をカスタマイズできるので、ボディをパースする必要はありませんが Lambda Proxyインテグレーション を使用している場合、API GatewayはこのようにペイロードですべてをLambdaにプロキシします。

{
    "message": "Hello me!",
    "input": {
        "path": "/test/hello",
        "headers": {
            "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
            "Accept-Encoding": "gzip, deflate, lzma, sdch, br",
            "Accept-Language": "en-US,en;q=0.8",
            "CloudFront-Forwarded-Proto": "https",
            "CloudFront-Is-Desktop-Viewer": "true",
            "CloudFront-Is-Mobile-Viewer": "false",
            "CloudFront-Is-SmartTV-Viewer": "false",
            "CloudFront-Is-Tablet-Viewer": "false",
            "CloudFront-Viewer-Country": "US",
            "Host": "wt6mne2s9k.execute-api.us-west-2.amazonaws.com",
            "Upgrade-Insecure-Requests": "1",
            "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36 OPR/39.0.2256.48",
            "Via": "1.1 fb7cca60f0ecd82ce07790c9c5eef16c.cloudfront.net (CloudFront)",
            "X-Amz-Cf-Id": "nBsWBOrSHMgnaROZJK1wGCZ9PcRcSpq_oSXZNQwQ10OTZL4cimZo3g==",
            "X-Forwarded-For": "192.168.100.1, 192.168.1.1",
            "X-Forwarded-Port": "443",
            "X-Forwarded-Proto": "https"
        },
        "pathParameters": {"proxy": "hello"},
        "requestContext": {
            "accountId": "123456789012",
            "resourceId": "us4z18",
            "stage": "test",
            "requestId": "41b45ea3-70b5-11e6-b7bd-69b5aaebc7d9",
            "identity": {
                "cognitoIdentityPoolId": "",
                "accountId": "",
                "cognitoIdentityId": "",
                "caller": "",
                "apiKey": "",
                "sourceIp": "192.168.100.1",
                "cognitoAuthenticationType": "",
                "cognitoAuthenticationProvider": "",
                "userArn": "",
                "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36 OPR/39.0.2256.48",
                "user": ""
            },
            "resourcePath": "/{proxy+}",
            "httpMethod": "GET",
            "apiId": "wt6mne2s9k"
        },
        "resource": "/{proxy+}",
        "httpMethod": "GET",
        "queryStringParameters": {"name": "me"},
        "stageVariables": {"stageVarName": "stageVarValue"},
        "body": "{\"foo\":\"bar\"}",
        "isBase64Encoded": false
    }
}

あなたが参照している例では、オリジナルのリクエストからボディを取得しているわけではありません。API Gatewayに返すレスポンスボディを構築しているのです。このような形式であるべきです。

{
    "statusCode": httpStatusCode,
    "headers": { "headerName": "headerValue", ... },
    "body": "...",
    "isBase64Encoded": false
}