Search code examples
node.jslaravelsocket.iocorslaravel-valet

CORS, Laravel Valet, and Socket.io


This feels like it's all way harder than it should be. I am working on an application for a client and am at the end of my rope trying to get this thing running locally. So, I am using Laravel(served through Valet on my mac) and am writing a Socket.io server for handling different dashboard events. Socket.io runs in an https configuration as it will in production and I've got it running on port 3001. I've got both serving content over https, resolved all configuration issues there. However, now I can not stop getting CORS errors whenever I try to connect.

Here is the error I am getting:

Access to XMLHttpRequest at 'https://ags.test:3001/socket.io/?EIO=3&transport=polling&t=1605106550351-47' from origin 'https://ags.test' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

I've done a fair bit of testing on this and found that if I do a GET request to the root (/) of the express server, it works fine and without CORS errors. However, the polling at the url posted in the error above is still providing the same CORS error.

If it isn't abundantly obvious by now, I'm fairly new to the node ecosystem. So what I'm caught up on is what's happening with CORS when it goes from calling 'https://ags.test:3001' to 'https://ags.test:3001/socket.io/*'. Or is it possible that express isn't handling the CORS for socket.io at all?

Something I've seen multiple times in other stackoverflow answers is something along the lines of (from the server) io.origins('*:*') to set the origin policy. However, I can't seem to find documentation on this and calling it (or any of the variations I've seen of it)

So you know what I've already tried, here the server configuration for my Socket.io express server:

app.use(cors());
app.use((req, res, next) => {
    res.header('Access-Control-Allow-Origin', '*');

    // authorized headers for preflight requests
    // https://developer.mozilla.org/en-US/docs/Glossary/preflight_request
    res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
    next();

    app.options('*', (req, res) => {
        // allowed XHR methods  
        res.header('Access-Control-Allow-Methods', 'GET, PATCH, PUT, POST, DELETE, OPTIONS');
        res.send();
    });
});
var options = {
    key: fs.readFileSync('./ags.test.key'),
    cert: fs.readFileSync('./ags.test.crt'),
    origins: '*:*',
    cors: true,
};
const server = https.createServer(options, app);

I've also made adjustments to my laravel site config in valet as seen here https://gist.github.com/poul-kg/b669a76fc27afcc31012aa0b0e34f738 but applied directly to my site-specific config at ~/.config/valet/Nginx/ags.test and restarted.

As you can see, I've tried quite a few different things and am at the "throw everything at the wall to see what sticks" stage of trying to get these servers communicating. Any recommendations?


Solution

  • Okay, took me way too long to figure out what I was missing. Old stackoverflow answers show configuration methods that are no longer supported in Socket.io v3.

    Here's what I was missing to configure this for the most recent version of Socket.io as of the date of posting.

    const server = https.createServer(options, app);
    const io = require('socket.io')(server, {
        cors: {
            origin: 'https://ags.test'
        }
    });