Issue with Introspection Queries with Absinthe & GraphiQL

Hi there,

I created a small project using Absinthe (1.5.3) for some experiments. In this project I’m using only Plug (not Phoenix) and configured a route for the API and one for GraphiGL.

In GraphiQL I’m expecting to see the schema documentation but instead I get an error in the response part of the web interface with the message "syntax error before: \"\\\"query\\\"\"". On the elixir-side it looks ok (no error message etc.).

The setup looks like this:

defmodule Backend.API do
  use Plug.Router

  plug(Plug.Logger)
  plug(:match)
  plug(:dispatch)

  plug(Plug.Parsers,
    parsers: [:urlencoded, :multipart, :json, Absinthe.Plug.Parser],
    pass: ["*/*"],
    json_decoder: Jason
  )

  forward("/api",
    to: Absinthe.Plug,
    init_opts: [schema: Backend.API.Schema]
  )

  forward("/graphiql",
    to: Absinthe.Plug.GraphiQL,
    init_opts: [schema: Backend.API.Schema]
  )

  match _ do
    send_resp(conn, 404, "oops")
  end
end

defmodule Backend.API.Schema do
  use Absinthe.Schema

  import_types(Backend.API.Schema.ContentTypes)

  alias Backend.API.Resolvers

  query do
    @desc "Get all posts"
    field :posts, list_of(:post) do
      resolve(&Resolvers.Content.list_posts/3)
    end
  end
end

defmodule Backend.API.Schema.ContentTypes do
  use Absinthe.Schema.Notation

  object :post do
    field(:id, :id)
    field(:title, :string)
    field(:body, :string)
  end
end

The complete project can be found here: https://github.com/anagromataf/graphql-backend

I guess I’m just missing a step in the basic setup. Any help is appreciated.

In Backend.API you have the Plug.Parsers plug defined after dispatch plug, but dispatch needs the request to be parsed before it will work properly with the handlers that follow. Just move dispatch under Plug.Parsers and it works.

I found the issue. Due to the setup of the plug router, the parsers have no effect when the call is forwarded to “/api”. To fix this, I created a separate plug for the GraphQL API.

defmodule Backend.API.GQL do
  use Plug.Builder

  plug(Plug.Parsers,
    parsers: [:urlencoded, :multipart, :json, Absinthe.Plug.Parser],
    pass: ["*/*"],
    json_decoder: Jason
  )

  plug(Absinthe.Plug,
    schema: Backend.API.Schema
  )
end

defmodule Backend.API do
  # ...

  forward("/api",
    to: Backend.API.GQL
  )

 # ...
end

Now it is working as expected.

You don’t need a separate plug (though that is another way to achieve the same effect), you just need the correct ordering between dispatch and Plug.Parsers :slight_smile:

1 Like

Sometimes the order matters. :wink: