Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass a params from POST to AWS Lambda from Amazon API Gateway

In this question How to pass a querystring or route parameter to AWS Lambda from Amazon API Gateway

shows how to map query string params to AWS lambda using API gateway. I would like to do the same but mapping POST values instead of query-string. I tried:

{
    "values": "$input.params()"
}

but did not work, I don't see the actual form data. BTW I am posting using:

application/x-www-form-urlencoded

I get my response from my lambda function, so I know it is invoking lambda fine, but my problem is that I don't see the POST params anywhere. I can;t figure out how to map them. I dump all I get on Lambda side and here it is:

 {"values":"{path={}, querystring={}, header={Accept=*/*, Accept-Encoding=gzip, deflate, Accept-Language=en-US,en;q=0.8, Cache-Control=no-cache, 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, Content-Type=application/x-www-form-urlencoded, Origin=chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop, Postman-Token=7ba28698-8753-fcb1-1f48-66750ce12ade, Via=1.1 6ba5553fa41dafcdc0e74d152f3a7a75.cloudfront.net (CloudFront), X-Amz-Cf-Id=sc8C7dLcW0BHYopztNYrnddC0hXyFdBzHv0O9aWU1gKhd1D_J2HF3w==, X-Forwarded-For=50.196.93.57, 54.239.140.62, X-Forwarded-Port=443, X-Forwarded-Proto=https}}"}
like image 915
ecorvo Avatar asked Aug 17 '15 18:08

ecorvo


People also ask

How do I pass custom headers via API gateway to a Lambda function using custom Lambda integration?

To pass custom headers from an API Gateway API to a Lambda function, use a body mapping template. The API sends the updated API request to a Lambda function to process the headers. Then, the Lambda function returns one or more header values from the original API request.


Video Answer


4 Answers

Good answer by r7kamura. Additionally Here's an example of an understandable and robust mapping template for application/x-www-form-urlencoded that works for all cases (assuming POST):

{     "data": {         #foreach( $token in $input.path('$').split('&') )             #set( $keyVal = $token.split('=') )             #set( $keyValSize = $keyVal.size() )             #if( $keyValSize >= 1 )                 #set( $key = $util.urlDecode($keyVal[0]) )                 #if( $keyValSize >= 2 )                     #set( $val = $util.urlDecode($keyVal[1]) )                 #else                     #set( $val = '' )                 #end                 "$key": "$val"#if($foreach.hasNext),#end             #end         #end     } } 

It would transform an input of

name=Marcus&email=email%40example.com&message= 

into

{     "data": {                 "name": "Marcus",                 "email": "[email protected]",                 "message": ""     } } 

A Lambda handler could use it like this (this one returns all input data):

module.exports.handler = function(event, context, cb) {   return cb(null, {     data: event.data   }); }; 
like image 108
Marcus Whybrow Avatar answered Sep 21 '22 10:09

Marcus Whybrow


You can convert any request body data into valid JSON format by configuring the mapping templates in the integration settings so that AWS Lambda can receive it.

Currently it seems Amazon API Gateway does not support application/x-www-form-urlencoded officially yet, but avilewin posted a solution to do that on the AWS forums. In the mapping templates you can use Velocity Template Language (VTL), so what you need to do is to configure mapping templates that convert application/x-www-form-urlencoded format into valid JSON format. Of course this is a dirty solution, but I think it's the only way to do that for now.

like image 24
r7kamura Avatar answered Sep 22 '22 10:09

r7kamura


If you enable Lambda Proxy Integration enter image description here

The POST body will be available from:

event['body']['param']

GET parameters and headers will also be available via

event['pathParameters']['param1']
event["queryStringParameters"]['queryparam1']
event['requestContext']['identity']['userAgent']
event['requestContext']['identity']['sourceIP']
like image 45
Jonathan Avatar answered Sep 23 '22 10:09

Jonathan


You can convert the params into JSON with a API gateway template: https://forums.aws.amazon.com/thread.jspa?messageID=673012&tstart=0#673012

Or you may do this in the lambda function itself using QueryString parser pacakge: https://www.npmjs.com/package/qs

var qs = require('qs');
var obj = qs.parse('a=c');  // { a: 'c' } 

If Amazon adds built-in support for such feature, I will use that but until then I personally prefer the second way because it's cleaner and easier to debug if something goes wrong.

Update July 2017:

You may use proxy integration which supports it by default: http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html

like image 35
advncd Avatar answered Sep 20 '22 10:09

advncd