Low level websockets implies first a regular HTTP call and then an upgrade…
In my Phoenix project, I am configuring an endpoint with Endpoint.socket/3, passing it a module that implements the Phoenix.Socket.Transport behavior. This is so perfectly encapsulated, I have no idea how the above process is being done, nor by who. Just feels like magic.
I would definitely need to interfere in this process for some reason… is that even possible in Phoenix? I’d love to have an event pop up somewhere and have control over that HTTP socket before the upgrade.
Before 1.7 phoenix integrated directly with the underlying webserver to handle websockets, so it has been “magic”. With 1.7 changes to plug had been integrated, so plug can be involved in the initial http request till it’s upgraded, but afaik harnessing that added flexibility with
socket macro is still work to be done.
Is this process documented somewhere?
I mean, using the socket macro isn’t a requirement here… I willing to manually write plugs.
Plug.Conn — Plug v1.14.0 This should be a start.
Since 1.7 Phoenix uses WebsockAdapter.
Here is the relevant implementation in Phoenix.
So, I guess if I make a modified version of that thing and add it as a plug, that might do it…
Note that the
UserSocket connect/3 callback is a higher level place that lets you do something before the web socket upgrade. It is necessarily limited because it has to work for all transports, but if all you need is say, authenticate the user before allowing the web socket upgrade or other logic that you can get from query params or x headers, then that’s all you need without dipping lower.
To be more specific, if there’s a specific
Accept header, the app has to return data just like a normal GET request, and refrain from starting the websocket. It’s part of a protocol I am complying to.
gotcha. Yeah lower level HTTP req/resp will need access outside of the transport. Possible with 1.7, but not easily with <= 1.6
This reply made my day…
I modified the Phoenix implementation you just pointed to and it’s working perfectly!
Thank you so much!
Could you provide a bit of info into how you implemented this feature?
I need to do the exact same thing