- 
      
- 
        Save cblavier/0c2cf3f101d82c32503774f179a66a3f to your computer and use it in GitHub Desktop. 
| defmodule MasterProxy.Application do | |
| alias MyApp.Endpoint, as: MyAppEndpoint | |
| alias MyApp.UserSocket, as: MyAppUserSocket | |
| alias MyOtherApp.Endpoint, as: MyOtherAppEndpoint | |
| alias MyOtherApp.UserSocket, as: MyOtherAppUserSocket | |
| alias Phoenix.LiveReloader.Socket, as: LiveReloadSocket | |
| alias Plug.Cowboy | |
| use Application | |
| require Logger | |
| @port Application.get_env(:master_proxy, :port) | |
| def start(_type, _args) do | |
| {:ok, pid} = in_phoenix?() |> children |> run_application() | |
| Logger.info("successfully started master_proxy on port #{to_port(@port)}") | |
| {:ok, pid} | |
| end | |
| defp run_application(children) do | |
| import Supervisor.Spec, warn: false | |
| Supervisor.start_link( | |
| children, | |
| [strategy: :one_for_one, name: MasterProxy.Supervisor] | |
| ) | |
| end | |
| defp children(_start_cowboy = false), do: [] | |
| defp children(_start_cowboy = true) do | |
| [ | |
| Cowboy.child_spec( | |
| plug: nil, # since we're using manual dispatch, plug is ignored | |
| scheme: :http, | |
| options: [ | |
| port: to_port(@port), | |
| dispatch: [{:_, [ | |
| websocket_handler("/my_app/live_reload/socket/websocket", MyAppEndpoint, {LiveReloadSocket, :websocket}), | |
| websocket_handler("/my_other_app/live_reload/socket/websocket", MyOtherAppEndpoint, {LiveReloadSocket, :websocket}), | |
| websocket_handler("/my_app/socket/websocket", MyAppEndpoint, {MyAppUserSocket, websocket: true}), | |
| websocket_handler("/my_other_app/socket/websocket", MyOtherAppEndpoint, {MyOtherAppUserSocket, websocket: true}), | |
| {:_, Cowboy.Handler, {MasterProxy.Plug, []}} | |
| ]}] | |
| ] | |
| ) | |
| ] | |
| end | |
| defp websocket_handler(path, endpoint, options) do | |
| {path, Phoenix.Endpoint.Cowboy2Handler, {endpoint, options}} | |
| end | |
| # we only want the proxy to start when phoenix is started as well | |
| # (not in iex or tests) | |
| defp in_phoenix? do | |
| Application.get_env(:phoenix, :serve_endpoints) | |
| end | |
| defp to_port(nil) do | |
| Logger.error "Server can't start because :port in config is nil, please use a valid port number" | |
| exit(:shutdown) | |
| end | |
| defp to_port(binary) when is_binary(binary), do: String.to_integer(binary) | |
| defp to_port(integer) when is_integer(integer), do: integer | |
| defp to_port({:system, env_var}), do: to_port(System.get_env(env_var)) | |
| end | 
| use Mix.Config | |
| config :master_proxy, port: 5000 | |
| import_config "#{Mix.env}.exs" | 
| defmodule MasterProxy.Plug do | |
| def init(options) do | |
| options | |
| end | |
| def call(conn, _opts) do | |
| if conn.request_path =~ ~r{^/other_app} do | |
| MyOtherApp.Endpoint.call(conn, []) | |
| else | |
| MyApp.Endpoint.call(conn, []) | |
| end | |
| end | |
| end | 
| use Mix.Config | |
| config :master_proxy, | |
| port: {:system, "PORT"} | 
Hello ! @scorsi,
I succeed with LiveReload, but not with the LiveView socket :s
How did you manage it ?
It’s far too old... dont remember sorry
The gist is still accurate, the only different mention is that I also added LiveView sockets :
websocket_handler(
  "/my_app/live/websocket",
  MyAppEndpoint,
  {Phoenix.LiveView.Socket, :websocket}
),
websocket_handler(
  "/my_other_app/live/websocket",
  MyOtherAppEndpoint,
  {Phoenix.LiveView.Socket, :websocket}
)
in my JS, it looks like this:
const liveSocket = new LiveSocket('/my_app/live', Socket, { ... })
Let me know if it's working for you!
Yeah thanks it's working ! (But have to make a phx.digest)
I don't know why, I don't succeed to change the path.
My websocket_handler for an app looks like :
 websocket_handler(
   "/live/websocket",
   FortressWeb.Endpoint,
   {Phoenix.LiveView.Socket, :websocket}
 ),
 websocket_handler(
   "/phoenix/live_reload/socket/websocket",
   FortressWeb.Endpoint,
   {Phoenix.LiveReloader.Socket, :websocket}
 ),
 websocket_handler(
   "/socket/websocket",
   FortressWeb.Endpoint,
   {FortressWeb.UserSocket, websocket: true}
 ),
I trying to change  "/live/websocket" for  "/fortress_web/live/websocket", by changing
let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}}) to let liveSocket = new LiveSocket("/fortress_web/live", Socket, {params: {_csrf_token: csrfToken}}) but doesn't work :/
In your apps/fortress_web/lib/fortress_web/endpoint.ex did you change your socket path to /fortress_web/live as well?
yep :/
socket "/fortress_web/socket", FortressWeb.UserSocket,
    websocket: true,
    longpoll: false
socket "/fortress_web/live", Phoenix.LiveView.Socket, websocket: [connect_info: [session: @session_options]]
I don't understand why  "/live/websocket" is working with  LiveSocket("/live", Socket, {params: ... }) ^^'
When you expose a Phoenix Socket, it's available for two different protocols : websocket & long polling. That's why the actual websocket endpoint is /my_socket/websocket
Oh! ok thanks 🙏
@cblavier Is there a sample repository which implemented this... I am kinda new to umbrella apps.. , I want to host my admin app in umbrella using subdomain
Hello @cblavier,
I'm running into issues with your sample.
The Phoenix LiveReload isn't running correctly, are you experiencing some issues too ?
It did detect changes on code, actualize pages but code isn't updated. I'm running Phoenix 1.5.3 with LiveView. I did have change the path of live reloading to "/phoenix/...". Everything else is running correctly : LiveViews, Sockets and LiveReload socket connection (and page actualization).
It's a quite weird behaviour here.
Thanks,