Current section
Files
Jump to
Current section
Files
lib/graphql/plug/graphiql.ex
defmodule GraphQL.Plug.GraphiQL do
@moduledoc """
This is the GraphiQL plug for mounting a GraphQL server.
You can build your own pipeline by mounting the
`GraphQL.Plug.GraphiQL` plug directly.
```elixir
forward "/graphql", GraphQL.Plug.GraphiQL, schema: {MyApp.Schema, :schema}
```
You may want to look at how `GraphQL.Plug` configures its pipeline.
Specifically note how `Plug.Parsers` are configured, as this is required
for pre-parsing the various POST bodies depending on `content-type`.
"""
import Plug.Conn
alias Plug.Conn
alias GraphQL.Plug.Endpoint
@behaviour Plug
@graphiql_version "0.6.1"
@graphiql_instructions """
# Welcome to GraphQL Elixir!
#
# GraphiQL is an in-browser IDE for writing, validating, and
# testing GraphQL queries.
#
# Type queries into this side of the screen, and you will
# see intelligent typeaheads aware of the current GraphQL type schema and
# live syntax and validation errors highlighted within the text.
#
# To bring up the auto-complete at any point, just press Ctrl-Space.
#
# Press the run button above, or Cmd-Enter to execute the query, and the result
# will appear in the pane to the right.
"""
# Load GraphiQL HTML view
require EEx
EEx.function_from_file :defp, :graphiql_html,
Path.absname(Path.relative_to_cwd("templates/graphiql.eex")),
[:graphiql_version, :query, :variables, :result]
def init(opts) do
allow_graphiql? = Keyword.get(opts, :allow_graphiql?, true)
Endpoint.init(opts) ++ [allow_graphiql?: allow_graphiql?]
end
def call(%Conn{method: m} = conn, opts) when m in ["GET", "POST"] do
args = Endpoint.extract_arguments(conn, opts)
if use_graphiql?(conn, opts) do
handle_call(conn, args)
else
Endpoint.handle_call(conn, args)
end
end
def call(%Conn{method: _} = conn, _) do
Endpoint.handle_error(conn, "GraphQL only supports GET and POST requests.")
end
defp escape_string(s) do
s
|> String.replace(~r/\n/, "\\n")
|> String.replace(~r/'/, "\\'")
end
defp handle_call(conn, args) do
# TODO construct a simple query from the schema (ie `schema.query.fields[0].fields[0..5]`)
query = args.query || @graphiql_instructions <> "\n{\n\tfield\n}\n"
{_, data} = GraphQL.execute(args.schema, query, args.root_value, args.variables, args.operation_name)
{:ok, variables} = Poison.encode(args.variables, pretty: true)
{:ok, result} = Poison.encode(data, pretty: true)
graphiql = graphiql_html(@graphiql_version, escape_string(query), escape_string(variables), escape_string(result))
conn
|> put_resp_content_type("text/html")
|> send_resp(200, graphiql)
end
def use_graphiql?(%Conn{method: "GET"} = conn, opts) do
case opts[:allow_graphiql?] && get_req_header(conn, "accept") do
[accept_header | _] ->
String.contains?(accept_header, "text/html") &&
!Map.has_key?(conn.params, "raw")
_ ->
false
end
end
def use_graphiql?(_, _), do: false
end