diff --git a/lib/phoenix/router.ex b/lib/phoenix/router.ex index 7313ecad65..0d06d1a415 100644 --- a/lib/phoenix/router.ex +++ b/lib/phoenix/router.ex @@ -816,7 +816,14 @@ defmodule Phoenix.Router do end defp build_pipes(name, pipe_through) do - plugs = pipe_through |> Enum.reverse() |> Enum.map(&{&1, [], true}) + plugs = + pipe_through + |> Enum.reverse() + |> Enum.map(fn + {module, opts} -> {module, opts, true} + plug -> {plug, [], true} + end) + opts = [init_mode: Phoenix.plug_init_mode(), log_on_halt: :debug] {conn, body} = Plug.Builder.compile(__ENV__, plugs, opts) @@ -1036,6 +1043,11 @@ defmodule Phoenix.Router do pipe_through [:require_authenticated_user, :my_browser_pipeline] + A module plug may also be given, optionally with a tuple of `{plug, opts}` + to pass options to it: + + pipe_through [:browser, MyApp.Plugs.Locale, {MyApp.Plugs.Feature, flag: :beta}] + ## Multiple invocations `pipe_through/1` can be invoked multiple times within the same scope. Each diff --git a/test/phoenix/router/pipeline_test.exs b/test/phoenix/router/pipeline_test.exs index 3a404f4754..8fb719eb85 100644 --- a/test/phoenix/router/pipeline_test.exs +++ b/test/phoenix/router/pipeline_test.exs @@ -174,4 +174,35 @@ defmodule Phoenix.Router.PipelineTest do end end end + + test "pipe_through with module plug and options" do + defmodule ModulePlugRouter do + use Phoenix.Router + + defmodule GreetingPlug do + def init(opts), do: opts + + def call(conn, opts) do + Plug.Conn.assign(conn, :greeting, Keyword.fetch!(opts, :greeting)) + end + end + + pipeline :api do + plug :put_assign, "api" + end + + scope "/" do + pipe_through [:api, {GreetingPlug, greeting: "Hey there"}] + get "/hello", SampleController, :index + end + + defp put_assign(conn, value) do + assign(conn, :stack, [value | conn.assigns[:stack] || []]) + end + end + + conn = call(ModulePlugRouter, :get, "/hello") + assert conn.assigns[:greeting] == "Hey there" + assert conn.assigns[:stack] == ["api"] + end end