Error during WebSocket handshake: Unexpected response code: 400 when using Spring Websocket, Stomp, SockJS in Openshift

3.1k views Asked by At

From what I have learned so far while searching through internet is openshift provides only port 8000 for opening up the web socket connection over HTTP.

What I am unable to figure out is how do I make it work for Spring WebSocket implementation with Stomp and SockJs. Here is my code snippet,

Websocket Client Side Implementation:

function connect() {
        var socket = new SockJS('http://jbossews-nabac.rhcloud.com:8000/portal/ws');
        stompClient = Stomp.over(socket);
        stompClient.connect({}, function(frame) {
            setConnected(true);
            console.log('Connected: ' + frame);
            stompClient.subscribe('/queue/reply/${pageContext.session.id}', function(greeting) {
                showGreeting(greeting.body);
            });
        });
    }

WebSocket ServerSide Configration:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketDefaultConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic/", "/queue/");
        config.setApplicationDestinationPrefixes("/portal");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws")
        .withSockJS()
        .setInterceptors(httpSessionIdHandshakeInterceptor());
    }

    @Bean
    public HttpSessionIdHandshakeInterceptor httpSessionIdHandshakeInterceptor() {
        return new HttpSessionIdHandshakeInterceptor();
    }

}

Chrome Console

And if I try this way,

var socket = new SockJS('/portal/ws');

Error I get is,

Chrome Console

Please help me to fix this error.

1

There are 1 answers

0
Carmnu On

I had the same problem, and finally, after long time I managed to use Spring WebSocket in Openshift V3, but I think this solution works also in the older Openshift V2.

The only compromise is to not use SockJS, but the standard WebSocket API.

In your case you have to, in the method registerStompEndpoints remove .withSockJS(), edit the endpoint path adding the suffix "/websocket" and set allowed origins to "*" (probably the latter is not mandatory).

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketDefaultConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic/", "/queue/");
        config.setApplicationDestinationPrefixes("/portal");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws/websocket")
        .setAllowedOrigins(‌​"*")
        .setInterceptors(httpSessionIdHandshakeInterceptor());
    }

    @Bean
    public HttpSessionIdHandshakeInterceptor httpSessionIdHandshakeInterceptor() {
        return new HttpSessionIdHandshakeInterceptor();
    }
}

In the client, as said, you have to use the WebSocket API instead of SockJS, and use the new path to connect to the endpoint.

function connect() {
    var socket = new WebSocket('ws://your_service_exposed_route:80/portal/ws/websocket');
    stompClient = Stomp.over(socket);
    stompClient.connect({}, function(frame) {
        setConnected(true);
        console.log('Connected: ' + frame);
        stompClient.subscribe('/queue/reply/${pageContext.session.id}', function(greeting) {
            showGreeting(greeting.body);
        });
    });
}

As you can see I used the port 80: OpenShift V3 supports running WebSockets over the same port. When the service is exposed via a route, that will be port 80 externally for HTTP traffic including WebSockets.

That's all!