fastify / aws-lambda-fastify

Insipired by aws-serverless-express to work with Fastify with inject functionality.
MIT License
501 stars 32 forks source link

Doesn't work on a deployed lambda function #21

Closed hakimio closed 5 years ago

hakimio commented 5 years ago

While it seems to work fine when testing locally with sls offline, trying to run it on a deployed lambda function with API Gateway, I am getting the following error:

{
    "errorType": "TypeError",
    "errorMessage": "Cannot convert undefined or null to object",
    "stack": [
        "TypeError: Cannot convert undefined or null to object",
        "    at Function.keys (<anonymous>)",
        "    at getName (/var/task/_optimize/dev-main/src/lambda.js:17374:23)",
        "    at new Plugin (/var/task/_optimize/dev-main/src/lambda.js:17398:15)",
        "    at new Boot (/var/task/_optimize/dev-main/src/lambda.js:16259:16)",
        "    at Boot (/var/task/_optimize/dev-main/src/lambda.js:16211:22)",
        "    at build (/var/task/_optimize/dev-main/src/lambda.js:43616:17)",
        "    at bootstrapServer (/var/task/_optimize/dev-main/src/lambda.js:11:343)",
        "    at Runtime.exports.handler (/var/task/_optimize/dev-main/src/lambda.js:11:617)",
        "    at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)",
        "    at process._tickCallback (internal/process/next_tick.js:68:7)"
    ]
}

To Reproduce

Here is the lambda.ts file used to bootstrap the app:

import {NestFactory} from '@nestjs/core';
import {FastifyAdapter, NestFastifyApplication} from '@nestjs/platform-fastify';
import {AppModule} from './app.module';
import * as fastify from 'fastify';
import * as awsLambdaFastify from 'aws-lambda-fastify';
import {
    Context,
    APIGatewayProxyEvent,
    APIGatewayProxyResult
} from 'aws-lambda';
import { Logger } from '@nestjs/common';

interface NestApp {
    app: NestFastifyApplication;
    instance: fastify.FastifyInstance;
}

let cachedNestApp: NestApp;

async function bootstrapServer(): Promise<NestApp> {
    const serverOptions: fastify.ServerOptionsAsHttp = {
        logger: true,
    };
    const instance: fastify.FastifyInstance = fastify(serverOptions);
    const app = await NestFactory.create<NestFastifyApplication>(
        AppModule,
        new FastifyAdapter(instance),
        {
            logger: !process.env.AWS_EXECUTION_ENV ? new Logger() : console
        }
    );
    app.setGlobalPrefix(process.env.API_PREFIX);
    await app.init();

    return {
        app,
        instance
    };
}

export const handler = async (
    event: APIGatewayProxyEvent,
    context: Context,
): Promise<APIGatewayProxyResult> => {
    if (!cachedNestApp) {
        cachedNestApp = await bootstrapServer();
    }
    const proxy = awsLambdaFastify(cachedNestApp.instance);

    return proxy(event, context);
};

And here is serverless.yml:

service:
  name: my-service

plugins:
  - serverless-plugin-typescript
  - serverless-plugin-optimize
  - serverless-offline

custom:
  stage: ${opt:stage, self:provider.stage}
  common: ${file(../serverless/common.yml):${self:custom.stage}}

provider:
  name: aws
  runtime: nodejs10.x
  region: ${self:custom.common.REGION}
  environment:
    API_PREFIX: "${self:custom.common.API_PREFIX}"

functions:
  main:
    handler: src/lambda.handler
    events:
      - http:
          method: any
          path: ${self:custom.common.API_PREFIX}/{proxy+}

Expected behavior

To work without errors.

Your Environment

hakimio commented 5 years ago

And running sls invoke local --function main --data 'JSON data posted below' with the following data results in the same error:

{
  "body": "eyJ0ZXN0IjoiYm9keSJ9",
  "resource": "/{proxy+}",
  "path": "/path/to/resource",
  "httpMethod": "POST",
  "isBase64Encoded": true,
  "queryStringParameters": {
    "foo": "bar"
  },
  "pathParameters": {
    "proxy": "/path/to/resource"
  },
  "stageVariables": {
    "baz": "qux"
  },
  "headers": {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
    "Accept-Encoding": "gzip, deflate, sdch",
    "Accept-Language": "en-US,en;q=0.8",
    "Cache-Control": "max-age=0",
    "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",
    "Host": "1234567890.execute-api.eu-central-1.amazonaws.com",
    "Upgrade-Insecure-Requests": "1",
    "User-Agent": "Custom User Agent String",
    "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)",
    "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==",
    "X-Forwarded-For": "127.0.0.1, 127.0.0.2",
    "X-Forwarded-Port": "443",
    "X-Forwarded-Proto": "https"
  },
  "requestContext": {
    "accountId": "123456789012",
    "resourceId": "123456",
    "stage": "prod",
    "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
    "requestTime": "09/Apr/2015:12:34:56 +0000",
    "requestTimeEpoch": 1428582896000,
    "identity": {
      "cognitoIdentityPoolId": null,
      "accountId": null,
      "cognitoIdentityId": null,
      "caller": null,
      "accessKey": null,
      "sourceIp": "127.0.0.1",
      "cognitoAuthenticationType": null,
      "cognitoAuthenticationProvider": null,
      "userArn": null,
      "userAgent": "Custom User Agent String",
      "user": null
    },
    "path": "/prod/path/to/resource",
    "resourcePath": "/{proxy+}",
    "httpMethod": "POST",
    "apiId": "1234567890",
    "protocol": "HTTP/1.1"
  }
}

Can you test to see if the error is on my end or on "aws-lambda-fastify"?

hakimio commented 5 years ago

The issue seems to be with "serverless-plugin-optimize" + "serverless-plugin-typescript". Optimize plugin messes up the deployment package. Feel free to close this if you want.

hakimio commented 5 years ago

Also, it seems when using "express" with "aws-serverless-express", optimize plugin works fine, but when fastify is used with any adapter (aws-lambda-fastify, serverless-http or aws-serverless-fastify), optimize plugin generates messed-up deployment package.

adrai commented 5 years ago

Sorry not using typescript or serverless framework, but native javascript an cloudformation. I can't reproduce it with your json data... Can you provide a reproducable test here: https://github.com/fastify/aws-lambda-fastify/tree/master/test ?

hakimio commented 5 years ago

@adrai Would it be ok if I just made a github repo showing the issue?

adrai commented 5 years ago

ok.... any help is welcome

hakimio commented 5 years ago

@adrai I've created a new repository for you with two branches:

Just run yarn install and yarn run test:sls to reproduce the issue.

adrai commented 5 years ago

Seems aws-lambda-fastify is not causing this issue... It crashes here: https://github.com/hakimio/nest-serverless/blob/fastify/src/app.ts#L19 So even if you just call fastify() it crashes exactly the same... (you don't even have to require aws-lambda-fastify) I'm really sorry, but I have no clue about typescript, perhaps @mcollina or @delvedor may help?

hakimio commented 5 years ago

That's ok. Feel free to close this issue.

hakimio commented 5 years ago

Since it's an issue with serverless-plugin-optimize and is not caused by aws-lambda-fastify or fastify itself, I've created a bug report in serverless-plugin-optimize github page. Thanks for taking the time to look into this.