Appearance
MARS Engine WebSockets API
The MARS Engine provides robust WebSocket support with built-in session handling group messaging, and broadcast control. WebSockets can be used to build real-time features like chat, presence, dashboards, and collaborative interfaces.
Introduction
To define a WebSocket, create a file in your project and set its type to WebSocket in the file type configuration of the dialog.
This script will then handle WebSocket connections, including incoming messages, disconnection events, and session-based logic.
Every WebSockets endpoint has three possible activations:
- OnOpen - Handles the initial connection. You can use this to set an ID to the connection and do setup.
- OnMessage - Handles the messages from the client.
- OnDisconnect - Handles the connection teardown, you can use this for cleanup, setting database statuses and closing resources.
These are shown as the three tabs above the code editor.
Example 1 - Hello World Websocket
The first two tabs (onOpen and onMessage are server-side and are meant to be done on MARS Engine).
The third tab is a helpful HTML page you can use to connect to the server. You can set the HTML on MARS Engine by creating a new Text file and naming it exactly the same and running it on the server.
This example assumes your Websocket is in a folder called ws and has a websocket file ws01.
For example:
PROJECT ROOT
├── ws/
│ └── ws01
└ ws_client.html (optional)js
// Will send "Hello World" to the client when connected
write({message: "Hello World"});js
// Will send "Hello Client" back to the client when any message is received
write({message: "Hello Client"});html
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="result"></div>
<script>
// You can get this when you click on "Run site"
// What opens in your browser is your Site URL
// Remember to remove the "http://" or "https://"
const YOUR_SITE_URL = "example.mars2.mars-hosting.com"
// use 'ws:' if you don't have an SSL certificate
// use 'wss:' if you have an SSL certificate
// In short: ws for http, wss for https
let ws = new WebSocket(`wss://${YOUR_SITE_URL}/ws/ws01`);
ws.addEventListener("open", (event) => {
// Send a message to the server as soon as the connection is open
ws.send("Hello Server!");
});
// Listen for messages
ws.addEventListener("message", (event) => {
console.log("Message from server ", event.data);
});
</script>
</body>
</html>Example 2 - Authenticated sockets, setId, and role-based groups
You can use this regular (non-websocket) JavaScript API to store the user session and get the Session ID (sid) for the next example.
js
// A list of random names
let names = ["John Doe","Mary Sue","Ezekiel Campbell", "Suzy Lee"];
let sid = session();
session('user', {
'usr_id': Math.floor(Math.random()*100),
'usr_displayname': names[Math.floor(Math.random()*names.length)],
'usr_role': 'admin' // Change this to join a different group
});
let sessionUser = session('user')
write('user', sessionUser);
write('sid', sid);You can get the sid from the JSON response from the server by opening the API file in the MARS Editor and choosing Run file from the Run dropdown menu.
Then proceed to the following example and use the sid in the ws_client_example02.html.
Create a websocket file named ws02 in the ws folder.
js
// Reject anonymous sockets; tag the connection; auto-join useful groups
const user = session('user');
if (!user) {
write({'message':'not-logged-in'});
disconnect();
return;
}
// IMPORTANT: You need to make sure your ID is unique, otherwise the connection will
// be severed
setId(String(user.usr_id)); // so you can correlate socket-user later
addToGroup(`user:${user.usr_id}`); // personal fanout
if (user.usr_role) addToGroup(`role:${user.usr_role}`); // staff, admin, agent, etc.
write({ type: 'welcome', id: getId() });js
// Optional: mark presence in DB, log audit, etc.html
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="result"></div>
<script>
// You can get this when you click on "Run site"
// What opens in your browser is your Site URL
// Remember to remove the "http://" or "https://"
const YOUR_SITE_URL = "example.mars-2.mars-hosting.com"
const sid = 'FGgurm3lH1wD3YBkfbHvN1WmEYztVd2T'; //session ID
let ws = new WebSocket(`wss://${YOUR_SITE_URL}/ws/ws02?sid=${sid}`);
// Listen for messages
ws.addEventListener("message", (event) => {
console.log("Message from server ", event.data);
});
</script>
</body>
</html>Example 3 - Minimal JSON router (ping, echo, join/leave, broadcast)
js
let msg;
try {
msg = JSON.parse(message);
} catch {
write({ type: 'error', error: 'invalid-json' });
exit();
}
switch (msg.type) {
case 'ping':
write({ type: 'pong', ts: Date.now() });
break;
case 'echo':
write({ type: 'echo', data: msg.data ?? null });
break;
case 'join':
// join a "room:{id}" group for chat/collab
if (!msg.roomId) return write({ type: 'error', error: 'missing-roomId' });
addToGroup(`room:${msg.roomId}`);
write({ type: 'joined', roomId: msg.roomId });
break;
case 'leave':
if (!msg.roomId) return write({ type: 'error', error: 'missing-roomId' });
removeFromGroup(`room:${msg.roomId}`);
write({ type: 'left', roomId: msg.roomId });
break;
case 'broadcast':
// server-side fanout to a group (not including sender)
if (!msg.group || !('data' in msg)) {
return write({ type: 'error', error: 'missing-group-or-data' });
}
const ws = websockets('api_v1/websocket/ws'); // path to this WS endpoint
const channels = ws.group(msg.group);
if (!channels) return write({ type: 'error', error: 'group-not-found' });
channels.write({ type: 'broadcast', from: getId(), data: msg.data });
break;
default:
write({ type: 'error', error: 'unknown-type' });
}html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WS Test Page</title>
<style>
body { font-family: sans-serif; padding: 20px; }
#log { border: 1px solid #ccc; padding: 10px; height: 300px; overflow-y: auto; white-space: pre-wrap; }
button { margin: 5px; }
input { padding: 5px; margin: 5px; }
</style>
</head>
<body>
<h2>WebSocket Test</h2>
<div id="log"></div>
<div>
<div>
<input id="echoInput" type="text" placeholder="Enter message for echo" />
<button onclick="sendEcho()">Send Echo</button>
</div>
<button onclick="joinRoom()">Join Room</button>
<button onclick="leaveRoom()">Leave Room</button>
<button onclick="sendBroadcast()">Broadcast</button>
</div>
<script>
// You can get this when you click on "Run site"
// What opens in your browser is your Site URL
// Remember to remove the "http://" or "https://"
const YOUR_SITE_URL = "example.mars-2.mars-hosting.com"
// use 'ws:' if you don't have an SSL certificate
// use 'wss:' if you have an SSL certificate
// In short: ws for http, wss for https
const ws = new WebSocket(`wss://${YOUR_SITE_URL}/ws/ws03`);
const logDiv = document.getElementById("log");
function log(msg) {
logDiv.innerText += msg + "\n";
logDiv.scrollTop = logDiv.scrollHeight;
}
ws.addEventListener("open", () => {
log("✅ Connected to WS server");
// automatically send ping every 10 seconds
setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ type: "ping" }));
log("➡️ Sent: ping");
}
}, 10000);
});
ws.addEventListener("message", (e) => log("📩 " + e.data));
ws.addEventListener("close", () => log("❌ Disconnected"));
ws.addEventListener("error", (e) => log("⚠️ Error: " + e));
// === Test messages ===
function sendEcho() {
const input = document.getElementById("echoInput");
const msg = input.value.trim() || "Hello WS!";
ws.send(JSON.stringify({ type: "echo", data: msg }));
log(`➡️ Sent: echo {${msg}}`);
input.value = "";
}
function joinRoom() {
ws.send(JSON.stringify({ type: "join", roomId: "test-room" }));
log("➡️ Sent: join room:test-room");
}
function leaveRoom() {
ws.send(JSON.stringify({ type: "leave", roomId: "test-room" }));
log("➡️ Sent: leave room:test-room");
}
function sendBroadcast() {
ws.send(JSON.stringify({ type: "broadcast", group: "room:test-room", data: "Hello group!" }));
log("➡️ Sent: broadcast to room:test-room");
}
</script>
</body>
</html>Websocket Utility Functions
setId(id)
The setId() function is a function you can ONLY call in the onOpen method. It sets the websocket id of the connection to the value you passed. The setId() function accepts the following types: Number, String.
IMPORTANT NOTE: You must make sure that the id being set is unique accross all your current connections otherwise the connection will be cancelled.
getId()
The getId() function allows you to obtain the Websocket ID of the connection that you set in the setId(id) function in onOpen method. This is useful for keeping track of websockets in correlaction with current users.
addToGroup(groupId)
Adds the current socket to a group. The function accepts String as a groupId.
removeFromGroup(groupId)
Removes the current socket from a group. The function accepts String as a groupId.
disconnect()
Closes the current WebSocket connection
write(data)
Sends a message to the current WebSocket