How to access client hostname, http headers etc from a Java websocket server?
Asked Answered
C

2

10

I've followed many tutorials and sample sample code but I am yet to see a way to access client's HTTP header, hostname etc like the way we can in Servlet's request object.

How do I go about it?

Let's say I've onOpen defined as-

@OnOpen
    public void onOpen(Session session) {

} 

In above method, is there a way I can access underlying HTTP connection details using session field? I am okay even if I can get to underlying Servlet (if there is any)

Cornerstone answered 28/1, 2015 at 9:1 Comment(2)
see chapter 4.1.1.5 at tyrus.java.net/documentation/1.9/user-guide.html#d0e464. It requires some amount of work to get the info from ServerEnpointConfig.Configurator to endpoint instance, but it can be done. (github.com/tyrus-project/tyrus/blob/…)Sheffield
@PavelBucek - thanks! that seems like a lot of work just to get simple information. Anyways, can you post your comment as answer please?Cornerstone
S
1

see chapter 4.1.1.5 at Tyrus user guide. It requires some amount of work to get the info from ServerEnpointConfig.Configurator to endpoint instance, but it can be done. (see ModifyRequestResponseHeadersTest.java)

Sheffield answered 29/1, 2015 at 17:56 Comment(1)
Care to elaborate? The answer given here: #28940081 seems to be based on what you are saying in this answer. However, you then comment there that it isn't safe to do because of concurrency. So, it really sounds like it can't be done safely? Should we stash the headers read from the modifyHandshake method into a ThreadLocal and hope that the same thread that performs the handskake will call the onopen callback? Something else?Overseer
C
1

Based on link1 and link2

I finally figured out that we can get the client IP with the following two classes, actually you can do more with the exposed httpservletRequest...

ServletAwareConfigurator .java

package examples;
import java.lang.reflect.Field;

import javax.servlet.http.HttpServletRequest;

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

public class ServletAwareConfigurator extends ServerEndpointConfig.Configurator {

    @Override
    public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response) {
        HttpServletRequest httpservletRequest = getField(request, HttpServletRequest.class);
        String sClientIP = httpservletRequest.getRemoteAddr();
        config.getUserProperties().put("clientip", sClientIP);
        // ...
    }

    //hacking reflector to expose fields...
    private static < I, F > F getField(I instance, Class < F > fieldType) {
        try {
            for (Class < ? > type = instance.getClass(); type != Object.class; type = type.getSuperclass()) {
                for (Field field: type.getDeclaredFields()) {
                    if (fieldType.isAssignableFrom(field.getType())) {
                        field.setAccessible(true);
                        return (F) field.get(instance);
                    }
                }
            }
        } catch (Exception e) {
            // Handle?
        }
        return null;
    }
}

GetHttpSessionSocket.java

package examples;
import java.io.IOException;
import javax.servlet.http.HttpSession;
import javax.websocket.EndpointConfig;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint(value = "/example",
    configurator = ServletAwareConfigurator.class)
public class GetHttpSessionSocket {
    private Session wsSession;
    private String sClientIP;

    @OnOpen
    public void open(Session session, EndpointConfig config) {
        this.wsSession = session;
        this.sClientIP = (String) config.getUserProperties()
            .get("clientip");
    }
    @OnMessage
    public void echo(String msg) throws IOException {
        wsSession.getBasicRemote().sendText(msg);
    }
}
Cicero answered 1/7, 2017 at 6:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.