Search code examples
javaspring-bootspring-webfluxrsocket

How do I get the remote IP address for an Rsocket connection in SpringBoot


I'm trying to get the remote IP of the browser that connects to a RSocket+SpringBoot webserver. Connection is RSocket over WebSocket.

The webserver is Java-8, SpringBoot-2, using RSocket over WebSocket and sending RequestStreams to the browser. I'm leveraging SpringBoot autoconfig for the RSocket setup, so really minimal code on the server side - see below.

@Headers and MessageHeader in the code below was just to see if they had anything that could lead to the remote IP, no other reason they're there.

I've scoured the web looking for an answer - lots for http, a few for websockets, zero for RSocket. This - https://github.com/rsocket/rsocket-java/issues/735 - looked promising, but was unable to get a handle to DuplexConnection, so no cigar there.

Any ideas ? Thx !

application.yml:

spring.rsocket.server:
  mapping-path: /rsocket-test
  transport: websocket

server.port: 8080

TestController.java

 /**
     * TODO: get the remote IP address and log.
     * Options:
     * 1. @see <a href="https://github.com/rsocket/rsocket-java/issues/735">Ability to intercept requests and access channel information such as remote address</a>.
     * 2. Inject IP in header by nginx. See if it shows up in the @Headers param here.
     * 3. Browser gets its public IP and adds it to the request object. Doable, but lame
     * 4. (Unlikely) Find a way to access thru this chain of private members: headers.req.rsocket().source.connection.source.connection.connection.channel.remoteAddress
     */
    @MessageMapping("subscribe-topic")
    public Flux<StreamingEvent> subscribeToEventStream(
                @Headers Map<String,Object> hdrs,
                MessageHeaders mh,
                testRequest request) {
        return testService.subscribeTopic(request.getRequestId(), request.getTopic());
    }

Solution

  • Client's ip address is available in the DuplexConnection class. You can add an interceptor to the RSocketServer like this:

    @Bean
    public RSocketServerCustomizer ipCustomizer() {
        return rSocketServer -> rSocketServer.interceptors(registry -> registry.forConnection(new ConnectionInterceptor()));
    }
    
    

    where ConnectionInterceptor is:

    static class ConnectionInterceptor implements DuplexConnectionInterceptor {
        @Override
        public DuplexConnection apply(Type type, DuplexConnection duplexConnection) {
            SocketAddress socketAddress = duplexConnection.remoteAddress();
            if (socketAddress instanceof InetSocketAddress) {
                InetSocketAddress iso = (InetSocketAddress) socketAddress;
                // Here is the ip: iso.getHostString()
            }
            return duplexConnection;
        }
    }