In the servlet world there would be things like cookies and HttpSession for me to identify who was hitting my restful service to route the request to the correct data. Is it a good idea to use the Sec-WebSocket-Key as though it is a cookie identifying the client connection?
Specifically I am using the socko scala library (an akka webserver based on netty) to implement a websocket server starting from the demo app at socko-examples. Socko is wrapping a netty Channel and passing a netty WebSocketFrame into the application code. I would then like to dispatch the frame of incoming data based on "some identity" for the client connection which I have previously associated to the end users data (e.g their shopping basket). To do this I have written extension methods to expose the Sec-WebSocket-Key http header as though it is a top level property of the objects which come into the application by digging out the http header from the original websocket handshake:
package org.mashupbots.socko.examples.websocket
// pimp my library pattern to add extension method
object ChatWebSocketExtensions {
import org.mashupbots.socko.events.WebSocketFrameEvent
class WebSocketFrameEventWithSecWebSocketKey(wsFrame: WebSocketFrameEvent) {
def secWebSocketKey: String = {
wsFrame.initialHttpRequest.headers.get("Sec-WebSocket-Key").getOrElse("null")
}
}
implicit def webSocketFrameEventWithSecWebSocketKey(wsFrame: WebSocketFrameEvent) = new WebSocketFrameEventWithSecWebSocketKey(wsFrame)
import org.mashupbots.socko.events.WebSocketHandshakeEvent;
class WebSocketHandshakeEventWithSecWebSocketKey(event: WebSocketHandshakeEvent) {
def secWebSocketKey: String = {
val option = Option(event.nettyHttpRequest.getHeader("Sec-WebSocket-Key"))
return option.getOrElse("null");
}
}
implicit def webSocketHandshakeEventWithSecWebSocketKey(event: WebSocketHandshakeEvent) = new WebSocketHandshakeEventWithSecWebSocketKey(event)
}
Thats only some syntactic sugar so that the app code does not have to go digging around in the low level objects to get the Sec-WebSocket-Key header and just access it as though it were a first class property:
val routes = Routes({
case WebSocketHandshake(wsHandshake) => wsHandshake match {
case GET(PathSegments("websocket" :: roomNumber :: Nil)) => {
log.info("Handsake to join room " + roomNumber)
wsHandshake.authorize(onComplete = Some((event: WebSocketHandshakeEvent) => {
val identity = event.secWebSocketKey;
log.info("Authorised connection:" + identity);
// do something with this identified user connection
}))
}
}
case WebSocketFrame(wsFrame) => {
// Once handshaking has taken place, we can now process frames sent from the client
val identity = wsFrame.secWebSocketKey;
log.info("chat from:" + identity);
// do something with this identified data frame
}
})
My question is whether this is good practice or is there a better way to identify the user connection?