5

I am using apollo-server-lambda for my app. I have create custom authoization http headers and it is required . if authoization: LETMEIN then it will return true and also return all data, if there is no any authoization or wrong authoization then it wll throw an error. For local development I used serverless-offline.In Local environment, it works as expected and here is the image but when I deploy my code to AWS, the api end does not work. It always throws me the error: here is the link.

I test my function AWS console. I am getting this error:

enter image description here

I did not get what I am doing wrong.

Here is my code

/* eslint-disable @typescript-eslint/no-var-requires */
import { ApolloServerPluginLandingPageGraphQLPlayground } from 'apollo-server-core';
import { ApolloServer, AuthenticationError } from 'apollo-server-lambda';
import schema from '../graphql/schema';
import resolvers from '../resolvers';
import runWarm from '../utils/run-warm';

export const authToken = (token: string) => {
  if (token === 'LETMEIN') {
    return;
  } else {
    throw new AuthenticationError('No authorization header supplied');
  }
};

const server = new ApolloServer({
  typeDefs: schema,
  resolvers,
  debug: false,
  plugins: [ApolloServerPluginLandingPageGraphQLPlayground()],
  context: ({ event }) => {
    //console.log(context);

    if (event.headers) {
      authToken(event.headers.authorization);
    }
  },
});

export default runWarm(
  server.createHandler({
    expressGetMiddlewareOptions: {
      cors: {
        origin: '*',
        credentials: true,
        allowedHeaders: ['Content-Type', 'Origin', 'Accept'],
        optionsSuccessStatus: 200,
        maxAge: 200,
      },
    },
  })
);
This is my Lambda function

/**
 * Running warm functions help prevent cold starts
 */
const runWarm =
  (lambdaFunc: AWSLambda.Handler): AWSLambda.Handler =>
  (event, context, callback) => {
    // Detect the keep-alive ping from CloudWatch and exit early. This keeps our
    // lambda function running hot.
    if (event.source === 'serverless-plugin-warmup') {
      return callback(null, 'pinged');
    }
    return lambdaFunc(event, context, callback);
  };

export default runWarm;
Krisna
  • 2,854
  • 2
  • 24
  • 66
  • Unfortunately, I am not familiar with serverless-offline. But my first attempts to run a Lambda locally and firing requests against it showed the same error messages. A Lambda needs the AWS runtime environment and, for example, an HTTP API gateway in front of it, so that the requests hit the Lambda in a suitable form. serverless-offline might help you with that emulating the environment so its probably not configured correctly. – ploth Mar 05 '22 at 10:28

1 Answers1

13

This is not a direct answer, but might help, and could be useful if anyone else (like me) found this thread because of the error "Unable to determine event source based on event" when using apollo-server-lambda.

That error is coming from @vendia/serverless-express which is being used by apollo-server-lambda.

Within serverless-express, in src/event-sources/utils.js, there is a function called getEventSourceNameBasedOnEvent(), which is throwing the error. It needs to find something in the event object, and after a bit of experimentation I found that writing the lambda function like this solved the issue for me:

const getHandler = (event, context) => {
    const server = new ApolloServer({
        typeDefs,
        resolvers,
        debug: true,
    });
    const graphqlHandler = server.createHandler();
    if (!event.requestContext) {
        event.requestContext = context;
    }
    return graphqlHandler(event, context);
}

exports.handler = getHandler;

Note that the context object is added to the event object with the key "requestContext"....that's the fix.

(Also note that I have defined typeDefs and resolvers elsewhere in the code)

I can't guarantee this is the ideal thing to do, but it did work for me.

Simon
  • 265
  • 2
  • 5