This is very basic example code demonstarting web sockets using SWI-Prolog. There are three files, sever.pl, index.html and time.js. While the code could be further refactored it is left in its present form as it is typical of standard use cases.
File: server.pl
:- module(server,[]).
:- use_module(library(http/thread_httpd)).
:- use_module(library(http/http_dispatch)).
:- use_module(library(http/websocket)).
:- initialization
http_server(http_dispatch, [port(8000)]).
:- http_handler(root(.), http_reply_file('index.html', []), []).
:- http_handler(root('time.js'), http_reply_file('time.js', []), []).
:- http_handler(root(time),
http_upgrade_to_websocket(time_handler, []),
[spawn([])]).
time_handler(WebSocket) :-
ws_receive(WebSocket, Message, [format(json)]), % This waits until a message is received.
(
Message.opcode == close
->
true
;
time_response(Response_dict),
ws_send(WebSocket, json(Response_dict)),
time_handler(WebSocket)
).
time_response(Response_dict) :-
get_time(Time),
format_time(string(Message), '%c', Time),
dict_create(Data, _, [message-Message]),
dict_create(Response_dict, _, [data-Data,format-json,opcode-text]).
File: index.html
<!DOCTYPE html>
<html>
<head>
<title>Web Socket Example</title>
<script charset="utf-8" src="time.js"></script>
</head>
<body>
<h2>Current Time</h2>
<p id="time"> </p>
<button id="message-submit" type="button">Get current time</button>
</body>
</html>
File: time.js
// Called when page loads
document.addEventListener('DOMContentLoaded', (e) => {
const input_button = document.getElementById("message-submit")
const connection = openWebSocket()
input_button.addEventListener("click", (event) => {
connection.send(JSON.stringify(""))
})
})
// Called by addEventListener to get the connection when page loads
function openWebSocket() {
connection = new WebSocket("ws://" + window.location.host + "/time")
connection.onerror = (error) => {
console.log(error)
}
connection.onmessage = wsMessageHandler
return connection
}
// Called when Web Socket message arrives.
function wsMessageHandler(event) {
const payload = JSON.parse(event.data)
const message = payload.data.message
document.getElementById("time").innerHTML = message
}
Example run
Using SWI-Prolog
Welcome to SWI-Prolog (threaded, 64 bits, version 9.1.6)
...
?- working_directory(_,'C:/Users/Groot)').
true.
?- [server].
% Started server at http://localhost:8000/
true.
?-
then using an Internet browser
The page will load looking like this

click Get current time will update the time and look like this

Prompt
Explain code to a programmer new to Prolog, HTML and JavaScript.
Note: All of the code above was included in the prompt
ChatGPT Completion
This code sets up a simple web socket server that responds to requests for the current time.
The
server.plmodule sets up the server using thehttp_serverpredicate from thehttp/thread_httpdlibrary. It also registers several handlers for different URLs.The handler for the root URL (
/) responds with theindex.htmlfile, which contains a button and a placeholder for the current time.The handler for the
/timeURL upgrades the connection to a web socket and passes it to thetime_handlerpredicate. This predicate waits for a message from the web socket and then responds with the current time in a JSON format. It then waits for another message and repeats the process.The
index.htmlfile contains a script (time.js) that sets up an event listener on the button. When the button is clicked, it sends an empty JSON message to the web socket connection.The script also defines two functions (
openWebSocketandwsMessageHandler) that handle the web socket connection.openWebSocketsets up the connection and registers a message handler.wsMessageHandlerextracts the time from the JSON payload and updates the placeholder in the HTML file.Overall, this code demonstrates a simple example of a web socket server and client that communicate using JSON messages.
For more basic examples of working code see
If you know web sockets you will notice that this is not demonstrating an automatic push of data to the page. That can be easily be done but that makes the very basic example a bit more complicated and picks a specific use case so was not done.
Note: You may find it difficult to get ChatGPT to generate such an example as it struggles with certain parts of SWI-Prolog. The lack of examples for certain modules and predicates means that ChatGPT often hallucinates to get a completion which can be incorrect. However, if you are a skilled Prolog programmer, you can work out the kinks. The prompt can became so detailed in instructions that it was not worth using ChatGPT.
Enjoy