How to intercept HTTP messages generated by Endpoint's socket macro with a Plug?

Hi :wave:

I have an interesting use case that requires me to inject a response header into certain HTTP calls.
For most HTTP calls, this works fine with a custom Plug (see code sample below).
Unfortunately, I can’t seem to find a way to modify HTTP calls made as part of the socket macro in my Endpoint.
I’d expect to see HTTP calls being made as part of the HTTP Upgrade handshake used to establish a websocket, but they don’t seem to flow through the Endpoint.

There also doesn’t seem to be a documented way to insert tweak response headers as part of the socket macro itself (see docs).

It’s looking like I might need to open a separate websocket directly with cowboy and ditch the goodies I get from Phoenix.
Does anyone have a less painful suggestion?

Custom Plug

defmodule MyAppWeb.Plugs.CustomHeader do
  alias Plug.Conn

  def init(opts), do: opts

  # Replay requests to /gameserver
  def call(%Conn{path_info: ["relevant_path" | _path_info_tail]} = conn, _opts) do
    conn
     |> Conn.put_resp_header("foo", "bar")
  end

  # Don't modify other requests
  def call(%Conn{} = conn, _opts), do: conn
end

Relevant line in my Endpoint

socket "/live", Phoenix.LiveView.Socket, websocket: [connect_info: [session: @session_options]]

# Inserting my Plug either before or after this macro does nothing.
# It looks like the HTTP calls triggered by the macro don't flow through the rest of the `Endpoint`
plug MyAppWeb.Plugs.CustomHeader
1 Like

You can’t. socket intercepts the 101 upgrade from the endpoint pipeline.

1 Like

Thanks for confirming Chris.

It looks like the more generic Phoenix.Socket.Transport behavior also expects to be eventually mounted with the socket macro. I think I might have to go down to the :cowboy_websocket behavior and try to hand roll an implementation? :fearful:

1 Like

yeah you’ll need to use a cowboy web socket handler with dispatch rules if you want full control

2 Likes