Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolve promise before registering middleware and exposing routes #351

Closed
matt-mcdaniel opened this issue Jan 27, 2021 · 8 comments
Closed
Labels

Comments

@matt-mcdaniel
Copy link

I need to fetch a secret from a secrets manager using an async request to use for my middleware, but I find that I get no response or a timed out one when I try and wrap my middleware and routes in a promise chain.

getSecret().then(secret => {
  const strategy = new OAuth2Strategy({
    secret: secret
  }, function (accessToken, refreshToken, params, profile, done) {
    done(null,{data: 'some user data'});
  })


  passport.use('oauth2', strategy);
  refresh.use('oauth2', strategy);

  app.get('/my_route', async function (req, res) {
    ...
  })
})

What is the best way to deal with async code that needs to be resolved before I expose my routes?

@brettstack
Copy link
Collaborator

brettstack commented Jan 27, 2021

I'll need a more complete example to help with this. What's your lambda handler look like? You'll need something like:

let serverlessExpressHandler

const getAppPromise = getApp().then(app => {
  serverlessExpressHandler = serverlessExpress({ app }).handler
})

exports.handler = async (event, context) => {
  if (!serverlessExpressHandler) {
    await getAppPromise 
  }

  return serverlessExpressHandler(event, context)
}

@matt-mcdaniel
Copy link
Author

Thanks @brettstack, I'm trying to understand how to return the app as a promise so that I can fetch my secret. Take the following for example:

If I have, as you suggested, for my lambda.js

const getApp = require('./app');

let serverlessExpressHandler

const getAppPromise = getApp().then(app => {
  serverlessExpressHandler = serverlessExpress({ app }).handler
})

exports.handler = async (event, context) => {
  if (!serverlessExpressHandler) {
    await getAppPromise 
  }

  return serverlessExpressHandler 
}

and for my app.js I have exported a function that returns a promise

module.exports = () => {
    return new Promise((resolve, reject) => {
        const app = express();

        app.get('/', (req, res) => {...})
        
        resolve(app)
    })
}

This configuration gives me the following error:

{
    "errorType": "TypeError",
    "errorMessage": "Wrong arguments",
    "stack": [
        "TypeError: Wrong arguments",
        "    at RAPIDClient.postInvocationResponse (/var/runtime/RAPIDClient.js:46:23)",
        "    at complete (/var/runtime/CallbackContext.js:33:12)",
        "    at done (/var/runtime/CallbackContext.js:58:7)",
        "    at succeed (/var/runtime/CallbackContext.js:62:5)",
        "    at /var/runtime/CallbackContext.js:104:16"
    ]
}

What am I missing here? Are there any examples that show a full example of what you posted above?

@brettstack
Copy link
Collaborator

brettstack commented Jan 27, 2021

Sorry, that should be return serverlessExpressHandler(event, context). I don't have any complete examples though I recall seeing some Issues here with comments doing similar things. Definitely a common/valid use case that I should add an example for.

@smasilamani-cfins
Copy link

May I know how do we use this new version with NestJS. Please note that I am in no hurry to use latest version but I would like to give it a try but facing issue.

import { createServer, proxy } from '@vendia/serverless-express';
import { Handler } from 'aws-lambda';
import Express from 'express';
import { Server } from 'http';

import { INestApplication } from '@nestjs/common';
import { ExpressAdapter } from '@nestjs/platform-express';

const bootstrapServer: () => Promise<Server> = async () => {
	try {
		const expressApp: any = Express();
		const expAdapter: ExpressAdapter = new ExpressAdapter(expressApp);
		const app: INestApplication = await bootstrap(expAdapter);
		return createServer(app.getHttpAdapter().getInstance(), null, binaryMimeTypes);
	} catch (error) {
		// eslint-disable-next-line no-console
		console.error(error);
		throw error;
	}
};

export const handler: Handler = async (event, context) => {
	context.callbackWaitsForEmptyEventLoop = true;

	if (event.path === `/${DSServerConstants.GLOBAL_PATH_PREFIX}`) {
		event.path = `/${DSServerConstants.GLOBAL_PATH_PREFIX}/`;
	}

	event.path = event.path?.includes('swagger-ui') ? `/${DSServerConstants.GLOBAL_PATH_PREFIX}${event.path}` : event.path;
	if (!cachedServer) {
		cachedServer = await bootstrapServer();
	}
	if (event.source === 'serverless-plugin-warmup') {
		const response: {
			statusCode: number;
			body: any;
			headers: any;
		} = {
			statusCode: 200,
			body: null,
			headers: null
		};
		response.body = 'WarmUP - Lambda is warm!';
		// eslint-disable-next-line no-console
		console.log('index - Lambda is warm!');
		return response;
	}

	if (process.env.APP_ENV?.toUpperCase() !== DSServerConstants.LOCAL_ENV) {
		handleCustomDomanin(event);
	}
	return proxy(cachedServer, event, context, 'PROMISE').promise;
};

But now I am getting errors as below

Module '"../node_modules/@vendia/serverless-express/src"' has no exported member 'createServer'

Module '"../node_modules/@vendia/serverless-express/src"' has no exported member 'proxy'

This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export.ts(2497)

@brettstack
Copy link
Collaborator

Please see https://github.com/vendia/serverless-express/blob/mainline/UPGRADE.md for info on upgrading. I haven't tested with Nest. Let me know if you hit any issues. If you could send a PR with a minimum Nest example, that'd be great!

@smasilamani-cfins
Copy link

Please see https://github.com/vendia/serverless-express/blob/mainline/UPGRADE.md for info on upgrading. I haven't tested with Nest. Let me know if you hit any issues. If you could send a PR with a minimum Nest example, that'd be great!

Will definitely do by end of this week.

@smasilamani-cfins
Copy link

Please see https://github.com/vendia/serverless-express/blob/mainline/UPGRADE.md for info on upgrading. I haven't tested with Nest. Let me know if you hit any issues. If you could send a PR with a minimum Nest example, that'd be great!

Will definitely do by end of this week.

I see that you already have NestJS example.

@brettstack
Copy link
Collaborator

Yes we just merged this a few days ago. Let me know if you have any other issues. I'll close this issue for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants