socketry / async-websocket

Asynchronous WebSocket client and server, supporting HTTP/1 and HTTP/2 for Ruby.
MIT License
166 stars 18 forks source link

Problem connecting to websocket #16

Closed michelboaventura closed 4 years ago

michelboaventura commented 4 years ago

Hi,

I'm trying to connect to a crypto exchange to get some data using the code bellow. If I use the Event Machine version everything works, but if I use the async-websocket (which is commented) I always get a Protocol::HTTP2::StreamError: Stream closed!. Could you please help me debug this further?

require 'async'
require 'async/http/endpoint'
require 'async/io/stream'
require 'async/websocket/client'
require 'json'
require 'websocket-eventmachine-client'

payload = {
  OMSId: 1,
  InstrumentId: 1,
  Interval: 60,
  IncludeLastCount: 10
}

frame = {
  m: 0,
  i: 2,
  n: 'SubscribeTicker',
  o: payload.to_json
}.to_json

url = 'wss://api.coinext.com.br/WSGateway'

# Async do |task|
#   endpoint = Async::HTTP::Endpoint.parse(url)
#
#   Async::WebSocket::Client.connect(endpoint) do |connection|
#     connection.write(frame)
#   end
# end

EM.run do
  ws = WebSocket::EventMachine::Client.connect(uri: url)

  ws.onopen do
    ws.send(frame)
  end

  ws.onmessage do |message|
    puts message
  end
end
ioquatix commented 4 years ago

Does the remote endpoint support HTTP/2 websockets? Maybe we need to detect this situation. The error implies it's trying to connect using HTTP/2 but the websocket connection isn't supported. We probably need to fall back to HTTP/1 in this case.

ioquatix commented 4 years ago

You can force it to use HTTP/1... something like:

endpoint = Async::HTTP::Endpoint.parse("https://remote-server.com", alpn_protocols: Async::HTTP::Protocol::HTTP11.names)

Async::WebSocket::Client.connect(endpoint) do ...

Can you try that and report back? Try enabling verbose logging

CONSOLE_LOG_LEVEL=debug my-command

or

require 'async/logger'
Async.logger.debug!
michelboaventura commented 4 years ago

I've tried forcing HTTP/1 and it worked, so it seems like the remote endpoint doesn't support HTTP/2. Thank you for the help!

ioquatix commented 4 years ago

It supports http/2 just not http/2 websockets. It’s hard to auto detect this so it should be fine to use http/1 we sockets by default in your case.

ioquatix commented 4 years ago

If you have time can you submit a PR to show under Usage in the README how to do this and why?