Repository: absinthe-graphql/absinthe_plug
Pull request #237 (2020-11-26 05:16:16)

Transport Batch payload configuration option
This PR adds a configuration option that enables opting out of the default behavior for Transport Batch requests which nests the result in a `payload` key.

Followup to #179 from @aleqsio


Patch:
diff --git a/lib/absinthe/plug.ex b/lib/absinthe/plug.ex
index 7e50ba0..485c752 100644
--- a/lib/absinthe/plug.ex
+++ b/lib/absinthe/plug.ex
@@ -142,6 +142,7 @@ defmodule Absinthe.Plug do
   - `:log_level` -- (Optional) Set the logger level for Absinthe Logger. Defaults to `:debug`.
   - `:analyze_complexity` -- (Optional) Set whether to calculate the complexity of incoming GraphQL queries.
   - `:max_complexity` -- (Optional) Set the maximum allowed complexity of the GraphQL query. If a document’s calculated complexity exceeds the maximum, resolution will be skipped and an error will be returned in the result detailing the calculated and maximum complexities.
+  - `:transport_batch_payload_key` -- (Optional) Set whether or not to nest Transport Batch request results in a `payload` key. Older clients expected this key to be present, but newer clients have dropped this pattern. (default: `true`)
 
   """
   @type opts :: [
@@ -160,7 +161,8 @@ defmodule Absinthe.Plug do
           serializer: module | {module, Keyword.t()},
           content_type: String.t(),
           before_send: {module, atom},
-          log_level: Logger.level()
+          log_level: Logger.level(),
+          transport_batch_payload_key: Boolean.t()
         ]
 
   @doc """
@@ -206,6 +208,8 @@ defmodule Absinthe.Plug do
 
     before_send = Keyword.get(opts, :before_send)
 
+    transport_batch_payload_key = Keyword.get(opts, :transport_batch_payload_key, true)
+
     %{
       adapter: adapter,
       context: context,
@@ -219,7 +223,8 @@ defmodule Absinthe.Plug do
       content_type: content_type,
       log_level: log_level,
       pubsub: pubsub,
-      before_send: before_send
+      before_send: before_send,
+      transport_batch_payload_key: transport_batch_payload_key
     }
   end
 
@@ -456,9 +461,12 @@ defmodule Absinthe.Plug do
       results
       |> Enum.zip(request.extra_keys)
       |> Enum.map(fn {result, extra_keys} ->
-        Map.merge(extra_keys, %{
-          payload: result
-        })
+        result =
+          if config.transport_batch_payload_key,
+            do: %{payload: result},
+            else: result
+
+        Map.merge(extra_keys, result)
       end)
 
     {conn, {:ok, results}}


Test patch:
diff --git a/test/lib/absinthe/plug/transport_batching_test.exs b/test/lib/absinthe/plug/transport_batching_test.exs
index 557fec0..bd293d1 100644
--- a/test/lib/absinthe/plug/transport_batching_test.exs
+++ b/test/lib/absinthe/plug/transport_batching_test.exs
@@ -37,6 +37,11 @@ defmodule Absinthe.Plug.TransportBatchingTest do
     %{"payload" => %{"data" => %{"item" => %{"name" => "Bar"}}}}
   ]
 
+  @apollo_batch_link_foo_result [
+    %{"data" => %{"item" => %{"name" => "Foo"}}},
+    %{"data" => %{"item" => %{"name" => "Bar"}}}
+  ]
+
   @apollo_variable_query """
   [{
     "query": "query FooQuery($id: ID!){ item(id: $id) { name } }",
@@ -94,6 +99,18 @@ defmodule Absinthe.Plug.TransportBatchingTest do
     assert @apollo_foo_result == resp_body
   end
 
+  test "single batched query in modern apollo-link-batch-http format works" do
+    opts = Absinthe.Plug.init(schema: TestSchema, transport_batch_payload_key: false)
+
+    assert %{status: 200, resp_body: resp_body} =
+             conn(:post, "/", @apollo_query)
+             |> put_req_header("content-type", "application/json")
+             |> plug_parser
+             |> absinthe_plug(opts)
+
+    assert @apollo_batch_link_foo_result == resp_body
+  end
+
   test "single batched query in apollo format works with variables" do
     opts = Absinthe.Plug.init(schema: TestSchema)