Forward options from a Plug.Router to another Plug.Router

577 views Asked by At

Background

I have a Plug.Router application that receives some options. I need to pass these options to other plugs via forward but I don't know how to do it.

Code

This is the main router. It receives requests and decides where to forward them.

defmodule MyApp.Web.Router do
  use Plug.Router

  plug(:match)
  plug(:dispatch)

  #Here I check that I get options! 
  def init(father_opts), do: IO.puts("#{__MODULE__} => #{inspect father_opts}")

  forward "/api/v1", to: MyApp.Web.Route.API.V1, init_opts: father_opts??
end

As you can probably guess, this won't work. I want my forward call to access the father_opts this router is receiving, but I can't access them.

At first I though about the following code snippet:

def init(opts), do: opts

def call(conn, father_opts) do
  forward "/api/v1", to: MyApp.Web.Route.API.V1, init_opts: father_opts
end

But this doesn't work because I can't put a forward inside a call.

So how do I achieve my objective using forward?

1

There are 1 answers

2
Marcos Tapajós On BEST ANSWER

There is an option adding a top-level plug that will store the father options on private and you can fetch that on children call.

Something like:

defmodule Example.Router do
  def init(opts), do: opts
  def call(conn, options) do
    Example.RouterMatch.call(Plug.Conn.put_private(conn, :father_options, options), Example.RouterMatch.init(options))
  end
end

defmodule Example.RouterMatch do
  use Plug.Router

  plug :match
  plug :dispatch

  forward "/check", to: Example.Route.Check
  forward "/dispatch", to: Example.Plug.Dispatch
end

Then you can fetch options on the conn in Example.Route.Check.call/2.