Licenser

Licenser

Plan old websockets in phoenix but without magic

Hi, I’m looking for a way to create a good old web socket and to send data from and to the browser. The result is going to end up in xterm.js (browser-based terminal), so the whole channels thing is out of the question (I don’t want to re-write xterm.js just to support channels).

I’ve tried phx_raws, but Phoenix still wants to mess with the messages the process gets and breaks stuff.

I’ve looked at overwriting HTTP: on the config, but that breaks the live reloader.

I’m quite lost here, I just want a good old WebSocket, the logic is super simple: if it receives {:binary, bla} from the socket, it calls a library, if it receives {:data, bla} it sends it to the socket. A bit auth sprinkled on it, and that’s it (literally a copy of this src/wiggle_console_h.erl · test · Project-FiFo / FiFo / wiggle · GitLab).

Any advice, am I missing a flag to turn off ‘magic’?

First 10 of 36 Posts Switch mode

OvermindDL1

OvermindDL1

Phoenix’s websocket support is via an abstraction of ‘Channels’ and phoenix does not really have any websocket helpers itself.

Rather what you want, if you want raw websockets, is just to use the cowboy API underneath Phoenix directly. Phoenix tends to not rewrite anything into itself if one of it’s dependencies already handles it, and as cowboy handles raw websockets already then it does nothing special with it, just implement cowboy’s API and put cowboy in your supervision tree, hooking in phoenix in the right place too. There are docs, hmm… somewhere on how to do it, maybe someone will link them? Hard for me to google at moment… ^.^;

Licenser

Licenser OP

Thanks mate, yes I looked at the cowboy stuff, Document use of "raw" websockets · Issue #234 · phoenixframework/phoenix · GitHub mentions dispatch_option which seems to no longer exist. The only thing I’ve found is completely hand crafting the dispatch rules which seems to be badly documented and blows up in dev as there are some secret endpoints added :frowning:

OvermindDL1

OvermindDL1

Yep that’s it, and yep you have to be sure to add in Phoenix’s stuff back again, can just mostly copy/paste it’s setup code though (and add your own). ^.^;

It would be nice if Phoenix’s endpoint setup had a method to add extra things to the cowboy setup… Maybe PR it? :slight_smile:

Licenser

Licenser OP

the problem is that approach is not working. Not all required endpoints are not documented and even searching the entire repo doesn’t show where they come from :confused:

OvermindDL1

OvermindDL1

Well what you ‘usually’ put in your application is:

      # Start the endpoint when the application starts
      supervisor(MyServerWeb.Endpoint, []),

And your Endpoint uses Phoenix’s Endpoint, so checking it’s use function is:
https://github.com/phoenixframework/phoenix/blob/v1.3.0/lib/phoenix/endpoint.ex#L440-L449

And the endpoint module behaviour defines init and other such interesting things, which delegate to the Phoenix.Endpoint.Supervisor, and here is the interesting part there:
https://github.com/phoenixframework/phoenix/blob/v1.3.0/lib/phoenix/endpoint/supervisor.ex#L65-L71

And the interesting part is probably server_children at:
https://github.com/phoenixframework/phoenix/blob/v1.3.0/lib/phoenix/endpoint/supervisor.ex#L92-L101

But it becomes hairy, so maybe wait for a Phoenix person like @chrismccord or so? ^.^;

But overall you could get the supervisor data like that then mutate it to add your own part, or maybe Phoenix has a way to add in custom cowboy handlers yet? :slight_smile:

chrismccord

chrismccord

Creator of Phoenix

The cowboy handler docs allow you to set up a cowboy websocket handler to use as you see fit:

https://github.com/phoenixframework/phoenix/blob/master/lib/phoenix/endpoint/cowboy_handler.ex#L8-L52

You may have tried these docs as you said you have issues but it’s not clear what problems you’re encountering. Note the caveats in the docs where these are cow1 specific and changes here not subject to semver.

sasajuric

sasajuric

Author of Elixir In Action

Have you tried this? This allows you to specify custom Cowboy dispatch list, and then you should be able to handle websocket connections without using the channels protocol.

Licenser

Licenser OP

Hi sorry you’re right I was really unclear about the issue. I am a bit confused myself by the whole thing :blush:

I did set up a custom dispatcher based on that docs but the moment I did the logs got spammed by errors:

