I have problem with WebSocket using SpringBoot and Angular2:
Screenshot: consoleOutput
I think that error (Incompatibile SockJS! Main site uses: "1.1.4", the iframe: "1.0.0".) generate next problems with handshake response.
WebSocket Config
package com.example.demo;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
@Configuration
@EnableWebSocketMessageBroker
@EnableScheduling
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/socket").setAllowedOrigins("*").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/chat");
registry.setApplicationDestinationPrefixes("/app");
}
}
Controller
package com.example.demo;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
@Controller
public class WebSocketController {
@MessageMapping("/send/message")
@SendTo("/chat/greetins")
public String onReceivedMessage(String message) {
return message;
}
}
import { Component, OnInit } from '@angular/core';
import * as Stomp from 'stompjs';
import * as SockJS from 'sockjs-client';
import * as $ from 'jquery';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
private serverUrl = "/api/socket";
private title = "WebSockets chat";
private stompClient;
constructor() {
}
ngOnInit() {
this.initializeWebSocketConnection();
}
initializeWebSocketConnection() {
var ws = new SockJS(this.serverUrl);
this.stompClient = Stomp.over(ws);
let that = this;
this.stompClient.connect({}, function(frame) {
console.log("Connection Success.");
that.stompClient.subscribe("/chat/greetings", (message) => {
if (message.body) {
$(".chat").append("<div class='message'>" + message.body + "</div>");
}
});
} );
}
sendMessage() {
let message = $('#input').val();
this.stompClient.send("app/send/message", {}, message);
$('#input').val('');
}
}
Thanks for help.
I fixed it by manually hardcoding the SockJS version on the server-side (Spring/Java) by
@Override
public void registerStompEndpoints( StompEndpointRegistry registry )
{
registry.addEndpoint( "/socket" )
.setAllowedOrigins( "*" )
.withSockJS( )
.setClientLibraryUrl( "https://cdn.jsdelivr.net/sockjs/1.1.4/sockjs.min.js" );
}
Update: To load the JS library (local) using a relative path
@Override
public void registerStompEndpoints( StompEndpointRegistry registry )
{
registry.addEndpoint( "/socket" )
.setAllowedOrigins( "*" )
.withSockJS( )
.setClientLibraryUrl( "../lib/sockjs-client/dist/sockjs.min.js" ); // Added
}
The version used in the iframe is a server setting
You need to change the sockjs_url parameter when creating the server to match the version you are serving on the front end.
Your issue is probably related to missing Upgrade request header from your client. You can check your Tomcat logs and try to find something like this:
Handshake failed due to invalid Upgrade header: null
This is because the upgrade header is not passed from Nginx/Appache Http Server to Spring. This header is required to handshake connection between client and server via WebSockets. You can find more info about WebSocket handshake here:
https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers
So, check your load balancer or http server configuration. Check similar issue below with sample Nginx configuration:
https://github.com/sockjs/sockjs-client/issues/388
Sample Nginx configurations:
location / {
proxy_pass http://localhost:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
# For WebSocket upgrade header
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With