Repository: elixir-grpc/grpc
Pull request #163 (2020-06-21 19:57:08)

Relax cowboy version constraint from 2.7.0 to 2.7

nonninz: Seconded. This solves dependency problems that would prevent us to use `cowlib ~> 2.9` as advised [in this same project's README](https://github.com/elixir-grpc/grpc#installation)
hkrutzer: @tony612 do you have time to merge this?

Patch:
diff --git a/lib/grpc/adapter/cowboy/handler.ex b/lib/grpc/adapter/cowboy/handler.ex
index 370d016..495a4f3 100644
--- a/lib/grpc/adapter/cowboy/handler.ex
+++ b/lib/grpc/adapter/cowboy/handler.ex
@@ -361,7 +361,7 @@ defmodule GRPC.Adapter.Cowboy.Handler do
         end
       catch
         kind, e ->
-          Logger.error(Exception.format(kind, e, System.stacktrace()))
+          Logger.error(Exception.format(kind, e, __STACKTRACE__))
 
           exit({:handle_error, kind})
       end
diff --git a/lib/grpc/server.ex b/lib/grpc/server.ex
index f30933e..557686a 100644
--- a/lib/grpc/server.ex
+++ b/lib/grpc/server.ex
@@ -184,7 +184,7 @@ defmodule GRPC.Server do
         {:error, e}
     catch
       kind, reason ->
-        stack = System.stacktrace()
+        stack = __STACKTRACE__
         Logger.error(Exception.format(kind, reason, stack))
         reason = Exception.normalize(kind, reason, stack)
         {:error, %{kind: kind, reason: reason, stack: stack}}
diff --git a/lib/grpc/transport/http2.ex b/lib/grpc/transport/http2.ex
index dfee977..189830f 100644
--- a/lib/grpc/transport/http2.ex
+++ b/lib/grpc/transport/http2.ex
@@ -20,6 +20,9 @@ defmodule GRPC.Transport.HTTP2 do
     }
   end
 
+  @doc """
+  Now we may not need this because gun already handles the pseudo headers.
+  """
   @spec client_headers(GRPC.Client.Stream.t(), map) :: [{String.t(), String.t()}]
   def client_headers(%{channel: channel, path: path} = s, opts \\ %{}) do
     [
@@ -34,7 +37,7 @@ defmodule GRPC.Transport.HTTP2 do
   def client_headers_without_reserved(%{codec: codec} = stream, opts \\ %{}) do
     [
       # It seems only gRPC implemenations only support "application/grpc", so we support :content_type now.
-      {"content-type", opts[:content_type] || "application/grpc+#{codec.name}"},
+      {"content-type", content_type(opts[:content_type], codec)},
       {"user-agent", "grpc-elixir/#{opts[:grpc_version] || GRPC.version()}"},
       {"te", "trailers"}
     ]
@@ -50,6 +53,18 @@ defmodule GRPC.Transport.HTTP2 do
     # TODO: Authorization
   end
 
+  defp content_type(custom, _codec) when is_binary(custom), do: custom
+
+  defp content_type(_, codec) do
+    # Some gRPC implementations don't support application/grpc+xyz,
+    # to avoid this kind of trouble, use application/grpc by default
+    if codec == GRPC.Codec.Proto do
+      "application/grpc"
+    else
+      "application/grpc+#{codec.name}"
+    end
+  end
+
   def extract_metadata(headers) do
     headers
     |> Enum.filter(fn {k, _} -> is_metadata(k) end)
diff --git a/mix.exs b/mix.exs
index 68eb5da..980c755 100644
--- a/mix.exs
+++ b/mix.exs
@@ -22,7 +22,8 @@ defmodule GRPC.Mixfile do
       ],
       dialyzer: [
         plt_add_apps: [:mix, :iex]
-      ]
+      ],
+      xref: [exclude: [IEx]]
     ]
   end
 
@@ -36,13 +37,13 @@ defmodule GRPC.Mixfile do
   defp deps do
     [
       {:protobuf, "~> 0.5"},
-      {:cowboy, "~> 2.7.0"},
+      {:cowboy, "~> 2.7"},
       {:gun, "~> 2.0.0", hex: :grpc_gun},
       # 2.9.0 fixes some important bugs, so it's better to use ~> 2.9.0
       # {:cowlib, "~> 2.9.0", override: true},
-      {:ex_doc, "~> 0.21", only: :dev},
+      {:ex_doc, "~> 0.23", only: :dev},
       {:inch_ex, "~> 2.0", only: [:dev, :test]},
-      {:dialyxir, "~> 1.0.0", only: [:dev, :test], runtime: false}
+      {:dialyxir, "~> 1.0", only: [:dev, :test], runtime: false}
     ]
   end
 
diff --git a/mix.lock b/mix.lock
index 1603092..5e36522 100644
--- a/mix.lock
+++ b/mix.lock
@@ -4,14 +4,15 @@
   "cowlib": {:hex, :cowlib, "2.8.0", "fd0ff1787db84ac415b8211573e9a30a3ebe71b5cbff7f720089972b2319c8a4", [:rebar3], [], "hexpm", "79f954a7021b302186a950a32869dbc185523d99d3e44ce430cd1f3289f41ed4"},
   "dialyxir": {:hex, :dialyxir, "1.0.0", "6a1fa629f7881a9f5aaf3a78f094b2a51a0357c843871b8bc98824e7342d00a5", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "aeb06588145fac14ca08d8061a142d52753dbc2cf7f0d00fc1013f53f8654654"},
   "earmark": {:hex, :earmark, "1.4.3", "364ca2e9710f6bff494117dbbd53880d84bebb692dafc3a78eb50aa3183f2bfd", [:mix], [], "hexpm", "8cf8a291ebf1c7b9539e3cddb19e9cef066c2441b1640f13c34c1d3cfc825fec"},
