Skip to content
This repository was archived by the owner on Jul 25, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/graphql/plug.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ defmodule GraphQL.Plug do
{mod, func} -> apply(mod, func, [])
s -> s
end
%{schema: schema}
root_value = Keyword.get(opts, :root_value, %{})
%{:schema => schema, :root_value => root_value}
end

def call(conn, opts) do
Expand Down
38 changes: 28 additions & 10 deletions lib/graphql/plug/endpoint.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,18 @@ defmodule GraphQL.Plug.Endpoint do
{mod, func} -> apply(mod, func, [])
s -> s
end
%{schema: schema}
root_value = Keyword.get(opts, :root_value, %{})
%{:schema => schema, :root_value => root_value}
end

def call(%Conn{method: m} = conn, opts) when m in ["GET", "POST"] do
%{schema: schema} = conn.assigns[:graphql_options] || opts
%{:schema => schema, :root_value => root_value} = conn.assigns[:graphql_options] || opts

query = query(conn)
evaluated_root_value = evaluate_root_value(conn, root_value)
cond do
query && use_graphiql?(conn) -> handle_graphiql_call(conn, schema, query)
query -> handle_call(conn, schema, query)
query && use_graphiql?(conn) -> handle_graphiql_call(conn, schema, evaluated_root_value, query)
query -> handle_call(conn, schema, evaluated_root_value, query)
true -> handle_error(conn, "Must provide query string.")
end
end
Expand All @@ -27,14 +29,14 @@ defmodule GraphQL.Plug.Endpoint do
handle_error(conn, "GraphQL only supports GET and POST requests.")
end

defp handle_call(conn, schema, query) do
defp handle_call(conn, schema, root_value, query) do
conn
|> put_resp_content_type("application/json")
|> execute(schema, query)
|> execute(schema, root_value, query)
end

defp handle_graphiql_call(conn, schema, query) do
{:ok, data} = GraphQL.execute(schema, query)
defp handle_graphiql_call(conn, schema, root_value, query) do
{:ok, data} = GraphQL.execute(schema, query, root_value)
{:ok, result} = Poison.encode(%{data: data})
conn
|> put_resp_content_type("text/html")
Expand All @@ -48,8 +50,8 @@ defmodule GraphQL.Plug.Endpoint do
|> send_resp(400, errors)
end

defp execute(conn, schema, query) do
case GraphQL.execute(schema, query) do
defp execute(conn, schema, root_value, query) do
case GraphQL.execute(schema, query, root_value) do
{:ok, data} ->
case Poison.encode(%{data: data}) do
{:ok, json} -> send_resp(conn, 200, json)
Expand All @@ -63,6 +65,22 @@ defmodule GraphQL.Plug.Endpoint do
end
end

defp evaluate_root_value(conn, {mod, func}) do
apply(mod, func, [conn])
end

defp evaluate_root_value(conn, fn_root_value) when is_function(fn_root_value, 1) do
apply(fn_root_value, [conn])
end

defp evaluate_root_value(_, nil) do
%{}
end

defp evaluate_root_value(_, root_value) do
root_value
end

defp query(%Conn{params: %{"query" => query}}) do
if query && String.strip(query) != "", do: query, else: nil
end
Expand Down
2 changes: 1 addition & 1 deletion mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"cowlib": {:hex, :cowlib, "1.0.2"},
"earmark": {:hex, :earmark, "0.1.19"},
"ex_doc": {:hex, :ex_doc, "0.11.0"},
"graphql": {:hex, :graphql, "0.0.9"},
"graphql": {:hex, :graphql, "0.1.0"},
"plug": {:hex, :plug, "1.0.2"},
"poison": {:hex, :poison, "1.5.0"},
"ranch": {:hex, :ranch, "1.2.0"}}
33 changes: 33 additions & 0 deletions test/graphql/plug/endpoint_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ defmodule GraphQL.Plug.EndpointTest do
end

def greeting(_, %{name: name}, _), do: "Hello, #{name}!"
def greeting(%{greeting: name}, _, _), do: "Hello, #{name}!"
def greeting(_, _, _), do: greeting(%{}, %{name: "world"}, %{})
end

Expand All @@ -34,6 +35,38 @@ defmodule GraphQL.Plug.EndpointTest do
assert_query TestPlug, {:post, "/", query: "{greeting}"}, {200, success}
end

test "root data can be set at request time using function reference" do
defmodule TestRootPlugWithFunctionReference do
use Plug.Builder
def root_eval(_conn), do: %{greeting: "Root"}
plug GraphQL.Plug.Endpoint, [schema: {TestSchema, :schema}, root_value: &TestRootPlugWithFunctionReference.root_eval/1 ]
end

success = ~S({"data":{"greeting":"Hello, Root!"}})
assert_query TestRootPlugWithFunctionReference, {:get, "/", query: "{greeting}"}, {200, success}
end

test "root data can be hard coded at init time." do
defmodule TestRootPlugWithHardCodedData do
use Plug.Builder
plug GraphQL.Plug.Endpoint, [schema: {TestSchema, :schema}, root_value: %{greeting: "Hard Coded"}]
end

success = ~S({"data":{"greeting":"Hello, Hard Coded!"}})
assert_query TestRootPlugWithHardCodedData, {:get, "/", query: "{greeting}"}, {200, success}
end

test "root data can be set using {module, fun} syntax" do
defmodule TestRootPlugWithMF do
use Plug.Builder
def root_eval(_conn), do: %{greeting: "MF"}
plug GraphQL.Plug.Endpoint, [schema: {TestSchema, :schema}, root_value: {TestRootPlugWithMF, :root_eval}]
end

success = ~S({"data":{"greeting":"Hello, MF!"}})
assert_query TestRootPlugWithMF, {:get, "/", query: "{greeting}"}, {200, success}
end

test "specify schema using {module, fun} syntax" do
defmodule TestMFPlug do
use Plug.Builder
Expand Down