We have to do something similar at work. What we ended up doing is instead of having the Router as the final plug in our Endpoint we have a plug which chooses the correct router based on the hostname. Something akin to this:
plug Shared.RouteByDomain, %{
"example1.com" => Example1Router,
"example2.com" => Example2Router
}
And the call/2 looks like this:
def call(conn, routers) do
with {:ok, domain} <- fetch_domain(conn),
{:ok, router} <- fetch_router(routers, domain) do
conn
|> Conn.assign(:domain, domain)
|> router.call([])
else
# some error handling
end
end






















