Fresh - WebSocket client built atop the Mint

Hi yall,

I am working on a WebSocket client for some time now, aiming to develop a WebSocket client that’s both simple and reliable.

I’m eagerly looking forward to receiving your feedback! :smile:

GitHub - bunopnu/fresh: WebSocket client for Elixir, built atop the Mint ecosystem

8 Likes

This is awesome! I’ve been thinking about creating a reverse proxy with Elixir, something like this might make that a lot easier.

1 Like

I typically refrain from bothering forum with releases, but I believe these are noteworthy improvements that should be mentioned :sweat_smile:

v0.4.1 - 29th September 2023

Changed

  • The payload for :reply has been refined to Mint.WebSocket.frame() | [Mint.WebSocket.frame()], meaning it can now be either a single WebSocket frame or a list of WebSocket frames.

v0.4.0 - 23rd September 2023

Added

  • Exponential backoff strategy for reconnection attempts.
  • :hibernate_after Option to automatically hibernate the WebSocket connection process after a specified duration of inactivity, helping conserve system resources.

Changed

  • Enhanced documentation for a more user-friendly experience.
3 Likes

Hi, thanks for the library!

I’m having some trouble starting the websocket connection.

defmodule Mymodule.Protocol.Websocket do
  use Fresh

  def start_link() do
    __MODULE__.start_link(
      uri: "wss://ws.kraken.com",
      state: %{},
      opts: [
        name: {:local, :consumer_1}
      ]
    )
  end
end

and this is the response I receive:

{:ok, #PID<0.229.0>}
** (EXIT from #PID<0.228.0>) shell process exited with reason: an exception was raised:
    ** (FunctionClauseError) no function clause matching in Mint.HTTP1.request/5
        (mint 1.5.1) lib/mint/http1.ex:251: Mint.HTTP1.request(%Mint.HTTP1{host: "ws.kraken.com", port: 443, request: nil, streaming_request: nil, socket: {:sslsocket, {:gen_tcp, #Port<0.7>, :tls_connection, :undefined}, [#PID<0.238.0>, #PID<0.237.0>]}, transport: Mint.Core.Transport.SSL, mode: :active, scheme_as_string: "https", requests: {[], []}, state: :open, buffer: "", proxy_headers: [], private: %{scheme: :wss, extensions: [], sec_websocket_key: "BjILFTs2jHw7qAt9C6CftQ=="}, log: false}, "GET", nil, [{"upgrade", "websocket"}, {"connection", "upgrade"}, {"sec-websocket-version", "13"}, {"sec-websocket-key", "BjILFTs2jHw7qAt9C6CftQ=="}], nil)
        (fresh 0.4.2) lib/fresh/connection.ex:92: Fresh.Connection.disconnected/3
        (stdlib 5.1.1) gen_statem.erl:1377: :gen_statem.loop_state_callback/11
        (stdlib 5.1.1) proc_lib.erl:241: :proc_lib.init_p_do_apply/3

As I can see it actually starts the process but dies immediately after.
I’m using Elixir 1.15.5.

I found the bug.

It is because of a missing path, adding a “/” at the end of the URI solves the issue, it will be fixed in next release :slight_smile:

(sorry for late response, I was busy with my school)

1 Like

I’m also working on a reverse proxy that uses bandit and mint. Keen to compare notes.

1 Like

v0.4.3 - 26th October 2023

Fixed

  • Failing to connect when no path is given in URI.

v0.4.2 - 12th October 2023

Added

  • New open?/1 function, which allows you to check whether a connection is open.
1 Like