gauravphoenix
gauravphoenix

Reputation: 3082

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

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)

Upvotes: 10

Views: 7206

Answers (2)

pyang
pyang

Reputation: 152

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);
    }
}

Upvotes: 1

Pavel Bucek
Pavel Bucek

Reputation: 5324

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)

Upvotes: 1

Related Questions