My project using react + vite without any proxy config Im trying to use webstomp-client and sockjs to connect to websocket server (Springboot support SockJS)
The backend springboot server generated by JHipster and have default config for websocket like below:
package com.mycompany.myapp.config;
import com.mycompany.myapp.security.AuthoritiesConstants;
import java.security.Principal;
import java.util.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.server.*;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.*;
import org.springframework.web.socket.server.HandshakeInterceptor;
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;
import tech.jhipster.config.JHipsterProperties;
@Configuration
@EnableWebSocketMessageBroker
public class WebsocketConfiguration implements WebSocketMessageBrokerConfigurer {
public static final String IP_ADDRESS = "IP_ADDRESS";
private final JHipsterProperties jHipsterProperties;
public WebsocketConfiguration(JHipsterProperties jHipsterProperties) {
this.jHipsterProperties = jHipsterProperties;
}
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
String[] allowedOrigins = Optional
.ofNullable(jHipsterProperties.getCors().getAllowedOrigins())
.map(origins -> origins.toArray(new String[0]))
.orElse(new String[0]);
registry
.addEndpoint("/websocket/tracker")
.setHandshakeHandler(defaultHandshakeHandler())
.setAllowedOrigins(allowedOrigins)
.withSockJS()
.setInterceptors(httpSessionHandshakeInterceptor());
}
@Bean
public HandshakeInterceptor httpSessionHandshakeInterceptor() {
return new HandshakeInterceptor() {
@Override
public boolean beforeHandshake(
ServerHttpRequest request,
ServerHttpResponse response,
WebSocketHandler wsHandler,
Map<String, Object> attributes
) throws Exception {
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
attributes.put(IP_ADDRESS, servletRequest.getRemoteAddress());
}
return true;
}
@Override
public void afterHandshake(
ServerHttpRequest request,
ServerHttpResponse response,
WebSocketHandler wsHandler,
Exception exception
) {}
};
}
private DefaultHandshakeHandler defaultHandshakeHandler() {
return new DefaultHandshakeHandler() {
@Override
protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, Map<String, Object> attributes) {
Principal principal = request.getPrincipal();
if (principal == null) {
Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority(AuthoritiesConstants.ANONYMOUS));
principal = new AnonymousAuthenticationToken("WebsocketConfiguration", "anonymous", authorities);
}
return principal;
}
};
}
}
In client side (React app), im trying to connect to /websocket/tracker registered above like this
const url = `${WS_URL}/websocket/tracker?access_token=${authToken}`
const socket = new SockJS(url)
const stompClient = Stomp.over(
socket, { protocols: ['v12.stomp'] }
)
stompClient.connect({}, (f) => {
console.log('Connection established', f)
}, (e) => {
console.error('Connect failed', e)
})
But even when i use springboot server or public test websocket server (https://stream.elite12.de/api/sock) (I mean this may not server config issue), the above client code give me error code 2000: All transport failed image
Anyone have encountered this? Please give me an advice.
Node: 20.6.1 sockjs-client: 1.6.1 webstomp-client: 1.2.6 React project template: Metronic v8.0.25
I've tried switch to other browser (firefox, chrome, safari) but nothing changed, i also tried to debug into sockjs-client source code and found that all availableTransports can't enable (All driver undefined)
The reason no transport available for enable is integrate SockJS into react app cause global is not defined
Uncaught ReferenceError: global is not defined
at Object../node_modules/sockjs-client/lib/utils/browser-crypto.js (browser-crypto.js:3)
at __webpack_require__ (bootstrap:76)
at Object../node_modules/sockjs-client/lib/utils/random.js (random.js:4)
at __webpack_require__ (bootstrap:76)
at Object../node_modules/sockjs-client/lib/utils/event.js (event.js:3)
at __webpack_require__ (bootstrap:76)
at Object../node_modules/sockjs-client/lib/transport/websocket.js (websocket.js:3)
at __webpack_require__ (bootstrap:76)
at Object../node_modules/sockjs-client/lib/transport-list.js (transport-list.js:5)
at __webpack_require__ (bootstrap:76)
Instead of declare global variable, i have define in vite defineConfig
as {}
The correct fix is declare global variable in index.html