Search code examples
expresssocket.iocorslocalhostlocalserver

Why can't I connect to localhost server from localhost client (cors error)?


I have a local (Angular) client running on port 4200 (http://localhost:4200) and a local (express) server on port 5000 (http://localhost:5000). Whenever I try to connect to my server, I get this message.

Access to XMLHttpRequest at 'http://localhost:5000/socket.io/?EIO=4&transport=polling&t=NU7H' from origin 
'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Here is the code to start my local server

@injectable()
export default class App {
  app: express.Application;

  constructor() {
    this.app = express();
    this.config();
    this.bindRoutes();
  }

  // Middlewares config
  private config(): void {
    this.app.use(cors());
    this.app.use(express.json());
    this.app.use(express.urlencoded({ extended: true }));
  }

  bindRoutes(): void {
    this.app.use('/', router);
  }
}

Here is the code where I set up my socket

private _ioServer: SocketIO.Server;

initSocket(server: http.Server) {
    this._ioServer = new SocketIO.Server(server);

    this.connectChat(); // Chat namespace
    this.connectStream(); // Game board streaming namespace
}

I tried with Postman, everything is working.

Thank you!


Solution

  • Any malicious site can take advantage of your cookies stored in the system called Cross-site request forgery

    Any browser tries to prevent you from these attacks so they disable CORS.

    Shorthand Fix [Not recommended] : There are many plugins out there you can use for your local testing that disables these checks on browser.

    Proper Fix: Use an Express middleware to apply Access-Control-Allow-Origin: * in your header when response is returned back from the server.

    Gist is that when browser sends the request to your server it will append Origin: http://localhost:3000 to the headers. Reacting to this request from browser, server should return a Access-Control-Allow-Origin header to specify which origins can access the server's resources.

    You can be strict here to return Access-Control-Allow-Origin: http://localhost:4200 or open your gates by sending Access-Control-Allow-Origin: *.

    Here is the quick code to have an express middleware:

    const express = require('express');
    const request = require('request');
    
    const app = express();
    
    app.use((req, res, next) => {
      res.header('Access-Control-Allow-Origin', '*');
      next();
    });
    
    app.get('/jokes/random', (req, res) => {
      request(
        { url: 'https://joke-api-strict-cors.appspot.com/jokes/random' },
        (error, response, body) => {
          if (error || response.statusCode !== 200) {
            return res.status(500).json({ type: 'error', message: err.message });
          }
    
          res.json(JSON.parse(body));
        }
      )
    });
    
    const PORT = process.env.PORT || 3000;
    app.listen(PORT, () => console.log(`listening on ${PORT}`));
    

    Source: https://medium.com/@dtkatz/3-ways-to-fix-the-cors-error-and-how-access-control-allow-origin-works-d97d55946d9

    P.S, this is a very good read for your understanding of CORS.