Getting the remote_ip from the Conn into the Socket for WebSocket connection

I am connecting some client desktop applications to my server using GenSocketClient. I need to obtain the IP address for the client, which I use to identify clients (the whole system is in a private network with static IP addresses). In a channel, our state is a socket which does not have this info. It does live in the Conn and in the cowboy_websocket process’ state. I was able to find the websocket connection details in req of the state kept in cowboy_websocket.erl and extracted it like so:

defmodule MyAppWeb.SomeChannel do
  Record.defrecord(:state, Record.extract(:state, from: "deps/cowboy/src/cowboy_websocket.erl"))

  def handle_in("ping", payload, socket) do
    {cowboy_websocket_state, _, _} = :sys.get_state(socket.transport_pid)
    true = Record.is_record(cowboy_websocket_state, :state)
    req = Keyword.fetch!(state(cowboy_websocket_state), :req)
    peer = req[:peer]

    {:reply, {:ok, payload}, socket}
  end
end

It was suggested that this method is “hacky”, which is not untrue, and that I raise an issue with regards to getting the peer from the req, which becomes the remote_ip in the conn into the socket.

So, I have modified connect in Phoenix.Transports.WebSocket to put conn.remote_ip into my socket’s private map. I couldn’t see a way to request this from the cowboy websocket process and there is an old issue where the author informs them they have to put it in their state in init.

Any advice?

endpoint.ex

  socket "/socket", MyAppWeb.UserSocket,
    websocket: [connect_info: [:peer_data]],
    longpoll: false
3 Likes