WebSockets
This page presents one of the Web Application services. It describes how to use the WebSockets API of BaseX. WebSocket is a communication protocol for providing full-duplex communication.
The WebSocket protocol was standardized in RFC 6455 by the IETF. After an initial HTTP-request, all communication takes place over a single TCP connection. In contrast to the HTTP protocol, a connection will be kept alive, and a server can send unsolicited data to the client.
For establishing a WebSocket connection, a handshake request is sent by the client. The web server returns a handshake response. If the handshake is successful, the persistent connection will be open until an the client or the server closes it, an error occurs or a timeout happens. The timeout can be specified in the web.xml
configuration file. It is possible to transmit all kind of data, binary or text.
Introduction
Preliminaries
There are a bunch of annotations depending to WebSockets for annotating XQuery functions. When a WebSocket message arrives at the server, an XQuery function will be invoked that matches the constraints indicated by its annotations.
If a WebSocket function is requested (like connecting to the path '/', message to the path '/path', ...), the module directory and its sub-directories will be traversed, and all XQuery files will be parsed for functions with WebSocket annotations. Sub-directories that include an .ignore
the file will be skipped.
To speed up processing, the functions of the existing XQuery modules are automatically cached in main memory:
- Functions will be invalidated and parsed again if the timestamp of their module changes.
Examples
module namespace page = 'http://basex.org/modules/web-page'; import module namespace ws = "http://basex.org/modules/Websocket"; declare %ws:connect("/") function page:connect( ) { (: Do something after a client connects to the path "/" :) }; declare %ws:message("/","{$message}") function page:message( $message as xs:string ) { (: Do something if a message arrives at the server :) }; declare %ws:close("/") function chat:close() { (: Return a close message with the id of the client who closes the connection :) let $client-id := ws:id() let $msg := json:serialize( <json type="object"> <type>WebsocketClosed</type> <idThatClosed>{$client-id}</idThatClosed> </json> ) (: Broadcast the message to all connected users except the client who closes the connection :) return ws:broadcast($msg) };
Usage
- Enable the WebSocket servlet in the web.xml. You can set here the maxIdleTime, maxTextMessageSize and maxBinaryMessageSize too.
- If you get a message that exceeds the maxTextMessageSize/maxBinaryMessageSize or, if not set, the default messageSize of Jetty of 65 536 bytes (64 kB) then the connection will close. In this case, the ws:error annotation will be called.
<servlet> <servlet-name>wsservlet</servlet-name> <servlet-class>org.basex.http.ws.WsServlet</servlet-class> <init-param> <param-name>maxIdleTime</param-name> <param-value>100000</param-value> </init-param> <init-param> <param-name>maxTextMessageSize</param-name> <param-value>3000</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>wsservlet</servlet-name> <url-pattern>/ws/*</url-pattern> </servlet-mapping>
- Annotate your specific XQuery-Functions with WebSocketAnnotations.
Annotations
ws:connect(path)
Called directly after a successful WebSocket handshake. The path
specifies the path to which a client is connected to.
ws:message(path,message)
Called when a message
arrives at the server. The path
specifies the path to which a client is connected to. The message
is the message
sent by the client. Could be a text-message or a binary-message.
ws:close(path)
Called when the WebSocket closes. The path
specifies the path to which a client is connected to.
The WebSocket is already closed when this annotation is called so there can be no return.
ws:error(path, message)
Called when an error has occurred. Usually, this happens because of bad/malformed incoming packets. The path
specifies the path to which a client is connected to. The message
is the error message. The WebSocket connection gets closed after the error handling.
ws:header-param(name,variable[,default]
For accessing specific parameters like the Http-Version or the Sec-WebSocket-Version.
Parameters
- Http-Version -> f.e.: ```%ws:param("Http-Version", "{$version}")```
- Origin
- Protocol-Version
- QueryString
- IsSecure
- RequestURI
- Host
- Sec-WebSocket-Version
- offset -> just for binary-Messages
- len -> just for binary-Messages
Tipps
- For interacting with other clients or manage specific clients you should check out the WebSocket Module as well.