Apollo-server: Apollo Server supports only GET/POST requests.

Created on 3 Jun 2017  Â·  17Comments  Â·  Source: apollographql/apollo-server

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

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)

        graphqlPost:
          Type: HttpApi
          Properties:
            PayloadFormatVersion: '1.0'
            Path: /graphql
            Method: post

All 17 comments

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
Was this page helpful?
0 / 5 - 0 ratings