An open API service indexing awesome lists of open source software.

https://github.com/kontena/kontena-websocket-client

Ruby websocket client library
https://github.com/kontena/kontena-websocket-client

kontena ruby websockets

Last synced: about 1 year ago
JSON representation

Ruby websocket client library

Awesome Lists containing this project

README

          

[![Build Status](https://travis-ci.org/kontena/kontena-websocket-client.svg?branch=master)](https://travis-ci.org/kontena/kontena-websocket-client)
[![Gem Version](https://badge.fury.io/rb/kontena-websocket-client.svg)](https://badge.fury.io/rb/kontena-websocket-client)
[![Yard Docs](http://img.shields.io/badge/yard-docs-blue.svg)](http://www.rubydoc.info/github/kontena/kontena-websocket-client/master)

# Kontena::Websocket::Client

## Installation

Add this line to your application's Gemfile:

```ruby
gem 'kontena-websocket-client'
```

And then execute:

$ bundle

Or install it yourself as:

$ gem install kontena-websocket-client

## Usage

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 connected `Kontena::Websocket::Client` object
* The `read` method yields received websocket messages and returns once the websocket is closed
* The `send` and `close` methods can be called from the `connect` block, the `read` block, or a different thread
* Any of these functions can also raise `Kontena::Websocket::Error`

```ruby
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
```
### Environment variables

The library uses the following environment variables:

* `SSL_CERT_FILE`: Default value for `ssl_params: { ca_file: ... }`
* `SSL_CERT_PATH`: Default value for `ssl_params: { ca_path: ... }`

### Threadsafe

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.

### Timeouts

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, SSL `connect` operations
* `open_timeout` is used for the websocket `open` handshake
* `write_timeout` is used for each socket `write` operation
* `ping_timeout` is used for each websocket `ping` 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.

### SSL Validation

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:

```ruby
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`

### Examples

Use `bundle exec ./examples/...` to run the examples.

#### [Websocket Echo Client](./examples/websocket-echo-client.rb)

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
```

## Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/kontena/kontena-websocket-client.