Access UserAgent in Websocket session?
Asked Answered
O

1

4

Using the Tyrus reference implementation of Java's "JSR 356 - Java API for WebSocket", I cannot find a way to access the HTTP connection that was used for the Websocket upgrades. Thus, I cannot access the HTTP headers that the browser sent.

Is there a way to read the HTTP UserAgent header?

Casting a "Session" object to "TyrusSession" or similar would be acceptable, I have to do it to get the Remote Address anyway. Sending the UserAgent again as a message inside the Websocket connection would be my fallback solution.

Orthoscope answered 9/3, 2015 at 10:19 Comment(4)
seems like a duplicate of #28188672Lambertson
@PavelBucek: The question sounds similar indeed but the answer does not fit: using the ServerEndpointConfig.Configurator, I can only access the headers of the Websocket handshake, i.e.: {connection=[Upgrade], host=[localhost:8025], origin=[localhost:8025], sec-websocket-key=[vi6GPNd4GIj2oRTcwzWKYA==], sec-websocket-version=[13], upgrade=[websocket]} The request.getHttpSession() only works in a Java EE container and gives NULL in "normal" mode.Orthoscope
User-Agent header (when sent) should be there - there is no other way how to get User-Agent (web socket protocol does not send info like that anywhere).Lambertson
Oh, indeed, it's just Java that does not send one. To make this question at least a bit useful, I'll post a solution with source code as answer.Orthoscope
O
1

WARNING: ServerEndpointConfig is shared among all endpoint instances and multiple upgrade requests can be done concurrently! See comments!

The endpoint gets a configurator:

import javax.websocket.EndpointConfig;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint(value = "/foo", configurator = MyServerEndpointConfigurator.class)
public class MyEndpoint {

    @OnOpen
    public void onOpen(Session session, EndpointConfig endpointConfig) throws Exception {
        String ip = ((TyrusSession) session).getRemoteAddr();
        String userAgent = (String) endpointConfig.getUserProperties().get("user-agent");
        ...
   }
}

The configurator looks like this:

import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;

public class MyServerEndpointConfigurator extends ServerEndpointConfig.Configurator {

    @Override
    public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
        if (request.getHeaders().containsKey("user-agent")) {
            sec.getUserProperties().put("user-agent", request.getHeaders().get("user-agent").get(0)); // lower-case!
        }
    }
}
Orthoscope answered 10/3, 2015 at 17:26 Comment(3)
:-) this is similar to the answer I originally wrote, BUT this is not a good solution. ServerEndpointConfig is shared among all endpoint instances and multiple upgrade requests can be done concurrently - which would effectively rewrite the "user-agent" entry and endpoints won't have the correct information..Lambertson
Then I better delete my answer. But I can't find the your solution in the other question or the Tyrus example you mentioned, though. In the example the ServerEndpoint.Config only sets some response headers for the websocket client, it does not pass any information to the ServerEndpoint, so how am I supposed to do it?Orthoscope
that is a good question and unfortunately, I don't have acceptable answer :-/ can you please file an issue against WebSocket API? java.net/jira/browse/WEBSOCKET_SPECLambertson

© 2022 - 2024 — McMap. All rights reserved.