Azolo

Azolo

Hey everyone,

I just released WebSockex which is a Elixir WebSocket client.

WebSockex strives to work as a OTP special process, be RFC6455 compliant, and be simple to use by providing smart defaults for common actions.

Take a look and let me know about any questions, suggestions, or any other comments you may have,

Showing Posts 53 to 44

LostKobrakai

LostKobrakai

Check the conditions required for terminate to be called.

marschro

marschro

Hi all,

I try to understand something.

I have a iot device (shelly switch) that I am connected to via stateful websockex.

When I just disconnect the shelly from the power grid, so that it immediately stops and the socket connection stops, then according to the docs terminate is invoked on our side (the side that created the socket connection)

I have those two callbacks:

 def terminate({:remote, :closed} = reason, state) do
    Logger.error("[ ShellySocketConnector ] - Terminate: #{inspect(reason)}")
    {:ok, state}
  end

  def terminate(reason, state) do
    Logger.error("[ ShellySocketConnector ] - Terminate: #{inspect(reason)}")
    {:ok, state}
  end

… but I never get a log when terminating the socket connection by pulling the plug.

So is this expected behavior or am I doing something wrong. I would be happy to find a way, when a client disconnects or more in my case, terminates the socket connection.

Any hint appreciated.

cheers,
Martin

anuaralfetahe

anuaralfetahe

Stumbled on the same problems.
So basically I created a GenServer which is wrapper for the WebSockex process.
Starting the GenServer will return the pid no matter if the WebSockex fails on the start_link or not. You actualy start the websocket connection in the handle_continue/2 func asynchrously.
Then you need to specify handle_initial_conn_failure: true option on the WebSockex start_link func so you can handle the error in the handle_disconnect/2 func. In the handle_disconnect/2 func you can return the tuple {:reconnect, state} for automatic reconnecting. I have added some process sleep there aswell. Here’s the code:

      def start_link(args) do
        GenServer.start_link(__MODULE__, args)
      end

      @impl GenServer
      def init(state) do
        {:ok, state, {:continue, :start_ws}}
      end

      @impl GenServer
      def handle_continue(:start_ws, state) do
        {:ok, pid} = WebSockex.start_link(url, __MODULE__, [], [handle_initial_conn_failure: true])

        subscribe(pid, state)

        {:noreply, state}
      end

      @impl WebSockex
      def handle_disconnect(_conn, state) do
        IO.puts("Disconnected!")

        # Wait before trying to reconnect.
        Process.sleep(5000)

        {:reconnect, state}
      end

Theres also an option called async on the WebSocex library but this does not seem to work with the sending frame or I am missing something.

AlchemistCamp

AlchemistCamp

I’ve implemented a terminate very similar to that one. It gets executed if I cut the web connection after connecting but not if the connection is off when start_link() is called. In both cases, this leads to taking down the whole process and its supervisors.

The behavior I want instead is to just keep trying to reconnect to the 3rd party endpoint periodically.

Exadra37

Exadra37

Maybe you need to implement terminate/2?

Terminating with :normal after an Exceptional Close or Error

Usually you’ll want to negotiate and handle any abnormal close event or error leading to it, as per WS Spec, but there might be cases where you simply want the socket to exit as if it was a normal event, even if it was abruptly closed or another exception was raised. In those cases you can define the terminate callback and return exit(:normal) from it.

def terminate(reason, state) do 
  IO.puts(\nSocket Terminating:\n#{inspect reason}\n\n#{inspect state}\n") 
   exit(:normal) 
end
AlchemistCamp

AlchemistCamp

This is probably a basic question, but I’ve been having some problems getting modules where I use WebSockex to not crash their supervisors when there’s an issue connecting (e.g. when I turn my wifi off).

Here’s my start_link:

  def start_link(opts \\ []) do
    state = %{heartbeat: 0}

    socket_opts = [
      ssl_options: [
        ciphers: :ssl.cipher_suites() ++ [{:rsa, :aes_128_cbc, :sha}]
      ],
      handle_initial_conn_failure: true
    ]

    opts = Keyword.merge(opts, socket_opts)
    WebSockex.start_link(@socket_url, __MODULE__, state, opts)
  end

With my wifi off, iex -S mix will crash with:

* (Mix) Could not start application app: App.Application.start(:normal, []) returned an error: shutdown: failed to start child: App.Sockets.Supervisor
    ** (EXIT) shutdown: failed to start child: App.Sockets.Foo
        ** (EXIT) %WebSockex.ConnError{original: :timeout}

I’ve implemented a handle_disconnect/2. What changes should I make so that a networking failure doesn’t crash the whole module (and its supervisors)?

fcw528

fcw528

Cannot use proxy. When will proxy option be added?

ragamuf

ragamuf

Thumbs up for sharing this work. I’m using it to integrate with Slack RTM.

Azolo

Azolo OP

WebSockex 0.4.1 Released!

Enhancements

  • Allow :via and :global tuples for named registration.
    • This includes handling for cast/2 and send_frame/2.
  • Add access to response headers during handle_connect/2 via Conn.resp_headers.
  • Add Conn.parse_url/1 to handle url to URI conversion.
  • Allow Conn.new/2 to use a url string instead of a URI struct.
  • Automatically add a “/” path to a pathless url.
    • The HTTP request will break without a valid path!
  • Add child_spec definitions for Elixir 1.5+
    • Or any version that exports Supervisor.child_spec/2
  • Some documentation tweaks

Bug Fixes

  • No longer invoke handle_disconnect if there is reason to exit from invoking a callback. (e.g. an exception was raised)
  • Properly handle unexpected SSL socket termination.
    • This seems pretty important, but I don’t know…
  • Return a descriptive error when trying to use send_frame/2 in a callback.

Take a look at the v0.4.0...v0.4.1 diff or the release on hex.pm for more information.

Azolo

Azolo OP

Section 5.6 of the WebSocket Spec says that all complete text data frames need to be valid UTF8. However, closer reading of Section 8.1 implies that you could get away with sending a non-valid text frame and it is on the receiver to verify.

I think for the sake of this being a library and such, it should just work with as many use cases as possible instead of being the most correct version possible. So I am more than willing to forego the outgoing check in favor of making it work for your use case. Especially since the spec implies I can do that.

But there are probably a couple of non-trivial changes to make for iodata. Unless I don’t care about the overall send/write performance and just set it as a binary before it was sent, which would defeat the point of iodata.

Where Next? Top

Trending in Announcing Top

woylie
Flop is an Elixir library that applies filtering, ordering and pagination parameters to your Ecto queries. offset-based pagination with...
New
MRdotB
I needed to reuse React components from my Chrome extension in my Phoenix/LiveView backend. I noticed that for Svelte/Vue, there are live...
New
woylie
I released Doggo, a collection of unstyled Phoenix components. https://github.com/woylie/doggo Features Unstyled Phoenix components....
New
GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
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
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
anuaralfetahe
Hello Published a new library - ProcessHub! ProcessHub is a library designed to manage process distribution within the Elixir cluster. ...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New
AstonJ
This showed up on my feed.. anyone heard of it? Just hype? Ox Alpha is a reasoning model designed for coding, sustained ag...
New
bartblast
Hey folks, I just published a post about Hologram’s funding and where the project goes next - the short version: Curiosum as Main Spons...
New
CodeSync
:microphone: ElixirConf 2026 - Call for Talks is open! We’re heading to Chicago :united_states: :round_pushpin: In person + virtual :d...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews