serverless-plugin-simulate
serverless-plugin-simulate copied to clipboard
fix request body handling in lambda-proxy
What did you implement:
Prior to this, the API Gateway simulator used various content type middlewares for Express to parse request bodies, and then called JSON.stringify on the parsed bodies before invoking the lambda. AWS just passes the body through unchanged as a string in the event JSON. This commit matches AWS' behavior.
How did you implement it:
Used the text
middleware from body-parser
to handle every content type and stopped converting bodies to JSON.
How can we verify it:
- Set up a new project with this
serverless.yml
:
service: form-urlencoded-test
provider:
name: aws
runtime: nodejs6.10
functions:
hello:
handler: handler.hello
events:
- http:
method: post
path: hello
plugins:
- serverless-plugin-simulate
and this handler.js
'use strict';
module.exports.hello = (event, context, callback) => {
const response = {
statusCode: 200,
body: JSON.stringify(event)
}
callback(null, response);
// Use this code if you don't use the http event with the LAMBDA-PROXY integration
// callback(null, { message: 'Go Serverless v1.0! Your function executed successfully!', event });
};
- Install
serverless-plugin-simulate
-
sls deploy
-
curl -X POST -d 'Foo=1&Bar=2' -H "Content-Type: application/x-www-form-urlencoded" https://YOUR_DOMAIN_HERE.amazonaws.com/dev/hello
- You'll see something like this:
{"resource":"/hello","path":"/hello","httpMethod":"POST","headers":{"Accept":"*/*","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","Host":"uyfbhveuki.execute-api.us-east-1.amazonaws.com","User-Agent":"curl/7.55.1","Via":"1.1 af602aaeaac93f5e274192569f593f59.cloudfront.net (CloudFront)","X-Amz-Cf-Id":"pS3ZMRFfozf-0BbnMyv9eTbR5-24Y_soHB1qHAYJ--PWHsdQVGrRRA==","X-Amzn-Trace-Id":"Root=1-5a987d62-6101c83f8c3803b09bcc5a33","X-Forwarded-For":"24.20.238.167, 52.46.16.78","X-Forwarded-Port":"443","X-Forwarded-Proto":"https"},"queryStringParameters":null,"pathParameters":null,"stageVariables":null,"requestContext":{"requestTime":"01/Mar/2018:22:23:31 +0000","path":"/dev/hello","accountId":"299718914046","protocol":"HTTP/1.1","resourceId":"uer9jx","stage":"dev","requestTimeEpoch":1519943011000,"requestId":"2bfff394-1d9f-11e8-83b7-f796fce58c28","identity":{"cognitoIdentityPoolId":null,"accountId":null,"cognitoIdentityId":null,"caller":null,"sourceIp":"24.20.238.167","accessKey":null,"cognitoAuthenticationType":null,"cognitoAuthenticationProvider":null,"userArn":null,"userAgent":"curl/7.55.1","user":null},"resourcePath":"/hello","httpMethod":"POST","apiId":"uyfbhveuki"},"body":"Foo=1&Bar=2","isBase64Encoded":false}
- Note that
body
in there is the original string we POSTed. -
sls simulate apigateway
- same curl command:
curl -X POST -d 'Foo=1&Bar=2' -H "Content-Type: application/x-www-form-urlencoded" http://localhost:3000/hello
- Prior to this commit, you'll get
{"path":"/hello","headers":{"host":"localhost:3000","user-agent":"curl/7.55.1","accept":"*/*","content-type":"application/x-www-form-urlencoded","content-length":"11"},"pathParameters":{},"requestContext":{"accountId":"localContext_accountId","resourceId":"localContext_resourceId","stage":"dev","requestId":"localContext_requestId_24394999491022662","identity":{"cognitoIdentityPoolId":"localContext_cognitoIdentityPoolId","accountId":"localContext_accountId","cognitoIdentityId":"localContext_cognitoIdentityId","caller":"localContext_caller","apiKey":"localContext_apiKey","sourceIp":"::ffff:127.0.0.1","cognitoAuthenticationType":"localContext_cognitoAuthenticationType","cognitoAuthenticationProvider":"localContext_cognitoAuthenticationProvider","userArn":"localContext_userArn","userAgent":"curl/7.55.1","user":"localContext_user"}},"resource":"localContext_resource","httpMethod":"POST","queryStringParameters":{},"body":"{\"Foo\":\"1\",\"Bar\":\"2\"}","stageVariables":{}}
. After it,body
will match Amazon's output.
Todos:
- [x] Write tests - It'd be nice if there were an easy way to test the Express routing automatically, but I added a test for the lambda-proxy integration at least
- [x] Write documentation - bugfix
- [x] Fix linting errors
- [x] Provide verification config/commands/resources
- [x] Change ready for review message below
Is this ready for review?: YES
Huh, somehow I pushed the wrong code. Should work now.