"The action 'execute' could not be found for GraphqlController" when using GraphQL on an API only Rails app?

Viewed 597

I've posted a bug for this on rmosolgo/graphql-ruby but just in case I may be doing something wrong, I'm hoping to see if anyone else has a solution to my problem.

When creating an API only rails application it seems that Rails believes the execute method in my GraphqlController is missing.

Here is my graphql_controller.rb file:

class GraphqlController < ApplicationController
  # If accessing from outside this domain, nullify the session
  # This allows for outside API access while preventing CSRF attacks,
  # but you'll have to authenticate your user separately
  protect_from_forgery with: :null_session

  def execute
    variables = ensure_hash(params[:variables])
    query = params[:query]
    operation_name = params[:operationName]
    context = {
      # Query context goes here, for example:
      # current_user: current_user,
    }
    result = RailsApiGraphqlExecuteTestSchema.execute(query, variables: variables, context: context, operation_name: operation_name)
    render json: result
  rescue => e
    raise e unless Rails.env.development?
    handle_error_in_development e
  end
# ... continues on
end

Here is my routes.rb file:

Rails.application.routes.draw do
  post "/graphql", to: "graphql#execute"
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end

when I run rake routes this is what I get:

prompt> rake routes                                   
                               Prefix Verb   URI Pattern          Controller#Action
                              graphql POST   /graphql(.:format)   graphql#execute
... continues on

You should be able to reproduce this with the following command line steps:

rails new execute-test --api
cd execute-test
vim Gemfile # or open an editor and add "gem 'graphql'"
bundle
rake db:create
rails g graphql:install
rake routes # to test that the route exists
rails s

When you use an app like GraphiQL and go to http://localhost:3000/graphql you'll get the following error:

Started POST "/graphql" for 127.0.0.1 at 2019-10-15 16:23:29 -0700
   (0.3ms)  SELECT sqlite_version(*)

AbstractController::ActionNotFound (The action 'execute' could not be found for GraphqlController):
... strack trace continues ...

Maybe I'm doing something wrong? Any help would be much appreciated.

1 Answers

It looks like this line in the execute method:

protect_from_forgery with: :null_session

is what caused the problem. I'll have to look into this some more. +1 and I'll even mark the answer correct if someone can figure out why this is happening.

Edit: The reason this is happening is because this method assumes you're inheriting from ActionController::Base and not ActionController::API (which doesn't have this method). the API class is supposed to be lighter and therefore doesn't support cookies/sessions out of the box.

Related