react.js 无法从 Spring Boot 应用程序连接到 websocket

问题描述 投票:0回答:1

我用

创建了一个小型 Spring Boot 服务器
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
    <version>3.3.4</version>
</dependency>

拥有 WebSocketConfigurer

@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
    registry.addHandler(new ServerWebSocketHandler(), "/socket");
}

在 ServerWebSocketHandler 中

@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
    log.info("Connection open");

    TextMessage message = new TextMessage("initial message from server");
    log.info("Sending message: {}", message);
    session.sendMessage(message);
}

当我使用 Postman 创建到

ws://localhost:8080/socket
的 Websocket 连接时,连接已建立,并且我看到了预期的消息和日志条目。 但是,尝试从 React.js 应用程序内部建立连接失败。 这是来自 App.tsx:

function App() {
  const ws : MutableRefObject<WebSocket|null> = useRef(null);

  useEffect(() => {
    ws.current = new WebSocket("ws://localhost:8080/socket");
    ws.current.onopen = () => console.log("ws open");
    ws.current.onclose = () => console.log("ws closed");

    const wsCurrent = ws.current;

    return () => {
      wsCurrent.close();
    };
  }, []);

  useEffect(() => {
    if (!ws.current) return;

    ws.current.onmessage = e => {
      const message = JSON.parse(e.data);
      console.log("e", message);
    };
  }, []);

  return (
    <div className="App">

      <div>
        Hey world.
      </div>
    </div>
  );
}

和日志条目:

App.tsx:15 WebSocket connection to 'ws://localhost:8080/socket' failed: WebSocket is closed before the connection is established.
App.tsx:10 ws closed
App.tsx:8 WebSocket connection to 'ws://localhost:8080/socket' failed: 
(anonymous) @ App.tsx:8
commitHookEffectListMount @ react-dom.development.js:23189
invokePassiveEffectMountInDEV @ react-dom.development.js:25193
invokeEffectsInDev @ react-dom.development.js:27390
commitDoubleInvokeEffectsInDEV @ react-dom.development.js:27369
flushPassiveEffectsImpl @ react-dom.development.js:27095
flushPassiveEffects @ react-dom.development.js:27023
(anonymous) @ react-dom.development.js:26808
workLoop @ scheduler.development.js:266
flushWork @ scheduler.development.js:239
performWorkUntilDeadline @ scheduler.development.js:533

这些尝试的服务器日志中没有任何内容...

那么为什么Postman可以连接到服务器而react却失败呢?我错过了什么?

编辑:深入挖掘一下,我注意到来自 React 的请求失败并出现 403 Forbidden... 但我看不出是什么导致一个请求失败而另一个请求成功..

GET /socket HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:131.0) Gecko/20100101 Firefox/131.0
Accept: */*
Accept-Language: de,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate, br, zstd
Sec-WebSocket-Version: 13
Origin: http://localhost:3000
Sec-WebSocket-Extensions: permessage-deflate
Sec-WebSocket-Key: -----------------------==
DNT: 1
Sec-GPC: 1
Connection: keep-alive, Upgrade
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: websocket
Sec-Fetch-Site: same-site
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket

(Websocket 密钥已删除)

reactjs spring-boot websocket
1个回答
0
投票

所以问题是react.js请求在spring-boot应用程序中触发了cors,而postman请求省略了origin header,从而跳过了cors检查。

现在我将 WebSocketConfigurer 更改为

@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
    registry.addHandler(new ServerWebSocketHandler(), "/socket")
            .setAllowedOrigins("http://localhost:3000");
}

避免这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.