.. index:: single: http_websocket
.. _http_websocket/0:

.. rst-class:: right

**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`` :ref:`options <options/0>`
| **Uses:**
|    :ref:`http_client <http_client/0>`
|    :ref:`http_core <http_core/0>`
|    :ref:`http_websocket_client_service(HTTPTransport) <http_websocket_client_service/1>`
|    :ref:`http_websocket_client_session <http_websocket_client_session/0>`
|    :ref:`http_websocket_messages <http_websocket_messages/0>`
|    :ref:`http_websocket_server_service(HTTPTransport) <http_websocket_server_service/1>`
|    :ref:`http_websocket_server_session <http_websocket_server_session/0>`
|    :ref:`json <json/0>`
|    :ref:`list <list/0>`
|    :ref:`term_io <term_io/0>`
|    :ref:`url(Representation) <url/1>`

| **Remarks:**
|    (none)

| **Inherited public predicates:**
|     :ref:`options_protocol/0::check_option/1`  :ref:`options_protocol/0::check_options/1`  :ref:`options_protocol/0::default_option/1`  :ref:`options_protocol/0::default_options/1`  :ref:`options_protocol/0::option/2`  :ref:`options_protocol/0::option/3`  :ref:`options_protocol/0::valid_option/1`  :ref:`options_protocol/0::valid_options/1`  

.. contents::
   :local:
   :backlinks: top

Public predicates
-----------------

.. index:: open/2
.. _http_websocket/0::open/2:

``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)``


------------

.. index:: open/3
.. _http_websocket/0::open/3:

``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)``


------------

.. index:: accept/3
.. _http_websocket/0::accept/3:

``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)``


------------

.. index:: accept/4
.. _http_websocket/0::accept/4:

``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)``


------------

.. index:: send/2
.. _http_websocket/0::send/2:

``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)``


------------

.. index:: send/3
.. _http_websocket/0::send/3:

``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)``


------------

.. index:: receive/2
.. _http_websocket/0::receive/2:

``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)``


------------

.. index:: receive/3
.. _http_websocket/0::receive/3:

``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)``


------------

.. index:: close/1
.. _http_websocket/0::close/1:

``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)``


------------

.. index:: close/2
.. _http_websocket/0::close/2:

``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)``


------------

.. index:: property/2
.. _http_websocket/0::property/2:

``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``


------------

.. index:: send_text/2
.. _http_websocket/0::send_text/2:

``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)``


------------

.. index:: receive_text/2
.. _http_websocket/0::receive_text/2:

``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)``


------------

.. index:: send_binary/2
.. _http_websocket/0::send_binary/2:

``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)``


------------

.. index:: receive_binary/2
.. _http_websocket/0::receive_binary/2:

``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)``


------------

.. index:: send_json/2
.. _http_websocket/0::send_json/2:

``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)``


------------

.. index:: receive_json/2
.. _http_websocket/0::receive_json/2:

``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)``


------------

.. index:: send_term/2
.. _http_websocket/0::send_term/2:

``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)``


------------

.. index:: receive_term/2
.. _http_websocket/0::receive_term/2:

``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)``


------------

.. index:: open_session/4
.. _http_websocket/0::open_session/4:

``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)``


------------

.. index:: open_session/5
.. _http_websocket/0::open_session/5:

``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)``


------------

.. index:: serve_once/5
.. _http_websocket/0::serve_once/5:

``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)``


------------

.. index:: serve_once/6
.. _http_websocket/0::serve_once/6:

``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
------------------

.. index:: handle_seed_/1
.. _http_websocket/0::handle_seed_/1:

``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``


------------

.. index:: handle_state_/9
.. _http_websocket/0::handle_state_/9:

``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)

