cro-websocket-client
Cro::WebSocket::Client
The Cro::WebSocket::Client class provides a web socket client. It can either be instantiated with default configuration (such as a default URI) or used directly.
Connecting
To connect without making an instance, use the connect method with a URI:
my $conn = await Cro::WebSocket::Client.connect:
'ws://some.host:1234/path/to/chat';
To connect securely, use a wss URI:
my $conn = await Cro::WebSocket::Client.connect:
'wss://some.host:1234/path/to/chat';
If many connections shall be made to the same web socket server over time, it can be convenient to factor that out by passing the URI to the constructor:
my $client = Cro::WebSocket::Client.new: uri =>
'ws://some.host:1234/path/to/chat';
The connect
method may then be used without an argument:
my $conn = await $client.connect();
It is an error to call connect
without a URI if none was set at construction
time. If a URI is passed to the constructor and to connect
, then the one
given to connect
will be treated as a URI reference.
The connect
method returns a Promise
that is broken if the connection can
not be made. Otherwise, it is kept with a Cro::WebSocket::Client::Connection
object, which can be used to communicate over the WebSocket.
To pass extra headers with the WebSocket handshake HTTP request, pass a list
of them with the headers
named argument. They can be passed as Pair
s or
as instances of Cro::HTTP::Header
.
my $client = Cro::WebSocket::Client.new:
uri => 'ws://some.host:1234/path/to/chat',
headers => [
referer => 'http://anotherexample.com',
Cro::HTTP::Header.new(
name => 'User-agent',
value => 'Cro'
)
];
Send messages
Call the send
method on the connection to send a message. One can pass:
An instance of
Cro::WebSocket::Message
(least convenient, but most flexible; all other options described here are convenience forms that make aCro::WebSocket::Message
)A
Str
, in which case a text message will be sentA
Blob
, in which case a binary message will be sentA
Supply
, which should emitBlob
s; each one will be sent as a frame, allowing fragmentation of large messagesAny other object, which will be serialized using the body serializers set on the client (described later). For example, a client constructed with
:json
will automatically serialize sent objects to JSON.
For example:
$connection.send('Some unimaginative example string');
The message is sent asynchronously, and send
returns immediately.
Receive messages
The messages
method on the client returns a Supply
, which can be tapped
to receive messages that arrive over the WebSocket connection. The message
is represented by the Cro::WebSocket::Message
class.
react {
whenever $connection.messages -> $message {
whenever $message.body -> $body {
# Process the body
}
}
}
By default, the body
method provides a Blob
for a binary message and a
Str
for a text message. However, it's possible to configure body parsers
to apply deserialization. For example, a client constructed with :json
will perform JSON deserialization on all messages
Closing the connection
Call the close
method to close the WebSocket connection. If wishing to
specify the close code pass it as an argument, otherwise, a default code
of 1000
will be used.
$connection.close(2000);
The close
method returns a Promise
that will be kept once the connection
has been gracefully closed. To specify a timeout, pass the timeout
named
argument. A timeout of zero sends a forceful termination and immediately
closes the connection.
await $connection.close(timeout => 2); # 2s timeout
$connection.close(:!timeout); # forceful close, no timeout
Ping
To test if the connection is still alive, call ping
. It returns a Promise
that will be kept when a pong is received from the server.
await $connection.ping();
A timeout can also be specified in seconds:
await $connection.ping(timeout => 5);
It is also possible to send binary (Blob
) or text (Str
) data with the ping
(this mechanism does not apply body serialization, however).
await $connection.ping('Anybody there?', timeout => 5);
Body Parsing and Serialization
It is possible to instantiate the client with body parsers and serializers.
These allow for sending of objects other than Str
and Blob
. For example,
By instantiating the client with a JSON parser and serializer:
use Cro::WebSocket::BodyParsers;
use Cro::WebSocket::BodySerializers;
my $client = Cro::WebSocket::Client.new:
body-parsers => Cro::WebSocket::BodyParser::JSON,
body-serializers => Cro::WebSocket::BodySerializer::JSON;
Then it is possible to send
an object (Hash
or List
) on a connection,
and have it serialized automatically. Similarly received messages will have
the body
property return a Promise
that will be kept with a deserialized
JSON object.
Since this JSON combination is so common, the above example can simply be written as:
my $client = Cro::WebSocket::Client.new: :json;
Implement the Cro::BodyParser
and Cro::BodySerializer
roles in order to
create custom body parsers and serializers for use with the WebSocket client.