GenericJam
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.
Trending in Guides/Tuts
I’ve spent some time understanding how to do hot code reloading with releases built using mix release, and here I’d like to detail the st...
New
# ~/src/livebook/.iex.exs
System.cmd("xdg-open", [ LivebookWeb.Endpoint.access_url() ] )
Because Livebook requires a unique passcode on ...
New
Other Trending Topics
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
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
I am happy to introduce the very α version of the new programming language compiled to BEAM.
Welcome Cure.
It has literally three kille...
New
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
Hi everyone!
The first release candidate for the Expert language server project is now available!
We’ve published a press release detai...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #ai
- #elixirconf-us
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #elixirconf-eu
- #metaprogramming
- #hex











Showing Posts 1 to 4- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
stevensonmt
Have you thought about putting together a tiny library for this that just provides a couple functions for creating sane connect_opts for the couple of different scenarios you’ve listed? Might be more readily discoverable via Hex than this forum post in the long run.
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
:gunintoGun.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.
lpil
This is super useful! Thank you
GenericJam
I made a PR for glock. Hopefully it will be merged soon.