6

I am trying to deploy a google calendar api to AWS Lambda. Since I was facing a problem in extracting the value from the event dictionary (created by lambda from the JSON payload of a POST request), i created a toy function to test

def handler(event,context):
    a=event.get("type")

    if a=='create':
        return {
                "statusCode": 200,
                "headers": { "Content-Type": "text/plain"},
                #"body": "Event_id"+ str(event_identifier) + " Event Link: " +str(links)
                "body" : str(a)
            }
    else:
        return {
                "statusCode": 200,
                "headers": { "Content-Type": "text/plain"},
                #"body": "Event_id"+ str(event_identifier) + " Event Link: " +str(links)
                "body" : "nope"
            }

While testing on the Lambda console with the following JSON, I get the correct response.

Test Payload: { "start_time" : "2018-01-24T09:00:00", "end_time" : "2018-01-24T13:00:00", "type": "create", "event_identifier": "pvno", "summary": "Company", "booking-email": "[email protected]" }

Response:

{
  "body": "create",
  "headers": {
    "Content-Type": "text/plain"
  },
  "statusCode": 200
}

When I send the same payload from postman(binary or body POST) (or test on API gateway console), I get "None" when I return the value from event.get("type").

To explain further, if I try and get the event.get('body') and return it all as a string I get the below, which is incorrect according to how the lambda event should work:

{
  "start_time" : "2018-01-24T09:00:00",
  "end_time" : "2018-01-24T13:00:00",
  "type": "create",
  "event_identifier": "pvnoc",
  "summary": "Company",
  "booking-email": "[email protected]"
}

My questions:

  • What am I doing wrong?
  • How can I get the correct value from the event dictionary?

4 Answers 4

15

When you invoke the lambda locally or through the Lambda console, you are invoking that lambda directly and so your lambda receives exactly what you're sending.

When you invoke it through API Gateway, API Gateway creates the event object for you based on your HTTP request. It adds the HTTP headers, path, query strings, payload, etc.

Here's a summary of what you're getting as an event from an API Gateway invocation:

{
    "resource": "Resource path",
    "path": "Path parameter",
    "httpMethod": "Incoming request's method name"
    "headers": {Incoming request headers}
    "queryStringParameters": {query string parameters }
    "pathParameters":  {path parameters}
    "stageVariables": {Applicable stage variables}
    "requestContext": {Request context, including authorizer-returned key-value pairs}
    "body": "A JSON string of the request payload."
    "isBase64Encoded": "A boolean flag to indicate if the applicable request payload is Base64-encode"
}

Reference: http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html#api-gateway-simple-proxy-for-lambda-input-format

As you can see, the body will be sent to you as a string which you can parse using json.loads().

Sign up to request clarification or add additional context in comments.

Comments

10
  • The request is fully packaged and sent as a single string in the 'body' key of the event dict.
  • This behaviour is different from the test console or invoking from CLI which has only the payload in the event dict meaning event.get('type') works directly.

Example code showing how to access the value of "type" key in payload:

import json

def lambda_handler(event, context):
    body_str = event.get("body", "{}")
    body_str = body_str if body_str else "{}"
    body_obj = json.loads(body_str)
    a = body_obj.get("type", "")

Comments

3

I have a better suggestion to test.
Just return the event that you are receiving in the lambda_handler.

1 Comment

I usually put the function logic in try catch and return the error as json string
0

As said AWS tests Lamda internally, which leads to a solution: you need to use the whole post as AWS get it, you cannot just send some data json as you do with curl.

So, if in doubt, you can fetch the event as Lambda receive it using

import json

def lambda_handler(event, context):

    return { "statusCode": 200, "body": json.dumps(event, indent=2) }

Once saved, this lambda will return the json you'll need to paste into the testing event on AWS Lmbda page.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.