diff --git a/racketmq/htdocs/client.html b/racketmq/htdocs/client.html
new file mode 100644
index 0000000..961ff29
--- /dev/null
+++ b/racketmq/htdocs/client.html
@@ -0,0 +1,44 @@
+
+
+
+
+ WebSub Client
+
+
+
+
+ WebSub Client
+ Subscription
+
+
+
+
+ Latest Notification
+
+
+ Canonical Hub URL |
+ |
+
+
+ Canonical Topic URL |
+ |
+
+
+ Content-Type |
+ |
+
+
+ Timestamp |
+ |
+
+
+ Content |
+ |
+
+
+
+
diff --git a/racketmq/htdocs/client.js b/racketmq/htdocs/client.js
new file mode 100644
index 0000000..e27c09f
--- /dev/null
+++ b/racketmq/htdocs/client.js
@@ -0,0 +1,50 @@
+var sock;
+
+window.addEventListener('load', function () {
+ function reconnect() {
+ if (sock) {
+ var oldsock = sock;
+ sock = null;
+ oldsock.close();
+ }
+
+ var topic = document.getElementById('topic').value.trim();
+
+ if (topic) {
+ var loc = new URL(document.location);
+ loc.protocol = (document.location.protocol === 'https:' ? 'wss:' : 'ws:');
+ loc.pathname = '/hub';
+ loc.search = 'hub.topic=' + encodeURIComponent(topic) + '&hub.poll_interval_seconds=10';
+
+ sock = new WebSocket(loc);
+ sock.onopen = function (e) {
+ console.log('sock onopen', e);
+ };
+ sock.onmessage = function (e) {
+ var msg = JSON.parse(e.data);
+ console.log('sock onmessage', msg);
+ document.getElementById('canonical-hub').innerText = msg.link.hub;
+ document.getElementById('canonical-topic').innerText = msg.link.self;
+ document.getElementById('content-type').innerText = msg['content-type'] ||
+ 'Unknown (assuming "text/plain", trying utf-8 first, falling back to latin-1)';
+ document.getElementById('timestamp').innerText = new Date();
+
+ var content_latin1 = atob(msg['content-base64']);
+ try {
+ document.getElementById('content').innerText = decodeURIComponent(escape(content_latin1));
+ } catch (exn) {
+ document.getElementById('content').innerText = content_latin1;
+ }
+ };
+ sock.onclose = function (e) {
+ if (sock !== null) {
+ console.log('sock onclose', e);
+ setTimeout(reconnect, 5000);
+ }
+ };
+ }
+ }
+
+ document.getElementById('topic').onchange = reconnect;
+ reconnect();
+});