I have a simple API set up in AWS API Gateway. It is set to invoke a Python 2.7 lambda function via API Gateway Proxy integration.
I hit a strange error in that the lambda worked (processed the body correctly and updated a DB) when invoked locally and through the lambda test console, but not through curl or Postman.
Turns out that, when invoked through the lambda test console, the event['body']
object is coming through as a dict
. When called via an HTTP client, it's coming through as a string (Unicode
).
I can work around it of course, but I'd like to understand it, and I'd also prefer a proper Python object. I'd also like to be able to use the lambda test console, but currently I can't as it passes its input differently.
Is there a configuration switch I'm missing which will force API Gateway to serialize the request body (as well as all other params) as a python dict
or proper object? The documentation on the specifics of what is passed is sparse, stating:
event – AWS Lambda uses this parameter to pass in event data to the handler. This parameter is usually of the Python dict type. It can also be list, str, int, float, or NoneType type.
I get that this blurb covers what I'm seeing, but it's not exactly helpful.
Looks like an ability to directly call Lambdas over the Internet without an API Gateway was just added to the SDK. Function URLs are available using the Lambda API and are supported in CloudFormation, AWS SAM and AWS CDK.
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()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With