object

# `http_websocket`

High-level WebSocket predicates for opening and closing connections, exchanging messages, and running common client and server session loops.

Availability:
`logtalk_load(http_websocket(loader))`
Author: Paulo Moura
Version: 1:0:0
Date: 2026-07-09
Compilation flags:
`static, context_switching_calls`
Imports:
`public` options
Uses:
http_client
http_core
http_websocket_client_service(HTTPTransport)
http_websocket_client_session
http_websocket_messages
http_websocket_server_service(HTTPTransport)
http_websocket_server_session
json
list
term_io
url(Representation)
Remarks:
(none)
Inherited public predicates:
check_option/1 check_options/1 default_option/1 default_options/1 option/2 option/3 valid_option/1 valid_options/1

## Public predicates

### `open/2`

Opens a client WebSocket connection to the given `ws://` or `wss://` URL and returns an opaque handle managed by this object.

Compilation flags:
`static`
Template:
`open(URL,WebSocket)`
Mode and number of proofs:
`open(+atom,-compound)` - `one_or_error`
Exceptions:
`URL` is a variable:
`instantiation_error`
`URL` is not a supported absolute WebSocket URL:
`domain_error(http_client_websocket_url,URL)`
`URL` uses an unsupported WebSocket scheme:
`domain_error(http_client_websocket_scheme,Scheme)`

### `open/3`

Opens a client WebSocket connection to the given URL, returning an opaque handle. Client handshake options are forwarded to `http_client::open_websocket/4`. The direct API also accepts `auto_pong(on|off)` and `max_payload_length(Bytes|none)` options.

Compilation flags:
`static`
Template:
`open(URL,WebSocket,Options)`
Mode and number of proofs:
`open(+atom,-compound,+list)` - `one_or_error`
Exceptions:
`URL` is a variable:
`instantiation_error`
`URL` is not a supported absolute WebSocket URL:
`domain_error(http_client_websocket_url,URL)`
`URL` uses an unsupported WebSocket scheme:
`domain_error(http_client_websocket_scheme,Scheme)`
`Options` is a variable or a partial list:
`instantiation_error`
`Options` is neither a variable nor a list:
`type_error(list,Options)`
`Options` contains an invalid direct WebSocket option:
`domain_error(http_websocket_option,Option)`
`Options` contains an invalid WebSocket client option:
`domain_error(http_client_websocket_option,Option)`
The WebSocket server response is not a valid opening handshake response:
`domain_error(http_client_websocket_response,Response)`

### `accept/3`

Accepts one incoming WebSocket connection on the given listener using the default opening-handshake policy and returns an opaque server-side handle together with the accepted client information.

Compilation flags:
`static`
Template:
`accept(Listener,WebSocket,ClientInfo)`
Mode and number of proofs:
`accept(+compound,-compound,-compound)` - `one_or_error`
Exceptions:
The WebSocket opening request does not exist:
`existence_error(http_socket_transport_websocket_request,Request)`
The WebSocket opening response is invalid:
`domain_error(http_socket_transport_websocket_response,Response)`

### `accept/4`

Accepts one incoming WebSocket connection on the given listener and returns an opaque server-side handle. Server opening-handshake options are forwarded to `http_server_core::accept_websocket/3`. The direct API also accepts `auto_pong(on|off)` and `max_payload_length(Bytes|none)` options.

Compilation flags:
`static`
Template:
`accept(Listener,WebSocket,ClientInfo,Options)`
Mode and number of proofs:
`accept(+compound,-compound,-compound,+list)` - `one_or_error`
Exceptions:
`Options` is a variable or a partial list:
`instantiation_error`
`Options` is neither a variable nor a list:
`type_error(list,Options)`
`Options` contains an invalid direct WebSocket option:
`domain_error(http_websocket_option,Option)`
The WebSocket opening request does not exist:
`existence_error(http_socket_transport_websocket_request,Request)`
The WebSocket opening response is invalid:
`domain_error(http_socket_transport_websocket_response,Response)`

### `send/2`

Writes one outbound WebSocket message using the opaque handle. Accepts normalized `message(Type, Payload)` terms and the convenience wrappers `text(Text)`, `binary(Bytes)`, `ping(Bytes)`, `pong(Bytes)`, `close(Payload)`, `json(JSON)`, and `term(Term)`.

