Does Plug.Router need a pipeline?

Background

I have a Router module that forwards request to other routers.
In this router I have a pipleline comprised of plug(:match) and plug(:dispatch).

defmodule Example.Router do
  use Plug.Router

  plug(:match)
  plug(:dispatch)

  forward("/check", to: Example.Route.Check)

  get("/", do: send_resp(conn, 200, "router"))
end

In this second module I have the same pipeline:

defmodule Example.Route.Check do
  use Plug.Router

  plug(:match)
  plug(:dispatch)

  get "/", do: send_resp(conn, 200, "ok")
end

Questions

The issue I see here is that I always seem to need plug(:match) and plug(:dispatch) in all Plug.Routers. So I have the following questions:

  1. Is this really necessary?
  2. Do all routers need to have a pipeline in the same file they have the routes?

Normally every Plug.Router has to have those two plugs defined. This section in the Plug docs shows when it’s useful to have those plugs exposed like they are instead of being defined implicitly.

They are necessary because they define the order in which the plugs occur. So for example:

defmodule Example.Route.Check do
  use Plug.Router
  
  plug A
  plug(:match)
  plug B
  plug(:dispatch)
  plug C

  get "/", do: send_resp(conn, 200, "ok")
end

A runs before any matching or dispatching, B runs after matching but before dispatching, and C runs after dispatching if the dispatched route doesn’t send a response. If you didn’t have those two “boilerplate” plug calls you wouldn’t be able to thread other plugs at those points.

2 Likes

A real live example of that: needing a path_param from the url for the plug execution (so match is required) but the plug itself needing to run before dispatch: https://github.com/kipcole9/cldr/blob/master/test/plug/plug_router_test.exs#L1-L15

1 Like