AWS Lambda function to integrate with Express from AWS API Gateway
Install with npm install --save lambda-express
var lambdaExpress = require('lambda-express');
var express = require('express');
var app = express();
// ... initialize the app as usual ...
// create a handler function that maps lambda inputs to express
exports.handler = lambdaExpress.appHandler(app);
// or, if you want to do some preprocessing before delegating, pass a function in:
exports.handler = lambdaExpress.appHandler(function(event,context) {
// ... do some cool stuff here ...
return app;
});
The request expects the following attributes in the event:
event['queryString'] = 'name=value&foo=bar'; // query string from URL
event['headers'] = '{key1=val1, key2=val2}'; // string with header values from API Gateway
event['user-agent'] = '...'; // string with user agent
event['source-ip'] = '...'; // string with source ip for request
event['api-id'] = '...'; // id of the api in API Gateway
event['pathParams'] = '{key1=val1, key2=val2}'; // list of path param values
event['http-method'] = '...'; // http request method
event['resource-path'] = '...'; // the path for the API Gateway path
In API Gateway, this is accomplished with the following integration request mapping template:
{
"stage": "$context.stage",
"request-id": "$context.requestId",
"api-id": "$context.apiId",
"resource-path": "$context.resourcePath",
"resource-id": "$context.resourceId",
"http-method": "$context.httpMethod",
"source-ip": "$context.identity.sourceIp",
"user-agent": "$context.identity.userAgent",
"account-id": "$context.identity.accountId",
"api-key": "$context.identity.apiKey",
"caller": "$context.identity.caller",
"user": "$context.identity.user",
"user-arn": "$context.identity.userArn",
"queryString": "$input.params().querystring",
"headers": "$input.params().header",
"pathParams": "$input.params().path",
"allParams": "$input.params()"
}
On success, the following data structure is returned to Lambda:
{
contentType: '', // string with Content-Type header from express response
payload: '' // base64 encoded string of the output from express response
}
In API Gateway, this is handled with an integration response mapping template of:
$util.base64Decode( $input.path('$.payload') )
And a header mapping for Content-Type
of integration.response.body.contentType
If you want more headers on the return request, then add a responseHeaders
key
to the integration request mapping, separating headers by a :
. For example:
...
"pathParams": "$input.params().path",
"allParams": "$input.params()",
"responseHeaders": "Set-Cookie:X-Custom-Header"
Remember, don't forget the ,
. Then do the same as you did for Content-Type in the
header mapping, e.g. integration.response.body.Set-Cookie
.