# Minch
[![CI](https://github.com/nmbrone/minch/actions/workflows/ci.yml/badge.svg)](https://github.com/nmbrone/minch/actions/workflows/ci.yml)
A WebSocket client build around [`Mint.WebSocket`](https://github.com/elixir-mint/mint_web_socket).
## Installation
The package can be installed by adding `minch` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:minch, "~> 0.1.0"}
]
end
```
<!-- @moduledoc -->
## Usage
### Supervised client
```elixir
defmodule EchoClient do
use Minch
require Logger
def start_link(init_arg) do
Minch.start_link(__MODULE__, init_arg, name: __MODULE__)
end
@impl true
def init(_init_arg) do
{:ok, %{connected?: false}}
end
@impl true
def connect(_state) do
url = "wss://ws.postman-echo.com/raw"
headers = [{"authorization", "bearer: example"}]
# don't do this in production
options = [transport_opts: [{:verify, :verify_none}]]
{url, headers, options}
end
@impl true
def handle_connect(state) do
Logger.info("connected")
Process.send_after(self(), :produce, 5000)
{:reply, {:text, "welcome"}, %{state | connected?: true}}
end
@impl true
def handle_disconnect(reason, state) do
Logger.warning("disconnected: #{inspect(reason)}")
{:reconnect, 1000, %{state | connected?: false}}
end
@impl true
def handle_info(:produce, state) do
Process.send_after(self(), :produce, 5000)
{:reply, {:text, DateTime.utc_now() |> DateTime.to_iso8601()}, state}
end
@impl true
def handle_frame(frame, state) do
Logger.info(inspect(frame))
{:ok, state}
end
end
```
### Simple client
```elixir
url = "wss://ws.postman-echo.com/raw"
headers = []
# don't do this in production
options = [transport_opts: [{:verify, :verify_none}]]
IO.puts("checking ping to #{url}...")
case Minch.connect(url, headers, options) do
{:ok, pid, ref} ->
Minch.send_frame(pid, {:text, to_string(System.monotonic_time())})
case Minch.receive_frame(ref, 5000) do
{:text, start} ->
ping =
System.convert_time_unit(
System.monotonic_time() - String.to_integer(start),
:native,
:millisecond
)
IO.puts("#{ping}ms")
:timeout ->
IO.puts("timeout")
end
Minch.close(pid)
{:error, error} ->
IO.puts("connection error: #{inspect(error)}")
end
```