File:  [parser3project] / parser3 / tests / httpd / websocket-app / index.html
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Sat Oct 17 15:13:08 2026 UTC (7 days, 16 hours ago) by moko
Branches: MAIN
CVS tags: HEAD
websocket demo added (related to feature #1310)

# The WebSocket demo: front and back in one file.
# The browser opens the page using a usual request, then the JS opens it using ws://.

@main[]
^if($env:HTTP_UPGRADE eq websocket){
	^back[]
}{
	^front[]
}


# ---------- the server ----------

@back[][message]
^websocket:accept[]
^while(true){
	# wait for a message from the browser, but not longer than a second
	$message[^websocket:receive(0.05)]
	^if($message is hash){
		^if($message.type eq close){
			^break[]
		}
		^answer[$message]
	}
	$counter($counter+1)
	^send_status[]
}


@answer[message]
^if($message.type eq binary){
	^send[ $.type[answer] $.text[got $message.data.size bytes] ]
}($message.data eq ping){
	^send[ $.type[pong] ]
}{
	^send[ $.type[answer] $.text[$message.data?] ]
}


# what the server tells about itself: the time and resources usage
@send_status[]
^send[
	$.type[status]
	$.counter($counter)
	$.time[^date:sql-string[].^eval($status:rusage.tv_usec/1000)[%03.0f]]
	$.utime($status:rusage.utime)
	$.used($status:memory.used)
	$.allocated($status:memory.ever_allocated_since_compact)
]

@send[message]
^websocket:send[^json:string[$message]]


# ---------- the page ----------

@front[]
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>WebSocket demo</title>
</head>
<body align="center">

<h1>WebSocket demo</h1>
<p>Connection: <b id="state">connecting...</b> (to connect again, reload the page)</p>
<p>Server: <span id="server">nothing yet</span></p>

<p><form onsubmit="sendText(); return false;">
	<input id="text" value="Hello">
	<button>Send</button>
	<button type="button" onclick="sendPing()">Ping</button>
	<button type="button" onclick="sendBytes()">Send 1MB</button>
	<button type="button" onclick="socket.close(1000)">Close</button>
</form></p>

<textarea id="log" cols="80" rows="20" readonly></textarea>

<script>
	// same page, but the protocol is WebSocket
	var socket = new WebSocket("ws://" + location.host + "/");
	var state = document.getElementById("state");
	var server = document.getElementById("server");
	var log = document.getElementById("log");
	var pingTime = 0;

	socket.onopen = function () {
		state.textContent = "open";
		addToLog("connected");
	};

	socket.onclose = function (event) {
		state.textContent = "closed";
		addToLog("closed, code " + event.code);
	};

	// the server has sent a message
	socket.onmessage = function (event) {
		var message = JSON.parse(event.data);

		if (message.type == "status") {
			server.textContent =  message.time + " message " + message.counter + ", CPU time " + message.utime.toFixed(2) + " s, " +
				"memory used " + message.used.toFixed() + " KB, allocated since last compact " + message.allocated.toFixed() + " KB";
		} else if (message.type == "answer") {
			addToLog("server answered: " + message.text);
		} else if (message.type == "pong") {
			addToLog("pong, it took " + (Date.now() - pingTime) + " ms");
		}
	};

	function send(data) {
		if (socket.readyState != WebSocket.OPEN) {
			addToLog("not connected");
			return;
		}
		socket.send(data);
		addToLog("sent: " + (typeof data == "string" ? data : data.length + " bytes"));
	}

	function sendText() {
		send(document.getElementById("text").value);
	}

	function sendPing() {
		pingTime = Date.now();
		send("ping");
	}

	// not a text but bytes
	function sendBytes() {
		send(new Uint8Array(1000000));
	}

	function addToLog(line) {
		log.value = new Date().toLocaleTimeString() + " " + line + "\n" + log.value;
	}
</script>

</body>
</html>

E-mail: