ballerina/websocket

Overview

This module provides APIs for connecting and interacting with WebSocket endpoints.

This module facilitates two types of network entry points as the Client and Listener.

Client

The websocket:Client can be used to read/write text/binary messages synchronously.

A simple client code to handle text messages as follows.

1import ballerina/websocket;
2
3public function main() returns error? {
4 websocket:Client wsClient = check new("ws://echo.websocket.org");
5
6 check wsClient->writeTextMessage("Text message");
7
8 string textResp = check wsClient->readTextMessage();
9}

Similar to the above, this module has the writeBinaryMessage and readBinaryMessage functions to handle binary messages. A callback service with the two onPing and onPong remote functions can be registered at the initialization of the client to receive the ping/pong control frames.

1import ballerina/io;
2import ballerina/websocket;
3
4public function main() returns error? {
5 websocket:Client wsClient = check new("ws://echo.websocket.org", pingPongHandler = new clientPingPongCallbackService());
6 check wsClient->writeTextMessage("Text message");
7}
8
9service class clientPingPongCallbackService {
10 *websocket:PingPongService;
11 remote isolated function onPing(websocket:Caller caller, byte[] localData) returns byte[] {
12 io:println("Ping message received");
13 return localData;
14 }
15
16 remote isolated function onPong(websocket:Caller caller, byte[] localData) {
17 io:println("Pong message received");
18 }
19}

Listener

On the listener-side, an initial WebSocket upgrade service can be attached to the websocket:Listener to handle upgrade requests. It has a single get resource, which takes in an http:Request optionally. The get resource returns a websocket:Service to which incoming messages get dispatched after a successful WebSocket connection upgrade. This resource can be used to intercept the initial HTTP upgrade with custom headers or to cancel the WebSocket upgrade by returning an error. The returning websocket:Service has a fixed set of remote methods.

1service /ws on new websocket:Listener(21003) {
2 resource function get .(http:Request req) returns websocket:Service|websocket:UpgradeError {
3 return new WsService();
4}
5
6service class WsService {
7 *websocket:Service;
8 remote isolated function onTextMessage(websocket:Caller caller, string data) returns websocket:Error? {
9 check caller->writeTextMessage(data);
10 }
11}

Remote methods associated with websocket:Service

onOpen: As soon as the WebSocket handshake is completed and the connection is established, the onOpen remote method is dispatched.

onTextMessage: The received text messages are dispatched to this remote method.

onBinaryMessage: The received binary messages are dispatched to this remote method.

onPing and onPong: The received ping and pong messages are dispatched to these remote methods respectively.

onIdleTimeout: This remote method is dispatched when the idle timeout is reached. The idleTimeout has to be configured either in the WebSocket service or the client configuration.

onClose: This remote method is dispatched when a close frame with a statusCode and a reason is received.

onError: This remote method is dispatched when an error occurs in the WebSocket connection. This will always be preceded by a connection closure with an appropriate close frame.

Control Messages

A WebSocket contains three types of control messages: close, ping, and pong. A WebSocket server or a client can send a ping message and the opposite side should respond with a corresponding pong message by returning the same payload sent with the ping message. These ping/pong sequences are used as a heartbeat mechanism to check if the connection is healthy.

You do not need to explicitly control these messages as they are handled automatically by the services and clients. However, if required, you can override the default implementations of the ping/pong messages by registering a websocket:PingPongService in the client side as given in the above client code sample and by including the onPing and onPong remote functions in the websocket:Service in the server side.

1remote function onPing(websocket:Caller caller, byte[] data) returns error? {
2 io:println(string `Ping received with data: ${data.toBase64()}`);
3 check caller->pong(data);
4}
5
6remote function onPong(websocket:Caller caller, byte[] data) {
7 io:println(string `Pong received with data: ${data.toBase64()}`);
8}

A WebSocket server or a client can close the WebSocket connection by calling the close function. In the event of a connection closure, the service will be notified by invoking the onClose remote function. Also, on the client side, you will get a connection closure error if you try to read/write messages.

1remote function onClose(websocket:Caller caller, int statusCode, string reason) {
2 io:println(string `Client closed connection with ${statusCode} because of ${reason}`);
3}

WebSocket Compression

Per message compression extensions are supported by the Ballerina websocket module and this is enabled by default for both the WebSocket client and the server. Compression can be enabled or disabled by setting the webSocketCompressionEnabled to true or false in the ClientConfiguration and ListenerConfiguration. Once the compression is successfully negotiated, receiving compressed messages will be automatically decompressed when reading.

Origin Considerations

The Origin header can be used to differentiate between WebSocket connections from different hosts or between those made from a browser and some other kind of network client. It is recommended to validate this Origin header before accepting the WebSocket upgrade.

1import ballerina/http;
2import ballerina/websocket;
3
4service /basic/ws on new websocket:Listener(9090) {
5 resource isolated function get .(http:Request httpRequest) returns websocket:Service|websocket:UpgradeError {
6 string|error header = httpRequest.getHeader("Origin");
7 if header is string {
8 // Implement validateOrigin function to validate the origin header.
9 boolean validated = validateOrigin(header);
10 if validated {
11 return new WsService();
12 }
13 }
14 return error("Invalid upgrade request");
15 }
16}
17service class WsService {
18 *websocket:Service;
19 remote function onTextMessage(websocket:Caller caller, string text) {
20
21 }
22}

Using the TLS protocol to secure WebSocket communication

It is strongly recommended to use the wss:// protocol to protect against man-in-the-middle attacks. The Ballerina websocket module allows the use of TLS in communication to do this. This expects a secure socket to be set in the connection configuration as shown below.

Configuring TLS in server side

1listener websocket:Listener wssListener = new (9090, {
2 secureSocket: {
3 key: {
4 certFile: "../resource/path/to/public.crt",
5 keyFile: "../resource/path/to/private.key"
6 }
7 }
8});
9service /basic/ws on wssListener {
10
11}

Configuring TLS in client side

1websocket:Client wssClient = new ("wss://echo.websocket.org", {
2 secureSocket: {
3 cert: "../resource/path/to/public.crt"
4 }
5});

Listeners

[1]

Listener

This is used for creating WebSocket server endpoints.

Clients

[2]

Caller

Represents a WebSocket caller.

Client

Represents a WebSocket synchronous client endpoint.

Functions

[2]

addCookies

Adds cookies to the custom header.

authenticateResource

Uses for declarative auth design, where the authentication/authorization decision is taken by reading the auth annotations provided in service/resource and the Authorization header of request.

Object Types

[2]

PingPongService

The WebSocket service type to handle ping/pong frames

Service

The WebSocket service type

Records

[24]

BearerTokenConfig

Represents token for Bearer token authentication.

ClientConfiguration

Configurations for the WebSocket client.

ClientSecureSocket

Configures the SSL/TLS options to be used for WebSocket client.

CommonClientConfiguration

Common client configurations for WebSocket clients.

CredentialsConfig

Represents credentials for Basic Auth authentication.

FileUserStoreConfig

Represents file user store configurations for Basic Auth authentication.

FileUserStoreConfigWithScopes

Represents the auth annotation for file user store configurations with scopes.

JwtIssuerConfig

Represents JWT issuer configurations for JWT authentication.

JwtValidatorConfig

Represents JWT validator configurations for JWT authentication.

JwtValidatorConfigWithScopes

Represents the auth annotation for JWT validator configurations with scopes.

LdapUserStoreConfig

Represents LDAP user store configurations for Basic Auth authentication.

LdapUserStoreConfigWithScopes

Represents the auth annotation for LDAP user store configurations with scopes.

ListenerConfiguration

Provides a set of configurations for HTTP service endpoints.

ListenerHttp1Settings

Provides settings related to HTTP/1.x protocol.

ListenerSecureSocket

Configures the SSL/TLS options to be used for WebSocket service.

OAuth2ClientCredentialsGrantConfig

Represents OAuth2 client credentials grant configurations for OAuth2 authentication.

OAuth2IntrospectionConfig

Represents OAuth2 introspection server configurations for OAuth2 authentication.

OAuth2IntrospectionConfigWithScopes

Represents the auth annotation for OAuth2 introspection server configurations with scopes.

OAuth2JwtBearerGrantConfig

Represents OAuth2 JWT bearer grant configurations for OAuth2 authentication.

OAuth2PasswordGrantConfig

Represents OAuth2 password grant configurations for OAuth2 authentication.

OAuth2RefreshTokenGrantConfig

Represents OAuth2 refresh token grant configurations for OAuth2 authentication.

RequestLimitConfigs

Provides inbound request URI, total header and entity body size threshold configurations.

WebSocketRetryConfig

Retry configurations for WebSocket.

WSServiceConfig

Configurations for a WebSocket service.

Constants

[3]

AUTH_HEADER

Represents the Authorization header name.

AUTH_SCHEME_BASIC

The prefix used to denote the Basic authentication scheme.

AUTH_SCHEME_BEARER

The prefix used to denote the Bearer authentication scheme.

Annotations

[1]

ServiceConfig

The annotation which is used to configure a WebSocket service.

Types

[3]

ClientAuthConfig

Defines the authentication configurations for the WebSocket client.

ListenerAuthConfig

Defines the authentication configurations for the WebSocket listener.

OAuth2GrantConfig

Represents OAuth2 grant configurations for OAuth2 authentication.

Errors

[14]

AuthError

Defines the Auth error types that returned from the client.

AuthnError

Defines the authentication error type that returned from the listener.

AuthzError

Defines the authorization error type that returned from the listener.

ConnectionClosureError

Raised during failures in connection closure.

ConnectionError

Raised during connection failures.

Error

Represents any error related to the WebSocket module.

HandshakeTimedOut

Raised when the initial WebSocket handshake timed out.

InvalidContinuationFrameError

Raised when an out of order/invalid continuation frame is received.

InvalidHandshakeError

Raised during the handshake when the WebSocket upgrade fails.

PayloadTooLargeError

Raised when receiving a frame with a payload exceeding the maximum size.

ProtocolError

Raised when the other side breaks the protocol.

ReadTimedOutError

Raised when the client read time out reaches.

SslError

Raised when the SSL handshake fails.

UpgradeError

Raised when the WebSocket upgrade is not accepted.