Search code examples
amazon-web-servicesaws-lambdaaws-api-gateway

Getting json body in aws Lambda via API gateway


I'm currently using NodeJS to build a bot on AWS lambda via AWS Api Gateway and I'm running into an issue with POST requests and JSON data. My api uses 'Use Lambda Proxy integration' and even when I test the proxy sending a content-type of Application/json and some json in the body e.g {"foo":"bar"} I can't access the object without parsing it first

e.g

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

Now I know this doesn't seem a big deal just running it through JSON.parse, but I've seen a number of other examples where this isn't the case at all. see here https://github.com/pinzler/fb-messenger-bot-aws-lambda/blob/master/index.js

Do I need to add anything to my API gateway to handle this correctly? my 'request body' step in the 'post method request' section has a content-type of application/json set-up for the request body.

The readme for the example above doesn't seem to use proxy integration as far as I can tell so I'm not sure what I should be doing here


Solution

  • There are two different Lambda integrations you can configure in API Gateway:

    1. Lambda non-proxy integration (docs), also called Lambda custom integration
    2. Lambda proxy integration (docs)

    For Lambda non-proxy integration, you can customise what you are going to pass to Lambda in the payload that you don't need to parse the body, but when you are using Lambda Proxy integration in API Gateway, API Gateway will proxy everything to Lambda in payload like this:

    {
        "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
        }
    }
    

    For the example you are referencing, it is not getting the body from the original request. It is constructing the response body back to API Gateway. It should be in this format:

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