Using multiple routers in Phoenix

Hi, I’m experimenting with embedding one Phoenix project in another. In my endpoint I’ve configured two routers, one managed by my project (TribesWeb), and another imported from the dependency (Pleroma.Web):

plug TribesWeb.Router
plug Pleroma.Web.Router

The only thing stopping me from doing this is that Phoenix.Router terminates the conn in the first router if a match isn’t found:

Phoenix.Router.NoRouteError at GET /api/v1/instance
no route found for GET /api/v1/instance (TribesWeb.Router)

I want it to pass through to the second router if a match isn’t found. Is there a way around this?

1 Like

I am working in guide for this type of situation, but its still far from being complete… anyway you can take a look to it:

So, while my use case is more involved then yours, you can still use it as a starting point.


Another possibility for you is to use:


Also, @hauleth has some experience with this type of use case, thus he may also have some insights to share :slight_smile:

2 Likes

Thank you for the tip. I figured out I could create a wrapper plug to call multiple routers and handle the exception.

endpoint.ex:

plug TribesWeb.MultiRouterPlug, routers: [TribesWeb.Router, Pleroma.Web.Router]

And the plug code:

defmodule TribesWeb.MultiRouterPlug do
  import Plug.Conn

  @behaviour Plug

  def init(opts \\ []) do
    Enum.into(opts, %{})
  end

  def call(conn, %{routers: routers}) when is_list(routers) do
    Enum.reduce(routers, conn, fn router, conn ->
      try do
        router.call(conn, [])
      rescue
        Phoenix.Router.NoRouteError -> conn
      end
    end)
  end
end
3 Likes

You can also use forward/4 function from Phoenix.Router — Phoenix v1.5.8 at the end of your first router to forward all other routes to the second one.

This can have unwanted effects, because the pipelines in the other router will also run, therefore caution needs to be taken to not have some plugs doing twice the same thing and causing unwanted results.

2 Likes