Is there anyone here that can help with a lucee we...
# lucee
t
Is there anyone here that can help with a lucee websocket gateway implementation?
j
IMHO Lucee doesn't have a great websockets implementation. If its a relatively low volume application, pusher's free plan works pretty well. And this is getting more interesting by the month: https://github.com/soketi/soketi
t
I'm so very not excited about anything built on NodeJS.
j
pusher has a java client - happy to paste the code for making that work
It would be great if coldbox or lucee had integrated websocket support that was easy to configure and use, but neither do. Luis was working on adding it to coldbox at one point, but I don't know where that stands. Pusher is the best solution I've been able to find as it has both frontend and backend clients, and soketi is just an open-source (free) version that uses the same clients
b
The Ortus-built apps using websockets ATM are using RabbitMQ with the web STOMP plugin which works very well. Its scalable and you interact with it in CF with the rabbitSDK and in JS with any Stomp.js lib
It's possible to spin up a one-off Java websocket server in CF but it has a lot of drawbacks (many of which are shared by Lucee's extension) • difficulty in running CF code as it's a java library • Doesn't scale, meaning if you have two web servers, they each have their own websocket listeners and don't talk to each other, so web server one is only able to "push" messages to the browsers who happen to be connected to it • no authentication, you'd have to build it as a layer on top of when a connection is made, which again is difficult to do in CFML
We've talked about building a websocket server into CommandBox, but it also has all the issues above, plus some more such as being proprietary to the CommandBox web server and useless to anyone not deploying to CommandBox on production
j
soketi running on cloudflare sure sounds interesting
e
I am not sure why WebSockets is some kind of mystical art akin to the realms of magic and mysticism in ColdFusion. Make sure you uncomment the websocks in your proxy install and restart lucee then use the following code will help you get the basic idea.. A socket is nothing more than a port opening knock, and response of said knock.. IE knock knock (send) who is there (the response) <cfwebsocket name="chattyKathy" onMessage="handleMessage"> <cffunction name="handleMessage"> <cfargument name="event" type="struct"> <cfset var message = event.data> <cfset var username = event.username> <cfwebsocket type="broadcast" message="#username#: #message#"> </cffunction> <html> <head> <script> const socket = new WebSocket("ws://#cgi.server_name##cgi.script_name#"); socket.onmessage = function (event) { const messages = document.querySelector("#messages"); const message = document.createElement("li"); message.innerText = event.data; messages.appendChild(message); }; document.forms[0].onsubmit = function () { const input = document.querySelector("#input"); socket.send(input.value); input.value = ""; return false; }; </script> </head> <body> <ul id="messages"></ul> <form> <input id="input" type="text"> <button type="submit">Send</button> </form> </body> </html> </cfwebsocket>
Oh sorry, you said Lucee, the above works for AFC, this will work in lucee, <cfscript> websocket = createObject("websocket", "chattyKathy"); websocket.onMessage = function(event) { var message = event.getData(); var username = event.getUsername(); websocket.broadcast(username & ": " & message); }; </cfscript> <html> <head> <script> const socket = new WebSocket("ws://#cgi.server_name##cgi.script_path#"); socket.onmessage = function (event) { const messages = document.querySelector("#messages"); const message = document.createElement("li"); message.innerText = event.data; messages.appendChild(message); }; document.forms[0].onsubmit = function () { const input = document.querySelector("#input"); socket.send(input.value); input.value = ""; return false; }; </script> </head> <body> <ul id="messages"></ul> <form> <input id="input" type="text"> <button type="submit">Send</button> </form> </body> </html>
b
Are you sure?
Copy code
CFSCRIPT-REPL: createObject("websocket", "chattyKathy")
ERROR

Invalid argument for function createObject, first argument (type), must be (com, java, webservice or component) other types are not supported
websocket
is not a valid input to the first param of createObject https://docs.lucee.org/reference/functions/createobject.html
e
Wrap it in a component.
b
That's... not how websockets work.
e
<cfcomponent output="false" hint="I handle WebSockets"> <cffunction name="onMessage"> <cfargument name="event" type="struct"> <cfset var message = event.data> <cfset var username = event.username> <cfset var response = { type = "broadcast", message = "#username#: #message#" }> <cfcontent type="application/json"> <cfoutput>#serializeJson(response)#</cfoutput> </cffunction> </cfcomponent> <html> <head> <script> const socket = new WebSocket("ws://#cgi.server_name##cgi.script_path#"); socket.onmessage = function (event) { const message = JSON.parse(event.data); const messages = document.querySelector("#messages"); const li = document.createElement("li"); li.innerText = message.message; messages.appendChild(li); }; document.forms[0].onsubmit = function () { const input = document.querySelector("#input"); socket.send(input.value); input.value = ""; return false; }; </script> </head> <body> <ul id="messages"></ul> <form> <input id="input" type="text"> <button type="submit">Send</button> </form> </body> </html>
Here is the basis for making a javascript knocker in CF using a json on response call. You may want to look at taffy as it handles json better, or you may want to look more into using javascript or java to further play around with this.