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

sergio
Hey there, we’re going to walk through deploying a Phoenix app to a DigitalOcean droplet, manually - no tools no nothing. Just straight u...
New
kuon
I have a page with a large state that is loaded from DB, let’s call that “data”. I have a root live view that load “data” on mount and r...
New
bentanweihao
I wrote a thing: http://engineering.pivotal.io/post/how-to-set-up-an-elixir-cluster-on-amazon-ec2/ Hope this is helpful!
New
nelsonic
Complete beginners Todo List Tutorial in Phoenix 1.5.3 (latest and greatest): It’s a feature complete TodoMVC clone with 0% JavaScri...
New
f0rest8
Hi everyone, Just wanted to say that the new Self-referencing many to many guide is now up on the official Hex docs (at least I just not...
New
Jskalc
Sorry if it’s a common knowledge, but it’s something I just learned and wanted to share. I’ve seen that mind-blowing demo of hot-reload ...
New
alejandroErik
POST IN CONSTRUCTION Process for compile erlang otp 20 with odbc-unix for Oracle connections on Solaris 11.3 for 64 bits: Introductio...
New
slouchpie
Warmest greetings, comrades. I recently started using :dns_cluster (GitHub - phoenixframework/dns_cluster: Simple DNS clustering for dis...
New
nietaki
Just a quick heads up: There seems to be a bug in Erlang/OTP 21.3, which can cause some errors when making http requests. If you’re using...
New
anuragg
We finally have a Mix clustering guide to go with Phoenix deployment with Mix Releases. Deploy an Elixir Cluster with Mix Releases and l...
New

Other popular topics Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
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
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
lk-geimfari
What is most correct way to open, read and parse JSON file with poison? For example if we have example.json file in root of some projec...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New

We're in Beta

About us Mission Statement