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 a Cro::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.