somesingsomsing
somesingsomsing

Reputation: 3350

Error when trying access parameters in AWS Python Lambda function using API Gateway

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

Upvotes: 1

Views: 11383

Answers (3)

alpine.lines
alpine.lines

Reputation: 57

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

Upvotes: 1

somesingsomsing
somesingsomsing

Reputation: 3350

@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)
            }

Upvotes: 2

Thales Minussi
Thales Minussi

Reputation: 7215

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

Upvotes: 3

Related Questions