Skip to content

Commit 12a0a0c

Browse files
Support module plugs with options in pipe_through (#6755)
A module plug given with options as a {plug, opts} tuple raised at compile time: pipe_through [:api, {MyPlug, greeting: "hey"}] ** (ArgumentError) errors were found at the given arguments: * 1st argument: not an atom build_pipes/2 mapped every entry to {plug, [], true}, so a bare atom (function plug, pipeline, or module) worked, but a {plug, opts} tuple was passed through as the plug itself, which Plug.Builder then tried to treat as an atom. Map {plug, opts} tuples to {plug, opts, true} and keep the existing behaviour for bare entries. Closes #6711
1 parent 386b815 commit 12a0a0c

2 files changed

Lines changed: 44 additions & 1 deletion

File tree

lib/phoenix/router.ex

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -816,7 +816,14 @@ defmodule Phoenix.Router do
816816
end
817817

818818
defp build_pipes(name, pipe_through) do
819-
plugs = pipe_through |> Enum.reverse() |> Enum.map(&{&1, [], true})
819+
plugs =
820+
pipe_through
821+
|> Enum.reverse()
822+
|> Enum.map(fn
823+
{module, opts} -> {module, opts, true}
824+
plug -> {plug, [], true}
825+
end)
826+
820827
opts = [init_mode: Phoenix.plug_init_mode(), log_on_halt: :debug]
821828
{conn, body} = Plug.Builder.compile(__ENV__, plugs, opts)
822829

@@ -1036,6 +1043,11 @@ defmodule Phoenix.Router do
10361043
10371044
pipe_through [:require_authenticated_user, :my_browser_pipeline]
10381045
1046+
A module plug may also be given, optionally with a tuple of `{plug, opts}`
1047+
to pass options to it:
1048+
1049+
pipe_through [:browser, MyApp.Plugs.Locale, {MyApp.Plugs.Feature, flag: :beta}]
1050+
10391051
## Multiple invocations
10401052
10411053
`pipe_through/1` can be invoked multiple times within the same scope. Each

test/phoenix/router/pipeline_test.exs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,4 +174,35 @@ defmodule Phoenix.Router.PipelineTest do
174174
end
175175
end
176176
end
177+
178+
test "pipe_through with module plug and options" do
179+
defmodule ModulePlugRouter do
180+
use Phoenix.Router
181+
182+
defmodule GreetingPlug do
183+
def init(opts), do: opts
184+
185+
def call(conn, opts) do
186+
Plug.Conn.assign(conn, :greeting, Keyword.fetch!(opts, :greeting))
187+
end
188+
end
189+
190+
pipeline :api do
191+
plug :put_assign, "api"
192+
end
193+
194+
scope "/" do
195+
pipe_through [:api, {GreetingPlug, greeting: "Hey there"}]
196+
get "/hello", SampleController, :index
197+
end
198+
199+
defp put_assign(conn, value) do
200+
assign(conn, :stack, [value | conn.assigns[:stack] || []])
201+
end
202+
end
203+
204+
conn = call(ModulePlugRouter, :get, "/hello")
205+
assert conn.assigns[:greeting] == "Hey there"
206+
assert conn.assigns[:stack] == ["api"]
207+
end
177208
end

0 commit comments

Comments
 (0)