docker-lambda icon indicating copy to clipboard operation
docker-lambda copied to clipboard

how to test the response of a node lambda

Open dagda1 opened this issue 6 years ago • 18 comments

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.

dagda1 avatar Mar 06 '20 15:03 dagda1

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

mhart avatar Mar 06 '20 15:03 mhart

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

dagda1 avatar Mar 06 '20 16:03 dagda1

You have the same result? Unexpected end of JSON input?

mhart avatar Mar 06 '20 16:03 mhart

yes, unfortunately

dagda1 avatar Mar 06 '20 16:03 dagda1

That 405 is expected – your curl command is making a GET request, not a POST request

mhart avatar Mar 06 '20 16:03 mhart

Are you on windows or something? Try --payload "{}" instead

mhart avatar Mar 06 '20 16:03 mhart

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

dagda1 avatar Mar 06 '20 16:03 dagda1

Can you try with a simpler handler? Does it work on Lambda itself?

mhart avatar Mar 06 '20 16:03 mhart

(and are you sure there's not another docker container already running? I noticed you were using -d for example)

mhart avatar Mar 06 '20 16:03 mhart

no it would not stop with the same port, should I remove -d

dagda1 avatar Mar 06 '20 16:03 dagda1

Just try with a simple handler, like this:

exports.handler = async () => console.log('It works!')

mhart avatar Mar 06 '20 16:03 mhart

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.

dagda1 avatar Mar 09 '20 08:03 dagda1

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

mhart avatar Mar 09 '20 12:03 mhart

@dagda1 how'd you go with this?

mhart avatar May 11 '20 18:05 mhart

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 avatar Jun 28 '20 00:06 lestersm

@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?

mhart avatar Jun 28 '20 01:06 mhart

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

mhart avatar Jun 28 '20 01:06 mhart

Now everything makes sense 😂 . Thank you.

lestersm avatar Jun 28 '20 18:06 lestersm