Search code examples
spring-bootrsocketspring-rsocket

Does spring-rsocket support return a RejectedSetupException in @ConnectMapping annotated method?


I follow the spring-rsocket-demo project to complete my code. I add some authentication logic in my server side code as follows. You can see I throw a exception in the after the authentication logic 'CLIENT.add(requester)'. I execute the test method in spring-rsocket-demo project called 'testRequestGetsResponse' and I find I can't receive the exception. How to process setup payload in @ConnectMapping annotated method and return a RejectedSetupException if need.


        requester.rsocket()
                .onClose()
                .doFirst(() -> {
                    // Add all new clients to a client list
                    log.info("Client: {} CONNECTED.", client);
                    //throw Exception during process setup payload
                    //my authentication code.
                    try {
//                        CLIENTS.add(requester);
                        throw new RuntimeException();
                    } catch (Exception exception) {
                        throw exception;
                    }
                })
                .doOnError(error -> {
                    // Warn when channels are closed by clients
                    log.warn("Channel to client {} CLOSED", client);
                })
                .doFinally(consumer -> {
                    // Remove disconnected clients from the client list
                    CLIENTS.remove(requester);
                    log.info("Client {} DISCONNECTED", client);
                })
                .subscribe();

Solution

  • You should define your @ConnectionMapping method as following:

    @ConnectionMapping 
    Mono<Void> handleSetup(@Payload String payload) {
       // Add all new clients to a client list
       log.info("Client: {} CONNECTED.", client);
       boolean isAuthenticated = ... //my authentication code.
       if (!isAuthenticated) {
         //throw Exception during process setup payload
         return Mono.error(new RejectedSetupException("connection is not authenticated"));
       }
    
       // add client if it is authenticated
       CLIENTS.add(requester);
    
       requester.rsocket()
                .onClose()
                .doFinally(consumer -> {
                   // Remove disconnected clients from the client list
                   CLIENTS.remove(requester);
                   log.info("Client {} DISCONNECTED", client);
                })
                .subscribe();
    
       return Mono.empty();
    }
    

    As you may see from the code above, if a connection does not pass the authentication, it returns a Mono.error with an appropriate error