Specification: Ballerina WebSocket Library
Owners: @shafreenAnfar @bhashinee
Edition: Swan Lake
This is the specification for the WebSocket standard library of Ballerina language, which provides WebSocket client-server functionalities.
The WebSocket library specification has evolved and may continue to evolve in the future. The released versions of the specification can be found under the relevant GitHub tag.
If you have any feedback or suggestions about the library, start a discussion via a GitHub issue or in the Slack channel. Based on the outcome of the discussion, the specification and implementation can be updated. Community feedback is always welcome. Any accepted proposal, which affects the specification is stored under
/docs/proposals. Proposals under discussion can be found with the label
type/proposal in GitHub.
The conforming implementation of the specification is released and included in the distribution. Any deviation from the specification is considered a bug.
- Service Types
- Securing the WebSocket Connections
WebSocket is a protocol that allows a long held full-duplex connection between a server and client. This specification elaborates on how Ballerina language provides a tested WebSocket client and server implementation that is compliant with the RFC 6455.
The WebSocket listener can be constructed with a port or an http:Listener. When initiating the listener it opens up the port and attaches the upgrade service at the given service path. It is also worth noting that upgrade service is quite similar to an HTTP service.
When initializing the listener, following configurations can be provided,
ListenerHttp1Settings record contains the settings related to HTTP/1.x protocol. This is an included record from the HTTP package, and this will only be applicable to the initial WebSocket upgrade request.
ListenerHttp1Settings record in the HTTP package contains the following fields.
ListenerSecureSocket record contains configurations related to enabling SSL/TLS on the listener side, and it is an included record from the HTTP package. More details and examples of how to configure them can be found in a following section on
Securing the WebSocket Connections.
ListenerSecureSocket record in the HTTP package contains the following fields.
RequestLimitConfigs record represents configurations related to maximum sizes of URI, headers and entity body which is also an included record from the hTTP package as this will only be applicable to the initial WebSocket upgrade request.
RequestLimitConfigs record in the HTTP package contains the following fields.
The WebSocket listener can be initialized by providing the
port or a
http:Listener and optionally a
Upgrade service is pretty much similar to an HTTP service. 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.
When writing the service, following configurations can be provided,
3.2. WebSocket Service
Once the WebSocket upgrade is accepted by the UpgradeService, it returns a
websocket:Service. This service has a fixed set of remote functions that do not have any configs. Receiving messages will get dispatched to the relevant remote function. Each remote function is explained below.
As soon as the WebSocket handshake is completed and the connection is established, the
onOpen remote method is dispatched.
The received text messages are dispatched to this remote method.
The received binary messages are dispatched to this remote method.
The received messages are dispatched to this remote method. Data binding support is provided to accept the messages as
The received ping and pong messages are dispatched to these remote methods respectively. You do not need to explicitly control these messages as they are handled automatically by the services and clients.
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.
This remote method is dispatched when a close frame with a statusCode and a reason is received.
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.
websocket:Client can be used to send and receive data synchronously over WebSocket connection. The underlying implementation is non-blocking.
When initializing the client, following configurations can be provided,
A client can be initialized by providing the WebSocket server url and optionally the
writeTextMessage API can be used to send a text message. It takes in the message to be sent as a
string and returns an error if an error occurs while sending the text message to the connection.
writeBinaryMessage API can be used to send a binary message. It takes in the message to be sent as a
byte and returns an error if an error occurs while sending the binary message to the connection.
writeMessage API can be used to send messages. It takes in the message to be sent as subtypes of
anydata and returns an error if an error occurs while sending the message to the connection.
The input data is internally converted to relevant frame type as follows,
- subtypes of string, xml, json - write out using text frames
- byte - write out using binary frames
readTextMessage API can be used to receive a text message. It returns the complete text message as a
string or else an error if an error occurs while reading the messages.
readBinaryMessage API can be used to receive a binary message. It returns the complete binary message as a
byte or else an error if an error occurs while reading the messages.
readMessage API can be used to receive a message without prior knowledge of message type.
anydata type is supported by this API.
The contextually-expected data type is inferred from the LHS variable type. If there is an error when converting the expected data type or else any other error occurs while reading the messages, the respective error will be returned from the API
close API can be used to close the connection. It takes in the optional parameters
statusCode for closing the connection,
reason for closing the connection if there is any and the
timeout to wait until a close frame is received from the remote endpoint.
ping API can be used to send ping messages. It takes in the message to be sent as a
byte and returns an error if an error occurs while sending the ping message to the connection.
pong API can be used to send pong messages. It takes in the message to be sent as a
byte and returns an error if an error occurs while sending the pong message to the connection.
To receive ping/pong messages, users have to register a
websocket:PingPongService when creating the client. If the service is registered, receiving ping/pong messages will get dispatched to the
onPong remote functions respectively.
If the user has implemented
onPing on their service, it's user's responsibility to send the
pong frame. It can be done simply by returning the data from the remote function, or else can be done using the
pong API of websocket:Caller. If the user hasn't implemented the
onPing remote function,
pong will be sent automatically.
Ballerina provides inbuilt support for SSL/TLS and configurations to enforce authentication and authorization such as Basic Auth, JWT auth, and OAuth2.
You can configure a secure socket for your WebSocket listener and client to upgrade to a TCP connection with TLS.
The TLS-enabled Listener
The TLS-enabled Client
The Ballerina WebSocket library provides built-in support for the following listener authentication mechanisms that are validated in the initial upgrade request.
- Basic authentication
- JWT authentication
- OAuth2 authentication
To enable one of the above, you should configure the
auth field in
websocket:ServiceConfig annotation which consists of the following records:
Each of the above records consists of configurations specific to each type as
OAuth2IntrospectionConfig respectively. You just have to configure them and there will be no need for any extensions or handlers. Ballerina will perform the required validation for you.
The Ballerina WebSocket client can be configured to send authentication information to the endpoint being invoked. The Ballerina WebSocket library also has built-in support for the following client authentication mechanisms.
- Basic authentication
- JWT authentication
- OAuth2 authentication
The following code snippet shows how a WebSocket client can be configured to call a secured endpoint. The
auth field of the client configurations (websocket:ClientConfiguration) should have either one of the
OAuth2RefreshTokenGrantConfig records. Once this is configured, Ballerina will take care of the rest of the validation process.