I have a test server set up and when I try make a request to it, I get the error Apollo Server supports only GET/POST requests. I am testing locally using serverless online
Hi @solemidas. It may have to do with CORS, but it's a bit difficult to help you with this little information. I also think you'll be more likely to get an answer on the Apollo Slack channel or on stackoverflow, so I'll close the issue here! 🙂
Thanks, I found a way around it, the graphql-server-lambda uses event.httpMethod while the event uses event.method
@solemidas how exactly did you resolve this issue? I am running into the same issue after I deployed my api to aws.
export const graphqlHandler = (event, context, callback) =>
server.graphqlLambda({ schema, debug: true })(
{ ...event, httpMethod: event.method },
context,
callback
);
I was finally able to deploy to aws. My handler looks like this
serverless.yml
functions:
graphql:
handler: handler.graphqlHandler
events:
- http:
path: graphql
method: post
cors: true
handler.js
exports.graphqlHandler = function graphqlHandler(event, context, callback) {
function callbackFilter(error, output) {
// eslint-disable-next-line no-param-reassign
output.headers['Access-Control-Allow-Origin'] = '*';
context.succeed(output);
}
const handler = graphqlLambda({ schema, debug: true });
return handler( event, context, callbackFilter);
};
I wanted to add my solution. My situation is a little different; I'm not sure if that matters here. I am running on Google Cloud Functions, without using Serverless.
yarn add cors
export const api = express().use(
'/graphql', cors(), bodyParser.json(), graphqlExpress({schema, context: {}}),
);
So, basically, I'm using the cors package. Credit goes to this SO answer.
@crs2here i am having some problems but i have the same exact code you have since i am using the graphql serverless boilerplate from october. But i get the following error (it works locally).
Failed to load https://XXXXX.execute-api.us-west-1.amazonaws.com/production/graphql: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://XXX.XXX' is therefore not allowed access. The response had HTTP status code 502. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
I am using HTTPS for my app, so I added
exports.graphqlHandler = function graphqlHandler(event, context, callback) {
function callbackFilter(error, output) {
// eslint-disable-next-line no-param-reassign
output.headers['Access-Control-Allow-Origin'] = '*';
output.headers['Access-Control-Allow-Credentials'] = 'true';
callback(error, output);
}
My YAML looks like this for my app-backend
functions:
graphql:
handler: handler.graphqlHandler
events:
- http:
path: graphql
method: post
cors: true
api:
handler: handler.apiHandler
events:
- http:
path: api
method: get
cors: true
@kvreem I sincerely apologize for taking so long on getting back to you. I don't know if this will help but here are the full files I used
serverless.yml
service: *****
frameworkVersion: ">=1.21.0 <2.0.0"
provider:
name: aws
runtime: nodejs6.10
stage: production
region: us-west-1
plugins:
- serverless-offline
- serverless-webpack
custom:
serverless-offline:
port: 4000
babelOptions:
presets: ["es2015", "stage-2"]
webpackIncludeModules: true
functions:
graphql:
handler: handler.graphqlHandler
events:
- http:
path: graphql
method: post
cors: true
handler.js
'use strict'; // eslint-disable-line strict,lines-around-directive
console.info("loading function");
import { makeExecutableSchema } from 'graphql-tools';
import { typeDefs } from './graphql/schema';
import { resolvers } from './graphql/resolvers';
const { graphqlLambda } = require('apollo-server-lambda');
const schema = makeExecutableSchema({
typeDefs,
resolvers,
logger: console,
});
exports.graphqlHandler = function graphqlHandler(event, context, callback) {
function callbackFilter(error, output) {
// eslint-disable-next-line no-param-reassign
output.headers['Access-Control-Allow-Origin'] = '*';
context.succeed(output);
}
const handler = graphqlLambda({ schema, debug: true });
return handler( event, context, callbackFilter);
};
here is my webpack config
const path = require('path');
// eslint-disable-next-line import/no-extraneous-dependencies
const nodeExternals = require('webpack-node-externals');
// eslint-disable-next-line import/no-extraneous-dependencies
const slsw = require('serverless-webpack');
module.exports = {
entry: slsw.lib.entries,
target: 'node',
externals: [nodeExternals()],
module: {
rules: [
{
test: /\.js$/,
use: [
'imports-loader?graphql',
{
loader: 'babel-loader',
options: {
presets: ["es2015", "react", "stage-0"],
},
},
],
},
],
},
output: {
libraryTarget: 'commonjs',
path: path.join(__dirname, '.webpack'),
filename: '[name].js',
},
};
@crs2here thanks! I will take a look. Just a quick question
context.succeed(output); what is significant about that line? Why is it needed/ what does it do vs using callback(error, output);?
I struggled through this for about a month, and I came across this link http://davin.ninja/using-aws-lambda-with-amazon-api-gateway/ on this issue https://github.com/serverless/serverless-graphql/issues/94 it was a comment by @joshhornby. I apologize for not being more clear but I think it has to do with API gateway configuration.
Hi, I'm running into the exact same issue, but I am using apollo-server-lambda 2.3.1
Here is my code:
//graphql.js
const {ApolloServer, gql} = require('apollo-server-lambda');
const typeDefs = gql`
type Query {
hello: String
}
`;
const resolvers = {
Query: {
hello: () => 'The API is Alive!!'
},
};
const server = new ApolloServer({
typeDefs,
resolvers,
formatError: error => {
console.log(error);
return error;
},
formatResponse: response => {
console.log(response);
return response;
},
context: ({event,context}) => ({
headers: event.headers,
functionName: context.functionName,
event,
context,
}),
tracing: true
});
exports.graphqlHandler = (event,context,callback) =>{
const handler = server.createHandler({
cors: {
origin: '*',
methods: [
'POST',
'GET'
],
allowedHeaders: [
'Content-Type',
'Origin',
'Accept'
]
},
}) ;
return handler(event, context,callback);
};
Any thoughts on what could be the issue?
Anyone fixed this?
Yo @WarunaS ,
This happened to me when I would invoke my Lambda like so : sls invoke local -f function_name
What you want to do instead is run: sls offline which will run GraphQL Playgroud on a localhost port.
Make sure you have serverless-offline installed.
I have made a template for scaffolding Serverless GraphQL APIs here.
Thanks @AmoDinho. This occurs when I try to use 'integration: lambda' in serverless.yml. Once I remove it, works fine.
The reason why I added 'integration: lambda' is, I'm getting below error in cloudwatch:
{
"errorType": "TypeError",
"errorMessage": "Cannot read property ‘Accept’ of null",
"trace": [
"TypeError: Cannot read property ‘Accept’ of null",
" at fileUploadHandler (/var/task/node_modules/apollo-server-lambda/dist/ApolloServer.js:143:50)",
" at Runtime.handler (/var/task/node_modules/apollo-server-lambda/dist/ApolloServer.js:166:13)",
" at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)"
]
}
@WarunaS I see bruv, normally integration: lambda-proxy should get you out of trouble.
Check out the Serverless docs for more info, for next time 🤙
I decided to try out AWS's HTTP API Gateway (was using REST), turns out the event payload doesn't carry the httpMethod, it's now in event.requestContext.http.method. This post helped me get there, I'm hoping if somebody tries the same and hits that WTF moment - there ya go. A quick hack ahead of creating the handler:
//workaround for HTTP API change (missing httpMethod)
if (event.httpMethod == undefined)
event.httpMethod = event.requestContext.http.method;
@texascj
This was helpful you can also change the HttpApi payload format version back to 1.0.
SAM template (should be similar for serverless)
graphqlPost:
Type: HttpApi
Properties:
PayloadFormatVersion: '1.0'
Path: /graphql
Method: post
Most helpful comment
@texascj
This was helpful you can also change the HttpApi payload format version back to 1.0.
SAM template (should be similar for serverless)