how to test the response of a node lambda
I have this index.js file:
const serverless = require('serverless-http');
const express = require('express');
const app = express();
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.get('/', (req, res) => {
res.status(200).send({ application: 'sample-app', version: '1' });
});
module.exports.handler = serverless(app);
Which I run with
docker run --rm -d \
-e DOCKER_LAMBDA_STAY_OPEN=1 \
-p 9001:9001 \
-v "$PWD":/var/task \
--name no \
lambci/lambda:nodejs12.x \
index.handler '{\"some\": \"event\"}'
I then try and call it with:
aws lambda invoke --endpoint http://localhost:9001/ --no-sign-request \
--function-name index --payload '{}' output.json
I get this response:
{
"StatusCode": 200,
"FunctionError": "Unhandled",
"ExecutedVersion": "$LATEST"
}
if I look at output.json, I see this:
{"errorType":"SyntaxError","errorMessage":"Unexpected end of JSON input"}
I can't tell what I am doing wrong.
Don't start with '{\"some\": \"event\"}' (just leave it out) – you're running in stay open mode, so you'll be passing in a new event each time via the API
thank you for the reply but even with that removed, I have the same result.
docker run --rm -d \
-e DOCKER_LAMBDA_STAY_OPEN=1 \
-p 9001:9001 \
-v "$PWD":/var/task \
--name no \
lambci/lambda:nodejs12.x \
index.handler
I notice if I curl the function with:
curl -i -v http://localhost:9001/2015-03-31/functions/index/invocations
I get this response
405 - Method Not Allowed
You have the same result? Unexpected end of JSON input?
yes, unfortunately
That 405 is expected – your curl command is making a GET request, not a POST request
Are you on windows or something? Try --payload "{}" instead
I'm not on windows, but osx and I have the same result with
aws lambda invoke \
--endpoint http://localhost:9001/ \
--no-sign-request \
--function-name index \
--payload "{}" response.json
Can you try with a simpler handler? Does it work on Lambda itself?
(and are you sure there's not another docker container already running? I noticed you were using -d for example)
no it would not stop with the same port, should I remove -d
Just try with a simple handler, like this:
exports.handler = async () => console.log('It works!')
Hi,
I have changed the handler to the above and running this command
gives this error message in the logs
Lambda API listening on port 9001... START RequestId: 3368a620-6dd6-138c-3185-9807c8870b0c Version: $LATEST 2020-03-09T07:55:44.562Z 3368a620-6dd6-138c-3185-9807c8870b0c ERROR Invoke Error {"errorType":"SyntaxError","errorMessage":"Unexpected end of JSON input","stack":["SyntaxError: Unexpected end of JSON input"," at JSON.parse (
)"," at Runtime.handleOnce (/var/runtime/Runtime.js:67:14)"]} END RequestId: 3368a620-6dd6-138c-3185-9807c8870b0c REPORT RequestId: 3368a620-6dd6-138c-3185-9807c8870b0c Init Duration: 112.03 ms Duration: 9.41 ms Billed Duration: 100 ms Memory Size: 1536 MB Max Memory Used: 39 MB
So it seems no matter what the handler is, it gives this error:
/var/runtime/Runtime.js:67 Unexpected end of JSON input
aws lambda invoke \
--endpoint http://localhost:9001/ \
--no-sign-request \
--function-name index \
response.json
Looking at Runtime.js it appears to be this code:
let result = this.handler(
JSON.parse(bodyJson),
invokeContext.attachEnvironmentData(callbackContext),
callback
);
if (_isPromise(result)) {
result
.then(callbackContext.succeed, callbackContext.fail)
.catch(callbackContext.fail);
So the bodyJson which is returned from let { bodyJson, headers } = await this.client.nextInvocation(); is not JSON for some reason.
Where does this Runtime.js file exist?
The error happens before the handler gets called.
It doesn't look like you're passing a payload in that last comment.
You can try just invoking it with curl to remove the AWS CLI as a factor – you can see an example in the README: https://github.com/lambci/docker-lambda#running-in-stay-open-api-mode
@dagda1 how'd you go with this?
I just found something that may help. I believe it may be related to v2 of aws cli. I'm running lambda with:
docker run --rm -e DOCKER_LAMBDA_WATCH=1 -e DOCKER_LAMBDA_STAY_OPEN=1 -p 9001:9001 -v "$PWD":/var/task:ro,delegated lambci/lambda:nodejs12.x index.handler
Then call it with:
aws lambda invoke --endpoint http://localhost:9001 --cli-binary-format raw-in-base64-out --function-name handler --payload file://myjson.json output.json
I'm using --payload file://myjson.json because I want to change the content easily.
and my function is handler
output:
{
"StatusCode": 200,
"ExecutedVersion": "$LATEST"
}
Ref: https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/invoke.html#examples
@lestersm that's an excellent point – AWS CLI v2 changed the way it deals with payloads. https://docs.aws.amazon.com/cli/latest/userguide/cliv2-migration.html#cliv2-migration-binaryparam
@dagda1 were you using AWS CLI v2 by any chance?
I added that to the README a while back btw: https://github.com/lambci/docker-lambda#running-in-stay-open-api-mode
If that solves your problem, then I'll close this issue as solved
Now everything makes sense 😂 . Thank you.