1
votes

I have this python lambda function

import json

def lambda_handler(event, context):

    post_user = ""
    post_user = event["user"]
    print(post_user)        

    return {
        "statusCode": 200,
        "headers": {"Content-Type": "application/json"},
        "body": True
        }

This works as expected when I run a test within the lambda IDE. The test is configured to pass:

{ "user": "JOHN", "pwd": "pwd1" }

but when I run a test using the API Gateway, I get this error:

Mon Mar 25 20:47:29 UTC 2019 : Endpoint response body before transformations: {"errorMessage": "'user'", "errorType": "KeyError", "stackTrace": [" File \"/var/task/lambda_function.py\", line 6, in lambda_handler\n post_user = event[\"user\"]\n"]} Mon Mar 25 20:47:29 UTC 2019 : Lambda execution failed with status 200 due to customer function error: 'user'. Lambda request id: f7955f74-e608-4b10-b216-4e4acf682307 Mon Mar 25 20:47:29 UTC 2019 : Method completed with status: 502

I have defined the API gateway test as follows: enter image description here

3
Why would you put the return statement in a try/except block?Daniel Roseman
there was a bunch of code there but got rid off before posting here. I will remove it to avoid any confusion.Kabard
Just log event and see what you getting, you can use `somedict.get('somekey') for accessing a key without raising an execption. If the key doens't exists it returns Nonegeckos
If you're using proxy integration you'll receive the event with a different structure: docs.aws.amazon.com/apigateway/latest/developerguide/…Tom Melo

3 Answers

2
votes

This is because when the event object comes from API Gateway, it has some extra information on it. It's not as simple as the JSON you use to test from the console.

You need to first access the body object and then finally your JSON object.

Here's how an event from API Gateway looks like:

{
    "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": "'{\"user\":\"john\",\"pwd\":\"pwd1\"}'"
  }

Keep in mind that the body from API Gateway always comes stringified, so if you want to access it, you first need to parse this JSON string using json.loads(event["body"]).

Remember that the body of your response must be Stringified when returning to API Gateway, as we discussed on this answer.

You can see the event sent from API Gateway in the docs

2
votes

@Thales Minussi led me to this answer but the key I'm getting from the response is different than he suggested but his suggestion is what helped me so I'm accepting it as the answer

I was getting this response. The body key is coming as null. but there were queryStringParameters

{
  "resource": "/match_creds",
  "path": "/match_creds",
  "httpMethod": "GET",
  "headers": null,
  "multiValueHeaders": null,
  "queryStringParameters": {
    "pwd": "pwd1",
    "user": "JOHN"
  },
  "multiValueQueryStringParameters": {
    "pwd": [
      "pwd1"
    ],
    "user": [
      "JOHN"
    ]
  },
  "pathParameters": null,
  "stageVariables": null,
  "requestContext": {
    "path": "/match_creds",
    "accountId": "",
    "resourceId": "",
    "stage": "test-invoke-stage",
    "domainPrefix": "testPrefix",
    "requestId": "",
    "identity": {
      "cognitoIdentityPoolId": null,
      "cognitoIdentityId": null,
      "apiKey": "test-invoke-api-key",
      "cognitoAuthenticationType": null,
      "userArn": "",
      "apiKeyId": "test-invoke-api-key-id",
      "userAgent": "",
      "accountId": "",
      "caller": "",
      "sourceIp": "test-invoke-source-ip",
      "accessKey": "",
      "cognitoAuthenticationProvider": null,
      "user": ""
    },
    "domainName": "testPrefix.testDomainName",
    "resourcePath": "/match_creds",
    "httpMethod": "GET",
    "extendedRequestId": "",
    "apiId": ""
  },
  "body": null,
  "isBase64Encoded": false
}

I changed my function to

import json

    def lambda_handler(event, context):

        json_data = event["queryStringParameters"] 
        user = json_data["user"]

        return {
            "statusCode": 200,
            "headers": {"Content-Type": "application/json"},
            "body": json.dumps(user)
            }
0
votes

You needs to activate the setting "Use Lambda Proxy integration" under "Integration Request".