【问题标题】:Express CORS is not working with socket.ioExpress CORS 不适用于 socket.io
【发布时间】:2020-08-05 21:17:05
【问题描述】:

我已经为我的快递服务器使用了 cors,但我不知道为什么它不起作用。谁能帮我解决这个问题?

访问 XMLHttpRequest 在 'https://tic-tac-toe-server.now.sh/socket.io/?EIO=3&transport=polling&t=N6Z2b4X' 来自原点“http://localhost:8080”已被 CORS 策略阻止: 请求中不存在“Access-Control-Allow-Origin”标头 资源。

客户:

import io from 'socket.io-client';
const socket = io('https://tic-tac-toe-server.now.sh')

这是我的 index.js

const express = require('express');
const socketio = require('socket.io');
const http = require('http');
const cors = require('cors');


const router = require('./router');
const { addUser, removeUser, getUsers } = require('./users');
const { getMatch, addPlayer, destroyMatch } = require('./players');

const PORT = process.env.PORT || 5000;

const app = express();
const server = http.createServer(app);


const io = socketio(server);

app.use(router);
app.use(cors());


io.on('connection', function (socket) {
    const id = socket.id;
    let user_room = '';

    /**
     * User Joins to the global room
     */
    socket.on('join', function ({ name, room, playing = false }) {
        addUser({ id, name, room, playing }); // add user to users array
        user_room = room;
        socket.join(user_room);
        socket.join(id);
        socket.emit('user_joined', getUsers());
        socket.broadcast.emit('user_joined', getUsers()); // emit event with modified users array
    });

    /**
     * Match Started
     */

    socket.on('player_joined', user => {
        const match = getMatch();
        addPlayer(user.match, user);
        if(match.hasOwnProperty(user.match) && match[user.match].length === 2){
            socket.emit('player_joined', match[user.match]);
            socket.broadcast.to(user.match).emit('player_joined', match[user.match]);
        }
    });

    socket.on('move', (data) => {
        socket.emit('move', data);
        socket.broadcast.to(data.match).emit('move', data);
    });

    socket.on('emote', (data) => {
        socket.emit('emote_from', data);
        socket.broadcast.to(data.match).emit('emote_to', data);
    });


    /**
     * On user challenge
     */


    socket.on('challenge', (socketId) => {
        io.to(socketId).emit('accept', id);
    });

    socket.on('rejected', (socketId) => {
        io.to(socketId).emit('rejected', id);
    });

    socket.on('accepted', data => {
        io.to(data.opponent.id).emit('accepted', data);
        socket.emit('accepted', data);
    });

    socket.on('player_left_match', match => {
        socket.broadcast.to(match).emit('player_left_match');
    });

    socket.on('destroy_match', match => {
        destroyMatch(match);
    });

    /**
     * User Disconnect function
     */
    socket.on('disconnect', () => {
        socket.leave(user_room);
        socket.leave(id);
        removeUser(id); // remove user form users array
        socket.emit('user_left', getUsers());
        socket.broadcast.emit('user_left', getUsers());  // emit event with modified users
    })


});

server.listen(PORT, () => console.log(`Server running on port ${PORT}`));

【问题讨论】:

  • 这里有一个解决方案:socket.io not connecting due to CORs error。
  • @jfriend00 谢谢你的评论,我没看懂这个答案,你能给我一个示例代码吗?
  • 有关该方向的更具体帮助,请将您的客户端 socket.io 连接代码添加到问题中。这就是进行上述更改的地方。
  • @jfriend00 我已经添加了我的客户端连接代码。

标签: javascript node.js express websocket cors


【解决方案1】:

你可以告诉 socket.io 只使用不受 CORS 约束的 webSocket 传输:

const socket = io('https://tic-tac-toe-server.now.sh')

到这里:

const socket = io('https://tic-tac-toe-server.now.sh', {transports: ['websocket']});

一些背景。在其默认配置中,socket.io 使用多个普通 http 请求启动每个连接。如果连接是跨域的,这些普通的 http 请求需要服务器端 CORS 支持。但是,socket.io 可以配置为直接使用 webSocket 传输(无论如何最终都会使用),并且 webSocket 连接不受 CORS 限制。

从 http 轮询开始的 socket.io 设计主要是因为在 webSocket 支持的早期,并不是每个浏览器都支持它,也不是每个服务器基础设施都支持它。但是现在,它得到了广泛的支持。

因此,告诉 socket.io 从一开始就使用 webSocket 传输可以避免许多潜在的 CORS 问题。


我们现在正在处理一个不同的问题,控制台中显示的错误 https://tic-tac-toe-vue.now.sh/ 来自 webSocket.js 中的这段代码。

  try {
    this.ws =
      this.usingBrowserWebSocket && !this.isReactNative
        ? protocols
          ? new WebSocketImpl(uri, protocols)
          : new WebSocketImpl(uri)
        : new WebSocketImpl(uri, protocols, opts);
  } catch (err) {
    return this.emit('error', err);
  }

由于引用了isReactNative,因此看起来与 React 相关,但由于您的代码已打包并最小化,因此从这里进行任何调试都不是很容易。

【讨论】:

  • 使用此代码出现另一个错误:WebSocket connection to 'wss://tic-tac-toe-server.now.sh/socket.io/?EIO=3&transport=websocket' failed: Error during WebSocket 握手:意外响应代码:404
  • @DelowarHosain - 您的客户端代码显示 https 连接。您的服务器代码显示一个 http 服务器。无法使用 https 连接到 http 服务器。你得到一个 404 的事实意味着 https 上确实有一个服务器,但它看起来不像是你显示上面代码的那个。
  • 我部署到https服务器,仍然出现这个错误:tic-tac-toe-vue.now.sh
  • @DelowarHosain - 这显然是另一回事(注意它是一个完全不同的错误)。您在问题中显示的代码本身并不能做到这一点。一种可能的猜测是客户端和服务器之间的 socket.io 版本不匹配。不幸的是,您的代码似乎已在该网站上打包并最小化,因此尝试调试很痛苦。我什至找不到你在页面上使用 socket.io 的地方。看看我在答案末尾添加了什么。
  • 客户端和服务器版本相同。服务器/根:github.com/delowardev/tic-tac-toeVue 客户端:github.com/delowardev/tic-tac-toe/tree/dev/vue-clientBty 非常感谢您帮助我
猜你喜欢
  • 1970-01-01
  • 2015-05-12
  • 2019-11-27
  • 2019-01-28
  • 1970-01-01
  • 1970-01-01
  • 2021-04-10
  • 2017-10-17
  • 1970-01-01
相关资源
最近更新 更多