简体   繁体   中英

Express CORS is not working with socket.io

I've used cors for my express server, but I can't figure out why it's not working. Can anyone please help me with this issue?

Access to XMLHttpRequest at ' https://tic-tac-toe-server.now.sh/socket.io/?EIO=3&transport=polling&t=N6Z2b4X ' from origin ' http://localhost:8080 ' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Client:

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

Here is my 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}`));

You can tell socket.io to only use the webSocket transport which is not subject to CORS by changing this:

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

to this:

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

Some background. In its default configuration, socket.io starts every connection with multiple plain http requests. These plain http requests require server-side CORS support if the connection is cross-origin. But, socket.io can be configured to go straight to the webSocket transport (which is what is eventually ends up using anyway) and webSocket connections are not subject to CORS limitations.

The socket.io design to start with http polling was largely there because in the early days of webSocket support, not every browser supported it and not every server infrastructure supported it. But now-a-days, it is pretty widely supported.

So, telling socket.io to start with the webSocket transport from the beginning avoids many potential CORS issues.


We are now chasing a different issue and the error showing in the console at https://tic-tac-toe-vue.now.sh/ is coming from this code in 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);
  }

It looks like something React related since there's a reference to isReactNative , but since your code is packaged and minimized, it's not very easy to do any debugging from here.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM