elixir-mint / mint_web_socket

HTTP/1 and HTTP/2 WebSocket support for Mint 🌱
https://hex.pm/packages/mint_web_socket
Apache License 2.0
117 stars 14 forks source link

How to connect to secure wss connections? #38

Closed justtorrell closed 2 months ago

justtorrell commented 2 months ago

I'm currently struggling to connect to the bybit futures websocket stream, using the mint websocket tool. This is the public URL I'm trying to connect to using the following steps (same as the basic example), yet I can't get past trying to upgrade the connection to a websocket, as it responds with a bad request and drops the connection:

{:ok, conn} = Mint.HTTP.connect(:http, "stream-testnet.bybit.com", 443)
{:ok, conn, ref} = Mint.WebSocket.upgrade(:wss, conn, "/v5/public/linear", [])

After these two commands, if you flush, I got presented with a badrequest error and a closed connection. Could you let me know what settings need to be set in order for this to connect and upgrade to a wss connection? Thanks

the-mikedavis commented 2 months ago

Is the Mint.HTTP.connect(:http part a typo? For an HTTPS/WSS connection it should be Mint.HTTP.connect(:https.

Otherwise it looks like you may want to force HTTP/1 by using Mint.HTTP1.connect/3 instead of Mint.HTTP.connect/3. Most web servers implement HTTP/1 websockets and very few implement HTTP/2 websockets. You may need to force an HTTP/1 connection since connecting might automatically choose HTTP/2.

the-mikedavis commented 2 months ago

If you mean to make an SSL connection then you must connect with Mint.HTTP.connect(:https or Mint.HTTP1.connect(:https. It does successfully connect but it's an HTTP connection rather than HTTPS. The {:tcp, port, data} message means that the connection is using plain TCP rather than SSL - you would receive a {:ssl, socket, data} message instead.

justtorrell commented 2 months ago

Hmm interesting, I've been playing with your solutions but still no luck, seems to be an issue when trying to upgrade to the websocket stream.

In the following example, I connect via SSL which seems to be fine and active, but the upgrade results in a WebSocket Error:

iex(9)> {:ok, conn} = Mint.HTTP.connect(:https, "stream-testnet.bybit.com", 443, [])
{:ok,
 %Mint.HTTP2{
   transport: Mint.Core.Transport.SSL,
   socket: {:sslsocket, {:gen_tcp, #Port<0.14>, :tls_connection, :undefined},
    [#PID<0.334.0>, #PID<0.333.0>]},
   mode: :active,
   hostname: "stream-testnet.bybit.com",
   port: 443,
   scheme: "https",
   authority: "stream-testnet.bybit.com",
   state: :handshaking,
   buffer: "",
   window_size: 65535,
   encode_table: %HPAX.Table{
     max_table_size: 4096,
     entries: [],
     size: 0,
     length: 0
   },
   decode_table: %HPAX.Table{
     max_table_size: 4096,
     entries: [],
     size: 0,
     length: 0
   },
   ping_queue: {[], []},
   client_settings_queue: {[[]], []},
   next_stream_id: 3,
   streams: %{},
   open_client_stream_count: 0,
   open_server_stream_count: 0,
   ref_to_stream_id: %{},
   server_settings: %{
     max_header_list_size: :infinity,
     initial_window_size: 65535,
     max_frame_size: 16384,
     max_concurrent_streams: 100,
     enable_push: true,
     enable_connect_protocol: false
   },
   client_settings: %{
     max_header_list_size: :infinity,
     initial_window_size: 65535,
     max_frame_size: 16384,
     max_concurrent_streams: 100,
     enable_push: true
   },
   headers_being_processed: nil,
   proxy_headers: [],
   private: %{},
   log: false
 }}
iex(10)> Mint.WebSocket.upgrade(:wss, conn, "/v5/public/linear", [])
{:error,
 %Mint.HTTP2{
   transport: Mint.Core.Transport.SSL,
   socket: {:sslsocket, {:gen_tcp, #Port<0.14>, :tls_connection, :undefined},
    [#PID<0.334.0>, #PID<0.333.0>]},
   mode: :active,
   hostname: "stream-testnet.bybit.com",
   port: 443,
   scheme: "https",
   authority: "stream-testnet.bybit.com",
   state: :handshaking,
   buffer: "",
   window_size: 65535,
   encode_table: %HPAX.Table{
     max_table_size: 4096,
     entries: [],
     size: 0,
     length: 0
   },
   decode_table: %HPAX.Table{
     max_table_size: 4096,
     entries: [],
     size: 0,
     length: 0
   },
   ping_queue: {[], []},
   client_settings_queue: {[[]], []},
   next_stream_id: 3,
   streams: %{},
   open_client_stream_count: 0,
   open_server_stream_count: 0,
   ref_to_stream_id: %{},
   server_settings: %{
     max_header_list_size: :infinity,
     initial_window_size: 65535,
     max_frame_size: 16384,
     max_concurrent_streams: 100,
     enable_push: true,
     enable_connect_protocol: false
   },
   client_settings: %{
     max_header_list_size: :infinity,
     initial_window_size: 65535,
     max_frame_size: 16384,
     max_concurrent_streams: 100,
     enable_push: true
   },
   headers_being_processed: nil,
   proxy_headers: [],
   private: %{scheme: :wss},
   log: false
 }, %Mint.WebSocketError{reason: :extended_connect_disabled}}

For me, I simply want to connect to this stream so I can subscribe to and grab the data: 'wss://stream-testnet.bybit.com/v5/public/linear' (websocket stream info found here Not sure what I'm doing to make this such a tedious task...

justtorrell commented 2 months ago

No worries, I fixed the issue and got the connection secured:

# Working solution for a secure connnection
{:ok, conn} = Mint.HTTP.connect(:https, "stream-testnet.bybit.com", 443, protocols: [:http1])
{:ok, conn, ref} = Mint.WebSocket.upgrade(:wss, conn, "/v5/public/linear", [{"host", "stream-testnet.bybit.com"}], [])

What you said @the-mikedavis made sense regarding http1 - had to force it. Thanks a lot