Add this line to your application's Gemfile:
gem 'kontena-websocket-client'
And then execute:
$ bundle
Or install it yourself as:
$ gem install kontena-websocket-client
The high-level Kontena::Websocket::Client#connect
API uses a synchronous programming model instead of the event-based on(:event) do ...
model used by the browser WebSockets API:
- The
connect
class method yields the connectedKontena::Websocket::Client
object - The
read
method yields received websocket messages and returns once the websocket is closed - The
send
andclose
methods can be called from theconnect
block, theread
block, or a different thread - Any of these functions can also raise
Kontena::Websocket::Error
require 'kontena-websocket-client'
def websocket_connect
Kontena::Websocket::Client.connect(url, options...) do |client|
on_open
client.send(...)
client.close(1000)
client.read do |message|
on_message(message)
end
on_close(client.close_code, client.close_reason) # client closed connection
end
rescue Kontena::Websocket::CloseError => exc
on_close(exc.code, exc.reason) # server closed connection
rescue Kontena::Websocket::Error => exc
on_error(exc)
end
The library uses the following environment variables:
SSL_CERT_FILE
: Default value forssl_params: { ca_file: ... }
SSL_CERT_PATH
: Default value forssl_params: { ca_path: ... }
The Kontena::Websocket::Client
is threadsafe: while a single read thread is blocking on read
, other threads may safely call send
, ping
and close
.
The read
block may also call send
, ping
and close
.
Do not call read
from multiple threads, or the websocket messages may get corrupted.
The library uses an internal Mutex
to protect the internal Websocket::Driver
state, and prevent socket read/write reordering/corruption.
XXX: The on_pong
callback is called with the mutex held; do not call any client methods from the on_pong
block.
The Kontena::Websocket::Client
uses timeouts (given in options
) to deal with network errors and not leave the client hanging. Timeouts will raise a descriptive Kontena::Websocket::TimeoutError
from either the connect
, read
or send/close
methods.
connect_timeout
is used for both TCP, SSLconnect
operationsopen_timeout
is used for the websocketopen
handshakewrite_timeout
is used for each socketwrite
operationping_timeout
is used for each websocketping
request
The Kontena::Websocket::Client
supports keepalive pings, where the read
method will send a websocket ping request every ping_interval
seconds, and raise a Kontena::Websocket::TimeoutError
if it does not receive a websocket pong response within ping_timeout
seconds.
The Kontena::Websocket::Client
validates wss://
server SSL certificates by default, using the OpenSSL APIs to provide useful Kontena::Websocket::SSLVerifyError
messages. It also provides methods to inspect and validate the server SSL certificates, even when not using strict SSL validation.
Example code and resulting messages:
begin
ssl_cert = ws.ssl_cert!
rescue Kontena::Websocket::SSLVerifyError => ssl_error
ssl_cert = ssl_error.cert
else
ssl_error = nil
end
if ssl_cert && ssl_error
$logger.warn "Connected to #{url} with ssl errors: #{ssl_error} (subject #{ssl_cert.subject}, issuer #{ssl_cert.issuer})"
elsif ssl_error
$logger.warn "Connected to #{url} with ssl errors: #{ssl_error}"
elsif ssl_cert && !ws.ssl_verify?
$logger.warn "Connected to #{url} without ssl verify: #{ssl_cert.subject} (issuer #{ssl_cert.issuer})"
elsif ssl_cert
$logger.info "Connected to #{url} with ssl verify: #{ssl_cert.subject} (issuer #{ssl_cert.issuer})"
else
$logger.info "Connected to #{url} without ssl"
end
ERROR -- websocket-echo-client: certificate verify failed: self signed certificate
WARN -- websocket-echo-client: Connected to wss://localhost:9293 with ssl errors: certificate verify failed: self signed certificate (subject /CN=kontena.test, issuer /CN=kontena.test)
WARN -- websocket-echo-client: Connected to wss://echo.websocket.org without ssl verify: /OU=Domain Control Validated/CN=*.websocket.org (issuer /C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.com/repository//CN=Go Daddy Secure Certificate Authority - G2)
INFO -- websocket-echo-client: Connected to wss://echo.websocket.org with ssl verify: /OU=Domain Control Validated/CN=*.websocket.org (issuer /C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.com/repository//CN=Go Daddy Secure Certificate Authority - G2)
INFO -- websocket-echo-client: Connected to ws://echo.websocket.org without ssl
Use bundle exec ./examples/...
to run the examples.
Connect to a websocket server, displaying the server SSL certificate. Send lines from stdin
, and write messages to stdout
. Close on EOF
.
I, [2017-07-21T17:06:48.353944 #17507] INFO -- : Connecting to wss://echo.websocket.org...
I, [2017-07-21T17:06:49.329616 #17507] INFO -- : Connected to wss://echo.websocket.org with ssl verify: /OU=Domain Control Validated/CN=*.websocket.org (issuer /C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.com/repository//CN=Go Daddy Secure Certificate Authority - G2)
hello
D, [2017-07-21T17:06:50.447423 #17507] DEBUG -- : websocket write: "hello\n"
D, [2017-07-21T17:06:50.578683 #17507] DEBUG -- : websocket read: "hello\n"
hello
D, [2017-07-21T17:06:51.135395 #17507] DEBUG -- : websocket close: EOF
I, [2017-07-21T17:06:51.375279 #17507] INFO -- : Client closed connection with code 1000: EOF
Bug reports and pull requests are welcome on GitHub at https://github.com/kontena/kontena-websocket-client.