Compilation flags:
`static`
Template:
`send(WebSocket,Message)`
Mode and number of proofs:
`send(+compound,+term)` - `one_or_error`
Exceptions:
`WebSocket` is a variable:
`instantiation_error`
`WebSocket` is not an open opaque WebSocket handle:
`domain_error(http_websocket_handle,WebSocket)`
`WebSocket` refers to a closed opaque WebSocket handle:
`existence_error(http_websocket_handle,WebSocket)`
`Message` is not a valid outbound WebSocket message:
`domain_error(http_websocket_message,Message)`

### `send/3`

Writes one outbound WebSocket message using the opaque handle and the given write options, forwarding those options to the underlying session `write_message/5` predicate.

Compilation flags:
`static`
Template:
`send(WebSocket,Message,Options)`
Mode and number of proofs:
`send(+compound,+term,+list)` - `one_or_error`
Exceptions:
`WebSocket` is a variable:
`instantiation_error`
`WebSocket` is not an open opaque WebSocket handle:
`domain_error(http_websocket_handle,WebSocket)`
`Message` is not a valid outbound WebSocket message:
`domain_error(http_websocket_message,Message)`
`Options` is a variable or a partial list:
`instantiation_error`
`Options` is neither a variable nor a list:
`type_error(list,Options)`
`Options` contains an invalid write option:
`domain_error(http_websocket_session_write_option,Option)`

### `receive/2`

Reads the next normalized WebSocket message using the opaque handle. Returns `end_of_file` when the peer closes the transport before another message is available.

Compilation flags:
`static`
Template:
`receive(WebSocket,Message)`
Mode and number of proofs:
`receive(+compound,-term)` - `one_or_error`
Exceptions:
`WebSocket` is a variable:
`instantiation_error`
`WebSocket` is not an open opaque WebSocket handle:
`domain_error(http_websocket_handle,WebSocket)`
`WebSocket` refers to a closed opaque WebSocket handle:
`existence_error(http_websocket_handle,WebSocket)`
The inbound WebSocket session sequence is invalid:
`domain_error(http_websocket_session_sequence,Frame)`

### `receive/3`

Reads the next normalized WebSocket message using the opaque handle and the given read options. The direct API accepts per-call `auto_pong(on|off)` and `max_payload_length(Bytes|none)` overrides.

Compilation flags:
`static`
Template:
`receive(WebSocket,Message,Options)`
Mode and number of proofs:
`receive(+compound,-term,+list)` - `one_or_error`
Exceptions:
`WebSocket` is a variable:
`instantiation_error`
`WebSocket` is not an open opaque WebSocket handle:
`domain_error(http_websocket_handle,WebSocket)`
`Options` is a variable or a partial list:
`instantiation_error`
`Options` is neither a variable nor a list:
`type_error(list,Options)`
`Options` contains an invalid direct WebSocket option:
`domain_error(http_websocket_option,Option)`
The inbound WebSocket session sequence is invalid:
`domain_error(http_websocket_session_sequence,Frame)`

### `close/1`

Best-effort graceful close of the WebSocket handle using the normal close payload `empty`.

Compilation flags:
`static`
Template:
`close(WebSocket)`
Mode and number of proofs:
`close(+compound)` - `one_or_error`
Exceptions:
`WebSocket` is a variable:
`instantiation_error`
`WebSocket` is not an open opaque WebSocket handle:
`domain_error(http_websocket_handle,WebSocket)`
`WebSocket` refers to a closed opaque WebSocket handle:
`existence_error(http_websocket_handle,WebSocket)`

### `close/2`

Best-effort graceful close of the WebSocket handle using the given close payload, which must be valid for a normalized `message(close, Payload)` term.

Compilation flags:
`static`
Template:
`close(WebSocket,Payload)`
Mode and number of proofs:
`close(+compound,+term)` - `one_or_error`
Exceptions:
`WebSocket` is a variable:
`instantiation_error`
`WebSocket` is not an open opaque WebSocket handle:
`domain_error(http_websocket_handle,WebSocket)`
`Payload` is not a valid close payload:
`domain_error(http_websocket_close_payload,Payload)`