+  "earmark_parser": {:hex, :earmark_parser, "1.4.10", "6603d7a603b9c18d3d20db69921527f82ef09990885ed7525003c7fe7dc86c56", [:mix], [], "hexpm", "8e2d5370b732385db2c9b22215c3f59c84ac7dda7ed7e544d7c459496ae519c0"},
   "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
-  "ex_doc": {:hex, :ex_doc, "0.21.3", "857ec876b35a587c5d9148a2512e952e24c24345552259464b98bfbb883c7b42", [:mix], [{:earmark, "~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "0db1ee8d1547ab4877c5b5dffc6604ef9454e189928d5ba8967d4a58a801f161"},
+  "ex_doc": {:hex, :ex_doc, "0.23.0", "a069bc9b0bf8efe323ecde8c0d62afc13d308b1fa3d228b65bca5cf8703a529d", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "f5e2c4702468b2fd11b10d39416ddadd2fcdd173ba2a0285ebd92c39827a5a16"},
   "gun": {:hex, :grpc_gun, "2.0.0", "f99678a2ab975e74372a756c86ec30a8384d3ac8a8b86c7ed6243ef4e61d2729", [:rebar3], [{:cowlib, "~> 2.8.0", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", "03dbbca1a9c604a0267a40ea1d69986225091acb822de0b2dbea21d5815e410b"},
   "inch_ex": {:hex, :inch_ex, "2.0.0", "24268a9284a1751f2ceda569cd978e1fa394c977c45c331bb52a405de544f4de", [:mix], [{:bunt, "~> 0.2", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "96d0ec5ecac8cf63142d02f16b7ab7152cf0f0f1a185a80161b758383c9399a8"},
   "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fdf843bca858203ae1de16da2ee206f53416bbda5dc8c9e78f43243de4bc3afe"},
-  "makeup": {:hex, :makeup, "1.0.0", "671df94cf5a594b739ce03b0d0316aa64312cee2574b6a44becb83cd90fb05dc", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "a10c6eb62cca416019663129699769f0c2ccf39428b3bb3c0cb38c718a0c186d"},
-  "makeup_elixir": {:hex, :makeup_elixir, "0.14.0", "cf8b7c66ad1cff4c14679698d532f0b5d45a3968ffbcbfd590339cb57742f1ae", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "d4b316c7222a85bbaa2fd7c6e90e37e953257ad196dc229505137c5e505e9eff"},
-  "nimble_parsec": {:hex, :nimble_parsec, "0.5.3", "def21c10a9ed70ce22754fdeea0810dafd53c2db3219a0cd54cf5526377af1c6", [:mix], [], "hexpm", "589b5af56f4afca65217a1f3eb3fee7e79b09c40c742fddc1c312b3ac0b3399f"},
+  "makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"},
+  "makeup_elixir": {:hex, :makeup_elixir, "0.15.0", "98312c9f0d3730fde4049985a1105da5155bfe5c11e47bdc7406d88e01e4219b", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "75ffa34ab1056b7e24844c90bfc62aaf6f3a37a15faa76b07bc5eba27e4a8b4a"},
+  "nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"},
   "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"},
   "protobuf": {:hex, :protobuf, "0.7.1", "7d1b9f7d9ecb32eccd96b0c58572de4d1c09e9e3bc414e4cb15c2dce7013f195", [:mix], [], "hexpm", "6eff7a5287963719521c82e5d5b4583fd1d7cdd89ad129f0ea7d503a50a4d13f"},
   "ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"},


Test patch:
diff --git a/test/grpc/transport/http2_test.exs b/test/grpc/transport/http2_test.exs
index b255281..b8fcd16 100644
--- a/test/grpc/transport/http2_test.exs
+++ b/test/grpc/transport/http2_test.exs
@@ -19,7 +19,7 @@ defmodule GRPC.Transport.HTTP2Test do
              {":scheme", "http"},
              {":path", "/foo/bar"},
              {":authority", "grpc.io"},
-             {"content-type", "application/grpc+proto"},
+             {"content-type", "application/grpc"},
              {"user-agent", "grpc-elixir/1.0.0"},
              {"te", "trailers"}
            ]
@@ -86,9 +86,10 @@ defmodule GRPC.Transport.HTTP2Test do
 
   test "client_headers/3 support custom content-type" do
     stream = %Stream{channel: @channel, path: "/foo/bar"}
-    headers = HTTP2.client_headers(stream, %{content_type: "application/grpc"})
+    headers = HTTP2.client_headers(stream, %{content_type: "application/grpc-custom"})
 
-    assert {_, "application/grpc"} = Enum.find(headers, fn {key, _} -> key == "content-type" end)
+    assert {_, "application/grpc-custom"} =
+             Enum.find(headers, fn {key, _} -> key == "content-type" end)
   end
 
   test "client_headers/3 support custom codec" do