It appears that there is a problem in Tomcat's static UpgradeUtil.doUpgrade 
logic when handling concurrent connection/upgrade requests that rely on a 
custom ServerEndpointConfig.Configurator.modifyHandshake to grab 
[per-upgrade-request] client header values and inject them into the wsSession 
that is being created.

Specifically, the static doUpgrade does not appear to make a copy of the 
ServerEndpointConfig before calling modifyHandshake.   As a result, any 
per-connection headers the Configurator may grab and put in the 
ServerEndpointConfig.UserProperties map will be overwritten by the last upgrade 
request that occurs before the upgrade logic creates the new wsSession in the 
WsHttpUpgradeHandler.init call.

I am able to replicate this very easily by using the following server 
configurator code.  By making concurrent websocket connect requests that place 
a unique "client-id" in the upgrade request headers, then grabbing that 
"client-id" property using the code below, ALL websocket sessions that get 
created will have the last "client-id" header value that came in concurrently.

public class Jsr356ServerConfigurator extends ServerEndpointConfig.Configurator
{
    @Override
    public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest 
request, HandshakeResponse response)
    {
              // get the request headers - looking for security claims and 
endpoint ID
              // claims will be checked in the OnOpen call and the connection 
closed if AUTH check fails
              Map<String, List<String>> headers = request.getHeaders();

              String id = headers.get("client-id").get(0);

              config.getUserProperties().put("client-id", id);
    }
}

@ServerEndpoint(...)
Public class MyServer
{
@OnOpen
public void onOpen(Session session)
{
              String id = (String) session.getUserProperties().get("client-id");
              _logger.warn("client ID: {}", id);
}
}


Based on chapter 3 of the JSR-356 API document, the actual websocket handshake 
process defined in the websocket spec,  and the online description of the 
process in this stackoverflow link 
(http://stackoverflow.com/questions/17936440/accessing-httpsession-from-httpservletrequest-in-a-web-socket-socketendpoint/17994303#17994303),
 it appears that we should be able to pass per-client information in the 
upgrade headers and we should be able to get them into the endpoint INSTANCE's 
Session user properties.

If this is a bug, please confirm and I will create a bugzilla entry, as it is 
very important that that we be able to do what I've described above.

If this is not a bug, can someone please describe how to obtain per-client 
instance data during the handshake/onOpen process?


Thanks,
Bob

http://www.thingworx.com<http://www.thingworx.com/>
Skype: bob.deremer.thingworx

Reply via email to