How to have an :id param in the websocket url?

Hey, I modified the socket URL in endpoint.ex to
socket("/socket/:app_id", WebpackWeb.UserSocket)

The reason I need this is to allow multiple client apps to connect to the same Phoenix server on a different socket URL.
However, this param doesn’t seem to be passed to the connect function.
Is there a quick way to solve this, or will I need to build my own transport?

handle_in("/socket/" <> app_id, ...)

or

handle_in("/socket/app1", ...)
handle_in("/socket/app2", ...)

Isn’t this only for channels? I need this before the socket connection. Tried some variations, but they don’t work, function isn’t being called.

I modified the phoenix.js file to pass the ID, seems to pass it, but I’ll run some tests to see if it behaves like I want it to.

endPointURL(){
  let uri = Ajax.appendParams(
    Ajax.appendParams(this.endPoint, this.params), {vsn: VSN, app_id: this.endPoint.split('/')[2]})
  if(uri.charAt(0) !== "/"){ return uri }
  if(uri.charAt(1) === "/"){ return `${this.protocol()}:${uri}` }

  return `${this.protocol()}://${location.host}${uri}`
}

Sounds like an XY problem(?).

Why do you need this? Do you want a specific ID per socket connection? Wouldn’t a params field as shown here suffice?

No, a param field won’t help. The URL must be different as I specified. I want to allow different client apps to connect to the socket server. If they all share the same URL then on broadcast everyone will see everything, which is not what I want.

Gotcha, so you want to run different applications on a same backend. I understood something else, my bad!

In the event you were able to specify an app ID in the URL, how were you planning to organize this?
I’d recommend you have a separate socket definition per app, so you can set-up their channels separately. This also means you’d have multiple socket/2 calls in your router for each of the definitions.

Otherwise, if you had every app talk to a same socket definition, you’d need to explicitly make sure an app’s client doesn’t join another’s channel.

Yes, you’re right. I was too optimistic to think that only a different URL would work.
Thanks for the help.

I see now. I think the only way to do this with Phoenix as it currently stands would be to use different ports. You could combine that with a proxy in front that would take different URLS on port 80/443 and redirect them to same IP different ports. That’s a bit convoluted–up to you to decide if it’s worth it–and note that a proxy could be nginx, or it could be something you write in Elixir and run in the same BEAM instance…

It would probably be easier to use a custom cowboy dispatch router or whatever it’s called.

Making the URLs different for each connecting user, like @sribe previously showed, will ensure that broadcasting will not end up sending a message to all of them.

Instead, you can connect to additional channels once you’re connected (selectively, based on your application logic so only users that should be connected are connected), and broadcast on these.

If you want to see a live code example: In Planga, the Seamless Live Chat Service that we are building at Resilia (it is not live yet, but the source is open), look at:

  • the user socket to see the definition of the encrypted_chat channel (which is "encrypted_chat:#{base64_encoded_encrypted_connection_info}"),
  • in chat_channel, we join this channel, use the passed info to decide if the connection is allowed, and then a couple lines lower, subscribe to the actual "chat:#{app_id}#{conversation_id}", which is the channel that will be used to broadcast messages to all users connected to this chat.