elixir-maru / maru

Elixir RESTful Framework
https://maru.readme.io
BSD 3-Clause "New" or "Revised" License
1.32k stars 84 forks source link

Using plugs within mounted router doesn't work #90

Closed jalcine closed 6 years ago

jalcine commented 6 years ago

I've attempted to use [Ueberauth][1] to handle authentication for a project of mine. Currently, I've had to resort to using the plug for Ueberauth at the highest-level plug (let's call it MyApp.API). For the sake of keeping my code clean, I moved it to MyApp.API.Auth, a module that'd look like this:

defmodule MyApp.API.Auth do
  use Maru.Router
  plug Ueberauth
end

From MyApp.API, I'd do the following:

defmodule MyApp.API do
  use Maru.Router
  before do
    plug :sessions
    # ... etc ..
  end

  mount MyApp.API.Auth
end

My expectation is that the plug defined in the mounted router would be visible/usable. However, what happens is that it works as if I never used that plug in that router.

jalcine commented 6 years ago

Looking at this, it looks like mounting means to only pass in Maru-known routes into its parent router. https://github.com/elixir-maru/maru/blob/e61cf79f11c4d016766efb6778f6ae735445b1b3/lib/maru/builder/dsls.ex#L141-L147

falood commented 6 years ago

plug macro in maru router is a little different from in plug router. it's also different to use plug within before and within mounted module. for example:

defmodule API do
  use Maru.Router
  before do
    plug AA
  end

  plug A

  mount API.Router1

  get :a do
    ...
  end
end

defmodule API.Router1 do
  use Maru.Router

  plug B

  get :b do
    ...
  end

  pipeline do
    plug C
  end
  get :c do
    ...
  end
end

this router will work like this:

def call(conn, []) do
  conn = AA.call(conn, [])
  route(conn)
end

def route(%Plug.Conn{path_info: ["a"]}=conn) do
  conn |> A.call(conn, []) |> YOUR_OWN_LOGIC()
end

def route(%Plug.Conn{path_info: ["b"]}=conn) do
  conn |> A.call(conn, []) |> B.call(conn, []) |> YOUR_OWN_LOGIC()
end

def route(%Plug.Conn{path_info: ["c"]}=conn) do
  conn |> A.call(conn, []) |> B.call(conn, []) |> C.call(conn, []) |> YOUR_OWN_LOGIC()
end

have I explained it clearly?

jalcine commented 6 years ago

I think I get it. It's an interesting system, and I can see how this'll allow for you to manipulate paths for plugs.

jalcine commented 6 years ago

I'll close this for now but some example test code (in the codebase itself) could help here with this.