GenericJam

GenericJam

Working config for gun websocket client

Just leaving some breadcrumbs for future me and future others like me.

Connect with TCP (not secured) - most servers will reject but useful for localhost, etc.

connect_opts =
      %{
        connect_timeout: 60000,
        retry: 10,
        retry_timeout: 300,
        transport: :tcp,
        # Specify :http or :http2 to tell the server what you'd like. Support for http 2  is not great generally
        protocols: [:http],
        # Tell the server which version to use. Note: this is an atom.
        http_opts: %{version: :"HTTP/1.1"}
      }

Connect with TLS/SSH but you don’t care to verify the host

connect_opts,
    do:
      %{
        connect_timeout: 60000,
        retry: 10,
        retry_timeout: 300,
        transport: :tls,
        tls_opts: [
          verify: :verify_none,
          # Specify a bunch of certs
          cacerts: :certifi.cacerts(),
          # Or just one cert
          # cacertfile: CAStore.file_path(),
          depth: 99,
          reuse_sessions: false
        ],
        # See above explanation why you should specify
        http_opts: %{version: :"HTTP/1.1"},
        protocols: [:http],
      }

Using TLS/SSH and you want to verify the host

connect_opts = %{
        connect_timeout: 60000,
        retry: 10,
        retry_timeout: 300,
        transport: :tls,
        tls_opts: [
          verify: :verify_peer,
          cacerts: :certifi.cacerts(),
          # cacertfile: CAStore.file_path(),
          depth: 99,
          server_name_indication: 'example.com',
          reuse_sessions: false,
          verify_fun: {&:ssl_verify_hostname.verify_fun/3, [check_hostname: 'example.com']}
        ],
        http_opts: %{version: :"HTTP/1.1"},
        protocols: [:http]
      }

For :certifi and CAStore you may need to install these libs if they are not already in use in your project.

Use like

{:ok, gun_pid} = :gun.open('ws.example.com', 443, connect_opts)
# Wait for gun to be up - equivalent to :gun_up message
{:ok, http_version} = :gun.await_up(gun_pid)
# Put gun_pid and stream_ref in state to match on incoming messages
stream_ref = :gun.ws_upgrade(gun_pid, path(), headers()) |> IO.inspect()

Elsewhere monitor for the upgrade message. If you’re using a GenServer this will land in handle_info.

def handle_info({:gun_upgrade, gun_pid, stream_ref, stuff, headers}, %{gun_pid: gun_pid, stream_ref: stream_ref} = state) do
  # Now the websocket is upgraded and can send and receive
  :gun.ws_send(gun_pid, stream_ref, {:text, "Hello Server"})
  {:noreply, state}
end 

If you’re using a GenServer the rest of the messages from gun will land in other handle_infos so make a clause for each one you want to handle.

This should also work for libs that use gun such as glock.

Most Liked

GenericJam

GenericJam

There’s already glock which I was going to do a PR for. I might do that.

I was also thinking about doing my own take on it but those ideas are still percolating.

I was trying to use glock but then I was getting a bit frustrated with why it wasn’t working so I just resorted to gun which is actually fine once you know what it’s doing. I would want whatever lib I made to be more useful than just making :gun into Gun.

For example I’m not sure it’s actually beneficial obscuring the websocket upgrade as that is kind of important. That’s part of what I like about gun is it gives you access to the guts of what’s happening and gives you the option to react to it.

I’m thinking whatever lib I’d make would be paired with the user’s genserver and report back each of the stages.

GenericJam

GenericJam

I made a PR for glock. Hopefully it will be merged soon.

Where Next?

Popular in Guides/Tuts Top

tfwright
I thought I’d share a small project I’m working on to gain some familiarty with LiveView in a Phoenix app. Github Repo Deployment It’s...
New
jswny
Hello everyone, I recently redesigned my entire deployment process for Phoenix apps based on Docker. I really like the strategy that I ca...
New
OvermindDL1
Ran across this recently, it’s a set of cheatsheet inforgraphic things of the OTP behaviours on the BEAM: https://github.com/Telichkin/o...
New
smpallen99
Did you know that IO.inspect/2 returns the the first argument and accepts a label option as a second argument. This makes it a perfect to...
New
New
danschultzer
I wrote this blog post based on our experiences setting up continuous delivery for our first production umbrella Phoenix app. Coming from...
New
kokolegorille
Hello dear alchemists, There was this question some days ago here about the deployment to a VPS. As I was in the process of deploying t...
New
drapermd
So here is the code I came up with to generically generate an array param that will be stored on a jsonb property in ecto. It only handl...
New
eclark
I’ve been working on a phoenix project lately and I wanted to use the latest versions of everything. Webpack 5 had some breaking changes ...
New
GenericJam
Just leaving some breadcrumbs for future me and future others like me. Connect with TCP (not secured) - most servers will reject but use...
New

Other popular topics Top

danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 29377 241
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
TunkShif
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
274 41539 114
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New

We're in Beta

About us Mission Statement