概要
React を用いた WebSocket チャットアプリケーションの開発中に、CORS ポリシーによるエラーが発生しました
そのエラーを解決した手順、原因を記載します
環境
-
クライアント側
- React: 18.3.1
- Vite: 6.0.5
- TypeScript: 5.6.2
-
サーバー側
- Node.js: 21.2.0
- Express: 4.21.2
- WebSocket: 4.8.1
-
実行環境
- クライアント: http://127.0.0.1:5173
- サーバー: http://localhost:3001
不具合事象
WebSocketで実装したチャットアプリにて
クライアントからサーバーに接続しようとしたが、以下のエラーがブラウザのコンソールに表示されていた
Access to XMLHttpRequest at 'http://localhost:3001/socket.io/?EIO=4&transport=polling&t=t8qibza8' from origin 'http://127.0.0.1:5173' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value 'http://localhost:5173' that is not equal to the supplied origin.
useChatService.ts:31
その他、以下のログも出ていた
GET http://localhost:3001/socket.io/?EIO=4&transport=polling&t=... net::ERR_FAILED 200 (OK)
原因と修正した内容
原因
ブラウザのセキュリティ機能である CORS (Cross-Origin Resource Sharing) によって、クライアント (http://127.0.0.1:5173) とサーバー (http://localhost:3001) の間でクロスオリジンのリクエストがブロックされていました。
この問題は以下事由によって発生していました
- サーバーが送信している Access-Control-Allow-Origin ヘッダーが http://localhost:5173 であった
- クライアントのURL が http://127.0.0.1:5173 であった
よって、ブラウザがオリジンの不一致を検出して上述のエラーが発生。通信がブロックされていた模様
修正内容
修正点1. サーバー側で CORS 設定を修正
修正前のコード
const io = new Server(server);
修正後のコード
const io = new Server(server, {
cors: {
origin: ["http://localhost:5173"],
methods: ["GET", "POST"]
}
});
修正点2. クライアント側でサーバー接続先を明記
viteを使用しているので、vite.config.ts
に以下追記
export default defineConfig({
server: {
host: "localhost",
port: 5173,
},
});
修正点3. クライアント側でio() の接続先を明記
socket.io-client を使って WebSocket インスタンスを生成しているが、io()の接続先を明記する
修正前のコード
socketRef.current = io();
修正後のコード
socketRef.current = io("http://localhost:3001");
まとめ
クライアント側とサーバー間のCORS設定が明記されていないのが原因でした
もし、上述のエラーが出ていた場合、本記事で記載個所を見直されると良いかと思います