### `property/2`

Enumerates properties of an open opaque WebSocket handle. Supported properties are `role(Role)`, `transport(Transport)`, `response(Response)`, `connection(Connection)`, `state(State)`, `client_info(ClientInfo)`, and `subprotocol(Protocol)`.

Compilation flags:
`static`
Template:
`property(WebSocket,Property)`
Mode and number of proofs:
`property(+compound,+compound)` - `zero_or_one`
`property(+compound,-compound)` - `zero_or_more`

### `send_text/2`

Convenience wrapper for sending one text message.

Compilation flags:
`static`
Template:
`send_text(WebSocket,Text)`
Mode and number of proofs:
`send_text(+compound,+atom)` - `one_or_error`
Exceptions:
`WebSocket` is not an open opaque WebSocket handle:
`domain_error(http_websocket_handle,WebSocket)`
`Text` is not a valid text payload:
`domain_error(http_websocket_message_text,Text)`

### `receive_text/2`

Reads the next message and returns its text payload when the message type is `text`. Returns `end_of_file` unchanged.

Compilation flags:
`static`
Template:
`receive_text(WebSocket,Text)`
Mode and number of proofs:
`receive_text(+compound,-term)` - `one_or_error`
Exceptions:
`WebSocket` is not an open opaque WebSocket handle:
`domain_error(http_websocket_handle,WebSocket)`
The received message is not a text message:
`domain_error(http_websocket_text_message,Message)`

### `send_binary/2`

Convenience wrapper for sending one binary message.

Compilation flags:
`static`
Template:
`send_binary(WebSocket,Bytes)`
Mode and number of proofs:
`send_binary(+compound,+list(byte))` - `one_or_error`
Exceptions:
`WebSocket` is not an open opaque WebSocket handle:
`domain_error(http_websocket_handle,WebSocket)`
`Bytes` is not a valid binary payload:
`domain_error(http_websocket_message,Message)`

### `receive_binary/2`

Reads the next message and returns its binary payload when the message type is `binary`. Returns `end_of_file` unchanged.

Compilation flags:
`static`
Template:
`receive_binary(WebSocket,Bytes)`
Mode and number of proofs:
`receive_binary(+compound,-term)` - `one_or_error`
Exceptions:
`WebSocket` is not an open opaque WebSocket handle:
`domain_error(http_websocket_handle,WebSocket)`
The received message is not a binary message:
`domain_error(http_websocket_binary_message,Message)`

### `send_json/2`

Serializes a JSON term as UTF-8 text and sends it as one text message. Uses curly terms for parsed JSON objects, dashes for parsed JSON pairs, and atoms for parsed JSON strings.

Compilation flags:
`static`
Template:
`send_json(WebSocket,JSON)`
Mode and number of proofs:
`send_json(+compound,+nonvar)` - `one_or_error`
Exceptions:
`WebSocket` is not an open opaque WebSocket handle:
`domain_error(http_websocket_handle,WebSocket)`
`JSON` cannot be serialized as a text WebSocket message:
`domain_error(json_sink,JSON)`

### `receive_json/2`

Reads the next text message and decodes its payload as JSON. Returns `end_of_file` unchanged. Uses curly terms for parsed JSON objects, dashes for parsed JSON pairs, and atoms for parsed JSON strings.

Compilation flags:
`static`
Template:
`receive_json(WebSocket,JSON)`
Mode and number of proofs:
`receive_json(+compound,-term)` - `one_or_error`
Exceptions:
`WebSocket` is not an open opaque WebSocket handle:
`domain_error(http_websocket_handle,WebSocket)`
The received text payload is not valid JSON:
`domain_error(http_websocket_json_text,Text)`

### `send_term/2`

Serializes a Prolog term using canonical write options and sends it as one text message.

Compilation flags:
`static`
Template:
`send_term(WebSocket,Term)`
Mode and number of proofs:
`send_term(+compound,+term)` - `one_or_error`
Exceptions:
`WebSocket` is not an open opaque WebSocket handle:
`domain_error(http_websocket_handle,WebSocket)`
`Term` cannot be serialized as a text WebSocket message:
`domain_error(http_websocket_term_text,Text)`

### `receive_term/2`

