ColdFusion WebSocket Tip - saving custom client metadata

This post is more than 2 years old.

With the help of ColdFusion engineer Awdhesh Kumar, I've discovered an important tip with ColdFusion 10 WebSockets I'd like to share. I will admit that I'm still trying to wrap my brain around the details somewhat, but this tip works well and may be useful for others.

Many of the JavaScript APIs that integrate with ColdFusion 10 WebSockets allow for metadata. For example, the publish API allows for an ad hoc message of any form as well as a set of custom headers.

One way I use this feature is in my demo chat applications. The subscribe API also allows for custom headers so I pass along the user's desired username (or chatroom) name when they subscribe.

myWS.subscribe(subscribedChannel, {username:name})

This allows me to use custom logic in the CFC handler to ensure that no two people have the same username:

The logic here is rather simple. The username value I passed in via JavaScript is available at the root level of the subscriberInfo argument passed to the CFC handler. This data persists in the result from wsGetSubscribers. I can just look at that data, and if there is a match, deny the subscription.

Simple, right? But - it turns out that the custom data I see in the subscriber packet returned from wsGetSubscribers is not present in other CFC handlers.

As an example, I wanted to use beforePublish to check the username of the person making the broadcast. This method is passed a publisherInfo struct, which I assumed was the same struct as what I saw returned from wsGetSubscribers. This is not true. As it stands, you do not have to subscribe to a channel to broadcast!

Awdhesh helped me see the difference here, although it took a little while to sink in. Luckily, there is a very simple fix.

In your allowSubscribe handler, you can write custom data to the subscriberInfo.connectionInfo structure. As an example, I did this:

In this example I've both set a hard coded value and copied a value from the subscriber metadata. Obviously you can do whatever you want here. Later on in my publisher info I'll have access to the same data.

Hope this helps!

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA

Archived Comments

Comment 1 by Andy posted on 6/7/2013 at 8:49 PM

I'm making a chat program and I added in userType and status when subscribing to the chat so on the admin side, I can list out the admins and users by calling wsGetSubscribers('chat') which show my custom fields. I'm planning on using the status as an online/offline flag for admins. This flag is used on the client end for whether or not to show the "chat is available" based on if any admins are "online". Meanwhile the admin who are offline are still able to chat to existing chats or other admins. How do I update this field in javascript/jQuery when a button is clicked?

Comment 2 by Raymond Camden posted on 6/8/2013 at 7:12 AM

I just did a test, and in beforePublish, I was able to modify subscriberinfo.connectioninfo with custom data. So you could do a publish on a client side that contains a message you pick up/recognize in beforePublish and use to set flags.

Comment 3 by Andy posted on 6/13/2013 at 12:59 AM

Thanks Ray. I'm using CFWheels and for some reason it won't reach the listener cfc that I define in the cfclistener attribute when creating the wschannels. I think it's a path issue. Anyway I posted some questions about that on CFWheels forums and hopefully that'll get resolved. In the meantime I just updated the ChannelListener.cfc and seems like the beforeSendMessage is the one I want where it passes in the subscriberInfo and not the publisherInfo but thanks for pointing me in the right direction. Also I was wondering if you know if the cfwebsocket can be used cross domain and cross server. Currently my chat is on one server and one domain but like other live help chat systems out there, I want to be able to place it on other domains/servers while the admin agents just log into a central domain to chat with users. Do you know if this is possible? If so, do you have any examples on how it can be implemented?

Comment 4 by Raymond Camden posted on 6/13/2013 at 1:05 AM

I don't know if you can use websockets cross domain. I would imagine it follows the same rules for HTTP for security reasons.

Of course, it may be possible in general, but NOT possible w/ CF's implementation. I do not believe cfwebsocket lets you specify another server.

Comment 5 by Andy posted on 6/13/2013 at 8:39 PM

Interesting, then do you know how other live help chat providers do this? They have the live chat on various client websites and a single site for the agent to log on and chat. I'm trying to accomplish the same thing except in CF.

Comment 6 by Raymond Camden posted on 6/13/2013 at 8:46 PM

Are they used WebSockets? THey could be using AJAX polls with CORS or JSON/P, or Flash even.