Accessing headers in liveview

# mix.ex
  def project do
    [
      app: :client,
      version: "0.1.0",
      elixir: "~> 1.15",
      elixirc_paths: elixirc_paths(Mix.env()),
      start_permanent: Mix.env() == :prod,
      aliases: aliases(),
      deps: deps()
    ]
  end
...
  defp deps do
    [
      {:phoenix, "~> 1.7.10"},
      # {:phoenix_ecto, "~> 4.4"},
      # {:ecto_sql, "~> 3.10"},
      # {:postgrex, ">= 0.0.0"},
      {:phoenix_html, "~> 3.3"},
      {:phoenix_live_reload, "~> 1.2", only: :dev},
      {:phoenix_live_view, "~> 0.20.1"},
      ...
      {:cors_plug, "~> 3.0"}
    ]
  end
# socket.ex
defmodule ClientWeb.PageSocket do
  use ClientWeb, :live_view
...

Im using cors_plug to allow cross site access.

I have 2 instances of the same server running, 4000, 4010

For whatever reason Liveview mounts to both. When it mounts to 4010 which is the port the site is being served from, it mounts as %{private: %{connect_info: %Plug.Conn{}}} = socket

When it mounts to 4000 it does not.

I need access to the headers in 4000. Also I would like to know why it mounts to 4010 at all?

// app.js
let liveSocket = new LiveSocket(`ws://localhost:4000/live`, Socket, {
  params: params,
  hooks: Hooks
});

I think we need more bits from your code base to understand how things are set up in order to help.

BTW why are you running two instances?

Apparently your app.js unconditionally connects to localhost:4000, that’s unusual – I think typically you’d have /live there, such that the address is relative to the current origin.

You might be seeing differences specifically because one of the connections is cross origin and the other is same origin.

Im running 2 instances because the app will be distributed in a way that requires it. Im connecting to localhost:4000 to demonstrate the problem. Even being hard coded it should work as expected… The domain will be injected with selection logic, this is just min reproducible… unless Im missing something? What other code would you find useful?

Why is it connecting to 4010 at all? I specified 4000.

The ws connection to 4010 is probably a different path related to live reload which is enabled in the dev env, can you check?

How are you configuring the cors_plug?

The tips in this thread might help How to: Embed a LiveView via iframe

# endpoint.ex

  socket("/live", Phoenix.LiveView.Socket,
    websocket: [
      check_origin: ["//localhost:*"],
      connect_info: [
        :peer_data,
        :trace_context_headers,
        :x_headers,
        :uri
      ]
    ]
  )
...
  plug(CORSPlug,
    # Allow all origins
    # origin: "*",
    origin: [~r{^http://localhost:\d+$}],
    # Allow common HTTP methods
    methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
    headers: ["*"]
  )

its only connecting to the liveview socket.

config :client, ClientWeb.Endpoint,
  code_reloader: false,

Thoughts?

# router.ex
  pipeline :live_pipe do
    plug(:accepts, ["html"])
    plug(:fetch_session)
    plug(:fetch_live_flash)
    plug(Session.Router)
    plug(:protect_from_forgery)
    plug(:put_secure_browser_headers)
  end

  scope "/", Session do
    pipe_through(:live_pipe)

    live_session :index, root_layout: {ClientWeb.Layouts, :root_index} do
      live("/", Index)
    end
  end

  scope "/", Session do
    pipe_through(:live_pipe)

    live_session :test, on_mount: ClientWeb.PageSocket, root_layout: {ClientWeb.Layouts, :root_test} do
      live("/test", Test)
    end
  end

GET ws://localhost:4000/live/websocket?permit=P9GxjmoRCHyxVViok-D1PgDEyF4g75MMy4A6qBcfiW_B_8dqDHRiDRjLDeQ_q4OR5U1sAFfDGALPNkGUXOagIVmxng8wjrj8H8nx3C8YWxe72OUKz7_5K24xGQgyragXHQ2otdR22z8AvPyQK7d4hqCH8CSZGR98EKgaFW39iZo&_headers=&_track_static%5B0%5D=http%3A%2F%2Flocalhost%3A4010%2Fassets%2Fapp.css&_track_static%5B1%5D=http%3A%2F%2Flocalhost%3A4010%2Fassets%2Fapp.js&_mounts=0&_live_referer=undefined&vsn=2.0.0 HTTP/1.1
Host: localhost:4000
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Upgrade: websocket
Origin: http://localhost:4010
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: en-US,en;q=0.9
Sec-WebSocket-Key: bkoTKmQA5j9WxTyfN/q0Xw==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
defmodule ClientWeb.PageSocket do
  use ClientWeb, :live_view

  ...

  @impl true
  def on_mount(_,params, session, socket) do
    socket.private |> IO.inspect()

    {:cont, socket}
  end

  ...

end

4000 prints

%{
  connect_info: %{
    uri: %URI{
      scheme: "http",
      authority: "localhost",
...

4010 prints

%{
  connect_info: %Plug.Conn{
    adapter: {Plug.Cowboy.Conn, :...},
    assigns: %{
      permit:
...

I think I understand why… but Im not sure how to fix it. It goes through the socket mount process on 4010 because its a live page.

  scope "/", Session do
    pipe_through(:live_pipe)

    live_session :test, on_mount: ClientWeb.PageSocket, root_layout: {ClientWeb.Layouts, :root_test} do
      live("/test", Test)
    end
  end

This is it connecting to the /test endpoint. Not through 4000 specified in app.js.