Difference between revisions of "WebSockets"
| Line 1: | Line 1: | ||
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. | 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. | ||
| − | After an initial HTTP-request | + | The WebSocket protocol was standardized in [https://tools.ietf.org/html/rfc6455 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 <code>web.xml</code> configuration file. It is possible to transmit all kind of data, binary or text. | |
| − | |||
| − | |||
=Introduction= | =Introduction= | ||
| Line 16: | Line 14: | ||
To speed up processing, the functions of the existing XQuery modules are automatically cached in main memory: | 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. | * Functions will be invalidated and parsed again if the timestamp of their module changes. | ||
| Line 22: | Line 21: | ||
<pre class="brush:xquery"> | <pre class="brush:xquery"> | ||
module namespace page = 'http://basex.org/modules/web-page'; | module namespace page = 'http://basex.org/modules/web-page'; | ||
| + | |||
| + | import module namespace ws = "http://basex.org/modules/Websocket"; | ||
| + | |||
declare | declare | ||
%ws:connect("/") | %ws:connect("/") | ||
| − | function | + | function page:connect( |
) { | ) { | ||
(: Do something after a client connects to the path "/" :) | (: Do something after a client connects to the path "/" :) | ||
}; | }; | ||
| − | |||
| − | |||
| − | |||
declare | declare | ||
%ws:message("/","{$message}") | %ws:message("/","{$message}") | ||
| − | function | + | function page:message( |
$message as xs:string | $message as xs:string | ||
) { | ) { | ||
(: Do something if a message arrives at the server :) | (: Do something if a message arrives at the server :) | ||
}; | }; | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
declare | declare | ||
%ws:close("/") | %ws:close("/") | ||
function chat: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) | |
| − | + | }; | |
</pre> | </pre> | ||
| Line 65: | Line 59: | ||
* Enable the WebSocket servlet in the web.xml. You can set here the maxIdleTime, maxTextMessageSize and maxBinaryMessageSize too. | * 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. | * 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. | ||
| + | |||
<pre class="brush:xml"> | <pre class="brush:xml"> | ||
<servlet> | <servlet> | ||
| Line 89: | Line 84: | ||
==ws:connect(path)== | ==ws:connect(path)== | ||
| − | Called | + | Called directly after a successful WebSocket handshake. The <code>path</code> specifies the path to which a client is connected to. |
==ws:message(path,message)== | ==ws:message(path,message)== | ||
| − | Called when a <code>message</code> arrives at the server. The <code>path</code> specifies the | + | Called when a <code>message</code> arrives at the server. The <code>path</code> specifies the path to which a client is connected to. The <code>message</code> is the <code>message</code> sent by the client. Could be a text-message or a binary-message. |
==ws:close(path)== | ==ws:close(path)== | ||
| − | Called when the WebSocket closes. The <code>path</code> specifies the | + | Called when the WebSocket closes. The <code>path</code> 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. | The WebSocket is already closed when this annotation is called so there can be no return. | ||
| − | ==ws:error(path,message) | + | ==ws:error(path, message)== |
| − | |||
| − | |||
| − | |||
| − | |||
| − | The | + | Called when an error has occurred. Usually, this happens because of bad/malformed incoming packets. The <code>path</code> specifies the path to which a client is connected to. The <code>message</code> is the error message. The WebSocket connection gets closed after the error handling. |
==ws:header-param(name,variable[,default]== | ==ws:header-param(name,variable[,default]== | ||
Revision as of 16:31, 31 August 2018
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.
Contents
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.