16

When I tried to establish websocket communication between AngularJS app and Spring Boot I'm getting the error: Error during websocket handshake - Unexpected response code: 200.

Here is my JS code:

function run(stateHandler, translationHandler, $websocket) {
    stateHandler.initialize();
    translationHandler.initialize();

    var ws = $websocket.$new('ws://localhost:8080/socket'); // instance of ngWebsocket, handled by $websocket service

    ws.$on('$open', function () {
        console.log('Oh my gosh, websocket is really open! Fukken awesome!');  
    });

    ws.$on('/topic/notification', function (data) {
        console.log('The websocket server has sent the following data:');
        console.log(data);

        ws.$close();
    });

    ws.$on('$close', function () {
        console.log('Noooooooooou, I want to have more fun with ngWebsocket, damn it!');
    });
}

And here is my Java code:

WebsocketConfiguration.java

@Override
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry)
{
    stompEndpointRegistry.addEndpoint("/socket")
        .setAllowedOrigins("*")
        .withSockJS();
}

@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
    registry.enableSimpleBroker("/topic");
}

WebsocketSecurityConfiguration.java

@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
    messages
        // message types other than MESSAGE and SUBSCRIBE
        .nullDestMatcher().authenticated()
        // matches any destination that starts with /rooms/
        .simpDestMatchers("/topic/tracker").hasAuthority(AuthoritiesConstants.ADMIN)
        .simpDestMatchers("/topic/**").permitAll()
        // (i.e. cannot send messages directly to /topic/, /queue/)
        // (i.e. cannot subscribe to /topic/messages/* to get messages sent to
        // /topic/messages-user<id>)
        .simpTypeMatchers(SimpMessageType.MESSAGE, SimpMessageType.SUBSCRIBE).denyAll()
        // catch all
        .anyMessage().denyAll();
}

Does anyone have an idea how to fix this problem?
Thank you in advance!

Heril Muratovic
  • 1,940
  • 6
  • 25
  • 46

3 Answers3

51

I had a similiar problem, I was testing my websocket connection using an chrome plugin (Simple WebSocket Client) and was trying to connect to ws://localhost:8080/handler/ which is defined in my code as registry.addEndpoint("/handler").setAllowedOrigins("*").withSockJS(); but unexpected error 200 was occuring. I've fixed this by appending /websocket to my client request string on the chrome extension, so what you could try is to change in your JS file the following line:

var ws = $websocket.$new('ws://localhost:8080/socket');

to

 var ws = $websocket.$new('ws://localhost:8080/socket/websocket');

I dont know the reason why this fixed it in my case i just randomly stumbled upon it, if some1 could clarify it more it would be really nice :)

Luka Špoljarić
  • 988
  • 1
  • 10
  • 23
  • 7
    I found that configuring spring with .withSockJS(); means to have to add 'websocket'. I assume because you're providing a fall back option? If you remove .withSockJS(); you don't need to append websocket. Thanks for your answer btw! – Maj Jan 18 '19 at 18:46
  • 1
    Thanks, you saved my evening! Does this show up in the documentation? I couldn't find anything... – Peter Catalin Jul 05 '19 at 14:11
  • 4
    This is the correct answer. When you use withSockJS(), you have to add /websocket to your url. Without SockJS you have to use your url from WebSocketConfiguration. – Binakot Sep 24 '19 at 14:08
  • 1
    This worked for me as well but drives me crazy because I haven't been able to find out in the code *why* it works. I am walking through everything but it seems like a hack more than a correct solution. – mkeathley Oct 05 '19 at 03:28
  • @mkeathley, totally smells like a hack, but at this moment i just don't have the time to dive in the problem and find out what exactly is going on. – Luka Špoljarić Oct 06 '19 at 13:45
  • 1
    Thank you very much. This problems is very crazy. lol – Higor Senna Sep 02 '20 at 11:41
  • 2
    @PeterCatalin You can check the suffix /websocket at link > https://github.com/sockjs/sockjs-node#connecting-to-sockjs-node-without-the-client – kidnan1991 Oct 22 '20 at 09:24
  • Thank you so much. You saved my day. It is crazy how some solutions are. – Naseem Ahamed Nov 24 '20 at 17:42
  • 1
    @Luka Špoljarić, thanks your solution worked for me. – Maulik Kayastha Dec 03 '20 at 08:11
5

Can you try this WebsocketConfiguration configuration:

@Override
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry)
{
    stompEndpointRegistry.addEndpoint("/socket").setAllowedOrigins("*");      
    stompEndpointRegistry.addEndpoint("/socket").setAllowedOrigins("*").withSockJS();
}

so you have both websocket and SockJS configurations?

Josef Veselý
  • 102
  • 1
  • 4
  • I think only the first configuration of the endpoint will be used with your code. – Reg Whitton Jul 15 '20 at 08:33
  • 2
    The .withSockJS() should configure the endpoint to fallback to SockJS when websockets are not available in the browser. However, if you use .withSockJS() then you also seem to need your web client to also be setup to use it, or you will get the 200 status during the negotiation. Compare: https://stomp-js.github.io/guide/stompjs/rx-stomp/ng2-stompjs/using-stomp-with-sockjs.html#example-with-stompjs with https://stomp-js.github.io/guide/stompjs/using-stompjs-v5.html#create-a-stomp-client. – Reg Whitton Jul 15 '20 at 08:45
1

You need to use a sockJS client if you configure it to use sockJS on your websocket endpoint.

Deadron
  • 5,135
  • 1
  • 16
  • 27