Intended Outcome: To deploy an apollo-server to AWS Lambda based off the example provided in the Apollo docs, here is my code below:
//graphql.js
const {ApolloServer, gql} = require('apollo-server-lambda');
const typeDefs = gql`
type Query {
hello: String
}
`;
const resolvers = {
Query: {
hello: () => 'Zansi is Alive!!'
},
};
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({event,context}) => ({
headers: event.headers,
functionName: context.functionName,
event,
context,
}),
});
exports.graphqlHandler = server.createHandler({
cors: {
origin: '*',
methods: 'POST',
allowHeaders: [
'Content-Type',
'Origin',
'Accept'
]
},
});
Operating System: Windows 10
Yarn Version: 1.1.0
Dependencies: apollo-server-lambda: "^2.3.1"
Actual outcome: when I invoke the function locally or deploy it I get the following response:
{
"body": "Apollo Server supports only GET/POST requests.",
"statusCode": 405,
"headers": {
"Allow": "GET, POST",
"Access-Control-Allow-Methods": "POST",
"Access-Control-Allow-Headers": "Content-Type,Origin,Accept",
"Access-Control-Allow-Origin": "*"
}
}
How to reproduce: Run the following in your terminal:
$ serverless install --url https://github.com/AnomalyInnovations/serverless-nodejs-starter --name my-project
then run npm install and after that install apollo-server-lambda. Create a graphql.js file and copy the code above into it.
Then run:
serverless invoke local --function graphql
Any help would be greatly appreciated.
Apologies, I was invoking the function locally like a REST API.
For anyone who encounters a similar problem, make sure to run : $ sls offline and playground should open at localhost://3000.
Furthermore, when you deploy you might run into an error message saying "missing authentication token", to solve this make sure your serverless.yml for the functions part looks something like this:
functions:
graphql:
handler: graphql.graphqlHandler
environment:
SLS_DEBUG: true
events:
- http:
path: graphql
method: post
cors: true
integration: lambda-proxy
- http:
path: graphql
method: get
cors: true
integration: lambda-proxy
Reason being is that API Gateway does not have access to your URL's stage and resources it is using.
What I found confusing is that for me this "apollo-server-lambda" and the ".createHandler(...)" thing looked like it could really do lambda.invoke() calls with it but instead it assumes HTTP requests.
In order to use lambda.invoke, like you would for example if you try to use apollo-link-lambda, you have to do something like this:
const handler = server.createHandler();
export const lambdaHandler = (event, context, callback) => {
event.httpMethod = event.httpMethod || "POST";
event.headers = {
"content-type": "application/json",
...(event.headers ||聽{}),
};
if(!event.body && event.query){
event.body = JSON.stringify({
query: event.query,
variables: event.variables
});
}
return handler(event, context, (er, res) => {
if(res){
callback(er, res.body);
}
else{
callback(er, res);
}
});
}
This way you make a HTTP event out of the raw lambda-invoke and return the body of the HTTP body as Payload back to the calling lambda.invoke.
Most helpful comment
Apologies, I was invoking the function locally like a REST API.
For anyone who encounters a similar problem, make sure to run :
$ sls offlineand playground should open atlocalhost://3000.Furthermore, when you deploy you might run into an error message saying "missing authentication token", to solve this make sure your
serverless.ymlfor the functions part looks something like this:Reason being is that API Gateway does not have access to your URL's stage and resources it is using.