-
-
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,