18:42:19.367 [error] Ranch listener 'Elixir.CloudUiWeb.Endpoint.HTTP' terminated with reason: {{#{'__exception__' => true,'__struct__' => 'Elixir.Phoenix.Router.NoRouteError',conn => #{'__struct__' => 'Elixir.Plug.Conn',adapter => {'Elixir.Plug.Adapters.Cowboy.Conn',{http_req,#Port<0.35209>,ranch_tcp,keepalive,<0.854.0>,<<"GET">>,'HTTP/1.1',{{127,0,0,1},65375},<<"localhost">>,undefined,4000,<<"/phoenix/live_reload/socket/websocket">>,undefined,<<"vsn=2.0.0">>,undefined,[],[{<<"host">>,<<"localhost:4000">>},{<<"connection">>,<<"Upgrade">>},{<<"pragma">>,<<"no-cache">>},{<<"cache-co...">>,...},...],...}},...},...},...},...}
[info] GET /phoenix/live_reload/socket/websocket
    [debug] ** (Phoenix.Router.NoRouteError) no route found for GET /phoenix/live_reload/socket/websocket (CloudUiWeb.Router)
    (cloud_ui) lib/cloud_ui_web/router.ex:1: CloudUiWeb.Router.__match_route__/4
    (cloud_ui) lib/phoenix/router.ex:303: CloudUiWeb.Router."call (overridable 2)"/2
    (cloud_ui) lib/plug/error_handler.ex:64: CloudUiWeb.Router.call/2
    (cloud_ui) lib/cloud_ui_web/endpoint.ex:1: CloudUiWeb.Endpoint.plug_builder_call/2
    (cloud_ui) lib/plug/debugger.ex:99: CloudUiWeb.Endpoint."call (overridable 3)"/2
    (cloud_ui) lib/cloud_ui_web/endpoint.ex:1: CloudUiWeb.Endpoint.call/2
    (plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
    (cowboy) /Users/heinz/Projects/fifo/core/cloud_ui/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4

I interpret this as the live reload server endpoint missing, I hoped the :_ case would provide that but it seems it’s not and I couldn’t figure out where in the phoenix code it was defined to add it like the /socket/websocket endpoint

satom99

satom99

Would you mind sharing in what way Phoenix interferes and breaks your code? I just saw your issue, did you get to configure it? I’m wondering so I can tackle issues down before working on this.

Going with a manual Cowboy configuration otherwise is as well a good option :slight_smile:

Licenser

Licenser OP

Sure! This involves a bit of guess work about how phoenix works as it’s really a big black box to me.

The problem, from what I tell, is that Phoenix’s Socket will interpret any message that arrives at the Socket process and tries to handle it.

Simplified what I try to write is a websocket proxy. Data that comes from a process and gets send to the browser. Data that comes from the browser gets send to a process.

The issue start that when the process sends it data to the Socket, the socket treats it the same way it would treat websocket data, meaning it’ll start trying to apply opcodes and things to id.

So when the process sends socket_pid ! {:data, some_binary} then the socket crashes as Phoenix tries to parse that as something coming from the web socket.

Where Next?

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
jonnycharles
I’m in search of an Elixir library that offers PDF generation capabilities similar to Ruby’s Prawn. While there have been discussions abo...
New
spammy
I’m looking to build a personal workflow to quickly deploy web applications written in elixir/phoenix, for local consumption (ie not on t...
New
silverdr
Using Phoenix.LiveView.TagEngine as an EEx.Engine is deprecated! To compile HEEx, use Phoenix.LiveView.TagEngine.compile/2 instead. Sta...
New
dli
Before I dive in myself, did anyone successfully sprinkle Hologram into their existing LiveView app? Looking for hints regarding: Addi...
New
bottlenecked
Hi all, I wanted to ask how the community is dealing with post-release steps. Today we have Ecto migrations, which make sure that the db...
New
michallepicki
I am using Oban and occasionally, shortly after a deployment, a handful of jobs can fail because of dependency on other parts of the syst...
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New
type1fool
I just stumbled on a newly redesigned elixir-lang.org. :tada: It looks like @Software_Mansion did the work, and I think it is generally a...
New
akoutmos
@hugobarauna and I (Alex Koutmos) have been hard at work on writing a book on Nerves that takes you from simply blinking LEDs to building...
New

We're in Beta

About us Mission Statement