Difference between revisions of "WebSocket Module"
Jump to navigation
Jump to search
(21 intermediate revisions by 2 users not shown) | |||
Line 3: | Line 3: | ||
=Conventions= | =Conventions= | ||
− | * The {{Code|basex-api}} | + | * The module will be available if the {{Code|basex-api}} library is found in the classpath. This is the case if you use one of the complete distributions of BaseX (zip, exe, war). |
− | * All functions and errors are assigned to the <code><nowiki>http://basex.org/modules/ | + | * All functions and errors are assigned to the <code><nowiki>http://basex.org/modules/ws</nowiki></code> namespace, which is statically bound to the {{Code|ws}} prefix. Prior to {{Version|9.2}}, the module needed to be imported in the query prolog: |
+ | |||
<pre class="brush:xquery"> | <pre class="brush:xquery"> | ||
− | import module namespace ws = "http://basex.org/modules/ | + | import module namespace ws = "http://basex.org/modules/ws"; |
... | ... | ||
</pre> | </pre> | ||
− | =Functions= | + | * As sessions are side-effecting operations, all functions are flagged as ''non-deterministic''. As a result, some query optimizations will be suppressed. |
+ | |||
+ | =General Functions= | ||
+ | |||
+ | ==ws:id== | ||
+ | |||
+ | {| width='100%' | ||
+ | |- | ||
+ | | width='120' | '''Signatures''' | ||
+ | |{{Func|ws:id||xs:string}} | ||
+ | |- | ||
+ | | '''Summary''' | ||
+ | |Returns the ID of the current WebSocket. | ||
+ | |- | ||
+ | | '''Errors''' | ||
+ | |{{Error|not-found|#Errors}} No WebSocket with the specified id exists. | ||
+ | |} | ||
+ | |||
+ | ==ws:ids== | ||
+ | |||
+ | {| width='100%' | ||
+ | |- | ||
+ | | width='120' | '''Signatures''' | ||
+ | |{{Func|ws:ids||xs:string*}} | ||
+ | |- | ||
+ | | '''Summary''' | ||
+ | |Returns the ids of all currently registered WebSocket. | ||
+ | |} | ||
+ | |||
+ | ==ws:path== | ||
+ | |||
+ | {| width='100%' | ||
+ | |- | ||
+ | | width='120' | '''Signatures''' | ||
+ | |{{Func|ws:path|$id as xs:string|xs:string}} | ||
+ | |- | ||
+ | | '''Summary''' | ||
+ | |Returns the path of the WebSocket with the specified {{Code|$id}}. | ||
+ | |- | ||
+ | | '''Errors''' | ||
+ | |{{Error|not-found|#Errors}} No WebSocket with the specified id exists. | ||
+ | |} | ||
+ | |||
+ | ==ws:close== | ||
+ | |||
+ | {| width='100%' | ||
+ | |- | ||
+ | | width='120' | '''Signatures''' | ||
+ | |{{Func|ws:close|$id as xs:string|empty-sequence()}} | ||
+ | |- | ||
+ | | '''Summary''' | ||
+ | |Closes the connection of the WebSocket with the specified {{Code|$id}}. | ||
+ | |- | ||
+ | | '''Errors''' | ||
+ | |{{Error|not-found|#Errors}} No WebSocket with the specified id exists. | ||
+ | |} | ||
+ | |||
+ | =Sending Data= | ||
==ws:send== | ==ws:send== | ||
Line 17: | Line 75: | ||
|- | |- | ||
| width='120' | '''Signatures''' | | width='120' | '''Signatures''' | ||
− | |{{Func|ws:send|$message as | + | |{{Func|ws:send|$message as item(), $ids as xs:string*|empty-sequence()}} |
|- | |- | ||
| '''Summary''' | | '''Summary''' | ||
− | |Sends a <code>$message</code> | + | |Sends a <code>$message</code> to the clients with the specified <code>$ids</code>. Ids that cannot be assigned to clients will be ignored. The message will be handled as follows: |
+ | * Items of type {{Code|xs:base64Binary}} and {{Code|xs:hexBinary}} will be transmitted as binary messages. | ||
+ | * Function items (maps, arrays) will be serialized as JSON and transmitted as string messages. | ||
+ | * All other items will be serialized with the default serialization options and transmitted as string messages. | ||
|} | |} | ||
Line 31: | Line 92: | ||
|- | |- | ||
| '''Summary''' | | '''Summary''' | ||
− | |Broadcasts <code>$message</code> | + | |Broadcasts a <code>$message</code> to all connected clients except to the caller. Invocations of this convenience function are equivalent to <code>ws:send($message, ws:ids()[. != ws:id()])</code>. See [[#ws:send|ws:send]] for more details on the message handling. |
|} | |} | ||
Line 42: | Line 103: | ||
|- | |- | ||
| '''Summary''' | | '''Summary''' | ||
− | |Emits a <code>message</code> | + | |Emits a <code>$message</code> to all connected clients. Invocations of this function are equivalent to <code>ws:send($message, ws:ids())</code>. See [[#ws:send|ws:send]] for more details on the message handling. |
|} | |} | ||
− | ==ws:id== | + | ==ws:eval== |
+ | |||
+ | {{Mark|Introduced with 9.2:}} | ||
+ | |||
+ | {| width='100%' | ||
+ | |- | ||
+ | | width='120' | '''Signatures''' | ||
+ | |{{Func|ws:eval|$query as xs:anyAtomicItem|xs:string}}<br />{{Func|ws:eval|$query as xs:anyAtomicItem, $bindings as map(*)?|xs:string}}<br />{{Func|ws:eval|$query as xs:anyAtomicItem, $bindings as map(*)?, $options as map(*)?|xs:string}}<br /> | ||
+ | |- | ||
+ | | '''Summary''' | ||
+ | |Schedules the evaluation of the supplied {{Code|$query}} and returns the result to the calling WebSocket client. The query can be a URI or a string, and variables and context items can be declared via {{Code|$bindings}} (see {{Function|XQuery|xquery:eval}} for more details). The following {{Code|$options}} can be supplied: | ||
+ | * {{Code|base-uri}}: sets the [https://www.w3.org/TR/xquery-31/#dt-static-base-uri base-uri property] for the query. This URI will be used when resolving relative URIs, such as with {{Code|fn:doc}}. | ||
+ | * {{Code|id}}: sets a custom job id. The id must not start with the standard <code>job</code> prefix, and it can only be assigned if no job with the same name exists. | ||
+ | Query scheduling is recommendable if the immediate query execution might be too time consuming and lead to a timeout. | ||
+ | |- | ||
+ | | '''Errors''' | ||
+ | |{{Error|overflow|#Errors}} Query execution is rejected, because too many jobs are queued or being executed. <br/>{{Error|id|#Errors}} The specified id is invalid or has already been assigned. | ||
+ | |- | ||
+ | | '''Examples''' | ||
+ | | | ||
+ | * Schedule a second query that will notify the client 10 seconds later that a message was processed: | ||
+ | <pre class='brush:xquery'> | ||
+ | declare | ||
+ | %ws:message('/tasks', '{$message}') | ||
+ | function local:message($message) { | ||
+ | ws:eval('prof:sleep(10000), "Your message has been processed."') | ||
+ | }; | ||
+ | </pre> | ||
+ | |} | ||
+ | |||
+ | =WebSocket Attributes= | ||
+ | |||
+ | ==ws:get== | ||
{| width='100%' | {| width='100%' | ||
|- | |- | ||
| width='120' | '''Signatures''' | | width='120' | '''Signatures''' | ||
− | |{{Func|ws:id||xs:string}} | + | |{{Func|ws:get|$id as xs:string, $name as xs:string|item()*}}<br/>{{Func|ws:get|$id as xs:string, $name as xs:string, $default as item()*|item()*}} |
|- | |- | ||
| '''Summary''' | | '''Summary''' | ||
− | |Returns the | + | |Returns the value of an attribute with the specified {{Code|$name}} from the WebSocket with the specified {{Code|$id}}. If the attribute is unknown, an empty sequence or the optionally specified {{Code|$default}} value will be returned instead. |
+ | |- | ||
+ | | '''Errors''' | ||
+ | |{{Error|not-found|#Errors}} No WebSocket with the specified id exists. | ||
|} | |} | ||
− | ==ws: | + | ==ws:set== |
{| width='100%' | {| width='100%' | ||
|- | |- | ||
| width='120' | '''Signatures''' | | width='120' | '''Signatures''' | ||
− | |{{Func|ws: | + | |{{Func|ws:set|$id as xs:string, $name as xs:string, $value as item()*|empty-sequence()}} |
|- | |- | ||
| '''Summary''' | | '''Summary''' | ||
− | |Returns the | + | |Returns the specified {{Code|value}} of the attribute with the specified {{Code|$name}} from the WebSocket with the specified {{Mono|$id}}. |
+ | |- | ||
+ | | '''Errors''' | ||
+ | |{{Error|not-found|#Errors}} No WebSocket with the specified id exists.<br>{{Error|set|#Errors}} The supplied value cannot be materialized. | ||
|} | |} | ||
− | ==ws: | + | ==ws:delete== |
{| width='100%' | {| width='100%' | ||
|- | |- | ||
| width='120' | '''Signatures''' | | width='120' | '''Signatures''' | ||
− | |{{Func|ws: | + | |{{Func|ws:delete|$id as xs:string, $name as xs:string|empty-sequence()}} |
|- | |- | ||
| '''Summary''' | | '''Summary''' | ||
− | | | + | |Deletes an attribute with the specified {{Code|$name}} from the WebSocket with the specified {{Mono|$id}}. |
+ | |- | ||
+ | | '''Errors''' | ||
+ | |{{Error|not-found|#Errors}} No WebSocket with the specified id exists. | ||
|} | |} | ||
− | = | + | =Examples= |
− | == | + | ==Example 1== |
<pre class="brush:xquery"> | <pre class="brush:xquery"> | ||
− | + | import module namespace ws = "http://basex.org/modules/ws"; | |
− | import module namespace ws = "http://basex.org/modules/ | ||
declare | declare | ||
− | %ws:connect( | + | %ws:connect('/') |
− | function local:connect( | + | function local:connect() as empty-sequence() { |
− | ) as empty-sequence() { | + | let $id := ws:id() |
− | let $ | + | let $message := json:serialize(map { |
− | let $ | + | 'type': 'Connect', |
− | + | 'id': $id | |
− | + | }) | |
− | + | return ws:broadcast($message) | |
− | |||
− | |||
− | |||
− | |||
− | return ws:broadcast($ | ||
}; | }; | ||
</pre> | </pre> | ||
− | + | '''Explanation:''' | |
− | + | * The function has a <code>%ws:connect</code> annotation. It gets called if a client successfully creates a WebSocket connection to the path <code>/</code> (check out [[WebSockets]] for further information). | |
− | * The <code> | + | * A JSON response is generated, which contains the new client id and a <code>Connect</code> string. |
− | * | + | * This response will be sent to all other connected clients. |
− | * | ||
− | |||
− | =Example 2 | + | ==Example 2== |
− | |||
− | |||
<pre class="brush:xquery"> | <pre class="brush:xquery"> | ||
− | + | import module namespace ws = "http://basex.org/modules/ws"; | |
− | import module namespace ws = "http://basex.org/modules/ | ||
declare | declare | ||
− | %ws:message( | + | %ws:message('/', '{$message}') |
function local:message( | function local:message( | ||
− | $message | + | $message as xs:string |
) as empty-sequence() { | ) as empty-sequence() { | ||
− | let | + | let $message := json:serialize(map { 'message': $message }) |
− | + | return ws:emit($message) | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | return ws:emit($ | ||
}; | }; | ||
+ | </pre> | ||
− | </ | + | '''Explanation:''' |
+ | |||
+ | * The function has a <code>%ws:message</code> annotation. It gets called if a client sends a new message. | ||
+ | * A JSON response is generated, which contains the message string. | ||
+ | * This response will be sent to all connected clients (including the calling client). | ||
+ | |||
+ | =Errors= | ||
+ | |||
+ | {| class="wikitable" width="100%" | ||
+ | ! width="110"|Code | ||
+ | |Description | ||
+ | |- | ||
+ | |{{Code|set}} | ||
+ | |The supplied value cannot be materialized. | ||
+ | |- | ||
+ | |{{Code|not-found}} | ||
+ | |No WebSocket with the specified id exists. | ||
+ | |} | ||
+ | |||
+ | =Changelog= | ||
+ | |||
+ | ;Version 9.2 | ||
− | + | * Added: [[#ws:eval|ws:eval]] | |
− | + | This module was introduced with Version 9.1. | |
− | |||
− | |||
− | |||
− | |||
− |
Revision as of 17:01, 1 February 2019
This XQuery Module contains functions for accessing specific WebSocket functions. This module is mainly useful in the context of WebSockets.
Contents
Conventions
- The module will be available if the
basex-api
library is found in the classpath. This is the case if you use one of the complete distributions of BaseX (zip, exe, war). - All functions and errors are assigned to the
http://basex.org/modules/ws
namespace, which is statically bound to thews
prefix. Prior to Version 9.2, the module needed to be imported in the query prolog:
import module namespace ws = "http://basex.org/modules/ws"; ...
- As sessions are side-effecting operations, all functions are flagged as non-deterministic. As a result, some query optimizations will be suppressed.
General Functions
ws:id
Signatures | ws:id() as xs:string
|
Summary | Returns the ID of the current WebSocket. |
Errors | not-found : No WebSocket with the specified id exists.
|
ws:ids
Signatures | ws:ids() as xs:string*
|
Summary | Returns the ids of all currently registered WebSocket. |
ws:path
Signatures | ws:path($id as xs:string) as xs:string
|
Summary | Returns the path of the WebSocket with the specified $id .
|
Errors | not-found : No WebSocket with the specified id exists.
|
ws:close
Signatures | ws:close($id as xs:string) as empty-sequence()
|
Summary | Closes the connection of the WebSocket with the specified $id .
|
Errors | not-found : No WebSocket with the specified id exists.
|
Sending Data
ws:send
Signatures | ws:send($message as item(), $ids as xs:string*) as empty-sequence()
|
Summary | Sends a $message to the clients with the specified $ids . Ids that cannot be assigned to clients will be ignored. The message will be handled as follows:
|
ws:broadcast
Signatures | ws:broadcast($message as xs:anyAtomicType) as empty-sequence()
|
Summary | Broadcasts a $message to all connected clients except to the caller. Invocations of this convenience function are equivalent to ws:send($message, ws:ids()[. != ws:id()]) . See ws:send for more details on the message handling.
|
ws:emit
Signatures | ws:emit($message as xs:anyAtomicType) as empty-sequence()
|
Summary | Emits a $message to all connected clients. Invocations of this function are equivalent to ws:send($message, ws:ids()) . See ws:send for more details on the message handling.
|
ws:eval
Signatures | ws:eval($query as xs:anyAtomicItem) as xs:string ws:eval($query as xs:anyAtomicItem, $bindings as map(*)?) as xs:string ws:eval($query as xs:anyAtomicItem, $bindings as map(*)?, $options as map(*)?) as xs:string |
Summary | Schedules the evaluation of the supplied $query and returns the result to the calling WebSocket client. The query can be a URI or a string, and variables and context items can be declared via $bindings (see xquery:eval for more details). The following $options can be supplied:
Query scheduling is recommendable if the immediate query execution might be too time consuming and lead to a timeout. |
Errors | overflow : Query execution is rejected, because too many jobs are queued or being executed. id : The specified id is invalid or has already been assigned.
|
Examples |
declare %ws:message('/tasks', '{$message}') function local:message($message) { ws:eval('prof:sleep(10000), "Your message has been processed."') }; |
WebSocket Attributes
ws:get
Signatures | ws:get($id as xs:string, $name as xs:string) as item()* ws:get($id as xs:string, $name as xs:string, $default as item()*) as item()*
|
Summary | Returns the value of an attribute with the specified $name from the WebSocket with the specified $id . If the attribute is unknown, an empty sequence or the optionally specified $default value will be returned instead.
|
Errors | not-found : No WebSocket with the specified id exists.
|
ws:set
Signatures | ws:set($id as xs:string, $name as xs:string, $value as item()*) as empty-sequence()
|
Summary | Returns the specified value of the attribute with the specified $name from the WebSocket with the specified $id .
|
Errors | not-found : No WebSocket with the specified id exists.set : The supplied value cannot be materialized.
|
ws:delete
Signatures | ws:delete($id as xs:string, $name as xs:string) as empty-sequence()
|
Summary | Deletes an attribute with the specified $name from the WebSocket with the specified $id .
|
Errors | not-found : No WebSocket with the specified id exists.
|
Examples
Example 1
import module namespace ws = "http://basex.org/modules/ws"; declare %ws:connect('/') function local:connect() as empty-sequence() { let $id := ws:id() let $message := json:serialize(map { 'type': 'Connect', 'id': $id }) return ws:broadcast($message) };
Explanation:
- The function has a
%ws:connect
annotation. It gets called if a client successfully creates a WebSocket connection to the path/
(check out WebSockets for further information). - A JSON response is generated, which contains the new client id and a
Connect
string. - This response will be sent to all other connected clients.
Example 2
import module namespace ws = "http://basex.org/modules/ws"; declare %ws:message('/', '{$message}') function local:message( $message as xs:string ) as empty-sequence() { let $message := json:serialize(map { 'message': $message }) return ws:emit($message) };
Explanation:
- The function has a
%ws:message
annotation. It gets called if a client sends a new message. - A JSON response is generated, which contains the message string.
- This response will be sent to all connected clients (including the calling client).
Errors
Code | Description |
---|---|
set
|
The supplied value cannot be materialized. |
not-found
|
No WebSocket with the specified id exists. |
Changelog
- Version 9.2
- Added: ws:eval
This module was introduced with Version 9.1.