Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Building custom API over Spring Websockets

I'm have to implement custom API over Websockets that requires:

  • Custom WAMP-like subprotocol
  • Path parameters in socket URI

So I've following questions:

  • Is there any documentation or guides on implementing custom subprotocols in Spring? Protocol requires that exact version must be specified in the Sec-Websocket-Protocol field. Where this field could be read on server side?
  • What is a proper way to pass path parameters into a message handler? I could use ant patterns in handler registration

        @Override 
        public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
            registry.addHandler(customHandler(), "/api/custom/{clientId}");
        }
    

    but those seems not available at TextWebSocketHandler. I'm solved this for now by extending default HttpSessionHandshakeInterceptor in a following way:

    public class CustomHandshakeInterceptor extends HttpSessionHandshakeInterceptor {
        private static final UriTemplate URI_TEMPLATE = new UriTemplate("/api/custom/{clientId}");
    
        @Override
        public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,
                                       WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
            Map<String, String> segments = URI_TEMPLATE.match(request.getURI().getPath());
            attributes.put("CLIENTID", segments.get("clientId"));
    
            return super.beforeHandshake(request, response, wsHandler, attributes);
        }
    }
    

    and then accessing it in TextWebSocketHandler:

    public class CustomHandler extends TextWebSocketHandler {
    
        @Override
        protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
            super.handleTextMessage(session, message);
    
            String clientId = session.getAttributes().get("CLIENTID");
    
            ...
    
            session.sendMessage(response);
        }
    
    }
    

    but this method, in my opinion, is a bit clunky. Is there more proper way to solve this?

Thanks.

like image 586
Gris Avatar asked Feb 17 '16 22:02

Gris


People also ask

Can a WebSocket call an API?

You can't call an HTTP API from web socket. You can call a web socket API from a web socket. That mostly means you send some specific message over web socket to the server, and the server sends something specific back.

How do you use WebSockets in Spring?

In order to tell Spring to forward client requests to the endpoint , we need to register the handler. Start the application- Go to http://localhost:8080 Click on start new chat it opens the WebSocket connection. Type text in the textbox and click send. On clicking end chat, the WebSocket connection will be closed.

Does Spring boot support WebSocket?

The Spring Framework provides support for using STOMP — a simple, messaging protocol originally created for use in scripting languages with frames inspired by HTTP. STOMP is widely supported and well suited for use over WebSocket and over the web.

Does Spring WebFlux use WebSocket?

Spring Framework 5 has modernized WebSockets support in the framework, adding reactive capabilities to this communication channel. We can find more on Spring WebFlux here.


1 Answers

The best advice I could give is to follow the example of the sub-protocol support that's built in -- starting with SubProtocolWebSocketHandler and the SubProtocolHandler's it delegates to including the StompSubProtocolHandler implementation. The SubProtocolWebSocketHandler is further connected to "clientInbound" and "clientOutbound" channels which are then used to form a processing flow as well as to provide thread boundaries.

There is a description for the processing flow for STOMP http://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html#websocket-stomp-message-flow which includes delegating messages to annotated controllers and/or to a message broker which can also send messages back downstream to clients.

Essentially the StompSubProtocolHandler translates to and from a WebSocketMessage and a Spring Message with protocol-specific content. So that controllers, message brokers, or any other consumer of the messages from the client inbound channel are decoupled and unaware from the WebSocket transport layer. Many of the facilities built around the building, sending, and processing of such sub-protocol messages are meant to be potentially usable for support of other STOMP-like protocols. That includes all the classes in the org.springframework.messaging.simp package.

As for URL path parameters, Spring doesn't provide anything at the WebSocket level which is mostly a transport layer. Most of the interesting stuff happens at the sub-protocol level. For example for STOMP a MessageMapping is supported based on the destination header along with a @DestinationVariable which is comparable to using @PathVariable in Spring MVC but based on the destination header, not the URL.

like image 103
Rossen Stoyanchev Avatar answered Oct 08 '22 19:10

Rossen Stoyanchev