Reads the next text message and parses its payload as one Prolog term. Returns `end_of_file` unchanged.

Compilation flags:
`static`
Template:
`receive_term(WebSocket,Term)`
Mode and number of proofs:
`receive_term(+compound,-term)` - `one_or_error`
Exceptions:
`WebSocket` is not an open opaque WebSocket handle:
`domain_error(http_websocket_handle,WebSocket)`
The received text payload is not a canonical Prolog term:
`domain_error(http_websocket_term_text,Text)`

### `open_session/4`

Convenience wrapper over `http_websocket_client_service::open/4` that keeps the user in the high-level `http_websocket` surface for callback-driven client sessions.

Compilation flags:
`static`
Template:
`open_session(URL,Handler,Response,State)`
Mode and number of proofs:
`open_session(+atom,+object_identifier,-compound,-compound)` - `one_or_error`
Exceptions:
`URL` is not a supported absolute WebSocket URL:
`domain_error(http_client_websocket_url,URL)`
`Handler` is not a valid WebSocket service handler:
`domain_error(http_websocket_service_handler,Handler)`

### `open_session/5`

Convenience wrapper over `http_websocket_client_service::open/5`.

Compilation flags:
`static`
Template:
`open_session(URL,Handler,Response,State,Options)`
Mode and number of proofs:
`open_session(+atom,+object_identifier,-compound,-compound,+list)` - `one_or_error`
Exceptions:
`URL` is not a supported absolute WebSocket URL:
`domain_error(http_client_websocket_url,URL)`
`Handler` is not a valid WebSocket service handler:
`domain_error(http_websocket_service_handler,Handler)`
`Options` contains an invalid WebSocket client service option:
`domain_error(http_websocket_client_service_option,Option)`
`Options` contains an invalid WebSocket service loop option:
`domain_error(http_websocket_service_option,Option)`

### `serve_once/5`

Convenience wrapper that accepts one incoming WebSocket connection on the given listener, performs the opening handshake using the default server policy, and runs one callback-driven server session.

Compilation flags:
`static`
Template:
`serve_once(Listener,Handler,Response,State,ClientInfo)`
Mode and number of proofs:
`serve_once(+compound,+object_identifier,-compound,-compound,-compound)` - `one_or_error`
Exceptions:
`Handler` is not a valid WebSocket service handler:
`domain_error(http_websocket_service_handler,Handler)`
The WebSocket opening request does not exist:
`existence_error(http_socket_transport_websocket_request,Request)`
The WebSocket opening response is invalid:
`domain_error(http_socket_transport_websocket_response,Response)`

### `serve_once/6`

Convenience wrapper that accepts one incoming WebSocket connection on the given listener and runs one callback-driven server session using the given combined handshake and session options.

Compilation flags:
`static`
Template:
`serve_once(Listener,Handler,Response,State,ClientInfo,Options)`
Mode and number of proofs:
`serve_once(+compound,+object_identifier,-compound,-compound,-compound,+list)` - `one_or_error`
Exceptions:
`Handler` is not a valid WebSocket service handler:
`domain_error(http_websocket_service_handler,Handler)`
`Options` contains an invalid WebSocket service loop option:
`domain_error(http_websocket_service_option,Option)`
The WebSocket opening request does not exist:
`existence_error(http_socket_transport_websocket_request,Request)`
The WebSocket opening response is invalid:
`domain_error(http_socket_transport_websocket_response,Response)`

## Protected predicates

(no local declarations; see entity ancestors if any)

## Private predicates

### `handle_seed_/1`

Last allocated opaque WebSocket handle identifier.

Compilation flags:
`dynamic`
Template:
`handle_seed_(HandleId)`
Mode and number of proofs:
`handle_seed_(?positive_integer)` - `zero_or_one`

### `handle_state_/9`

Stored opaque WebSocket handle state.

Compilation flags:
`dynamic`
Template:
`handle_state_(HandleId,Role,Transport,Connection,Response,ClientInfo,State,AutoPong,MaxPayloadLength)`
Mode and number of proofs:
`handle_state_(?positive_integer,?atom,?object_identifier,?compound,?compound,?term,?compound,?atom,?term)` - `zero_or_more`

## Operators

(none)