I’m writing an application that supports custom domains, where the basic routes look like:
https://myapp.example/account-abc/location-abc
and the custom routes look like:
https://account-xyz.example/location-xyz
router.ex
# Matches the default `myapp.example` host, everything else will fall through
# https://myapp.example/account-abc
# https://myapp.example/account-abc/location-abc
scope "/", Client, host: Client.Endpoint.host() do
pipe_through(:browser)
live_session :default,
on_mount: [{Client.InitAssigns, :account}, {Client.InitAssigns, :locale}] do
live("/:account_id", AccountLive, :index)
live("/:account_id/:location_id", LocationLive, :index)
end
end
# Matches all the custom domains
# https://account-xyz.example
# https://account-xyz.example/location-xyz
scope "/", Client do
pipe_through(:browser)
live_session :custom_domain,
on_mount: [{Client.InitAssigns, :account}, {Client.InitAssigns, :locale}] do
live("/", AccountLive, :index)
live("/:location_id", LocationLive, :index)
end
end
I’ve a little wrapper function that extends MyAppWeb.Router.Helpers
by removing the :account
assign so that the helper generates the correct route depending on whether host
is the basic or a custom domain.
def tenant_helper(m, f, [%{host_uri: uri, endpoint: endpoint} | _] = a) do
a = if uri.host != endpoint.host(), do: List.delete_at(a, 2), else: a
apply(m, f, a)
end
that I call like
<%= live_patch to: tenant_helper(Routes, :location_path, [@socket, :index, @account, @location, []]) do %>
It works alright—but is there a “framework supported” way of achieving the same thing?