Not able to solve Access-Control-Allow-Origin error

70 Views Asked by At

I am following some course about node.js. Under socket.io section it is teaching make multiplayer pong game using socket.io. But even after following that course it is showing from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. error.

This is server.js

const server = require('http').createServer()


const io = require('socket.io')(server)


server.listen(3000)

 io.on('connection',(socket)=>{        
 console.log("A user is connected")
})

This is index.js

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Pong Clone</title>
    <link rel="icon" type="image/png" 
href="https://s2.googleusercontent.com/s2/favicons?domain=www.jacinto.design">
    <link rel='stylesheet' href='stylesheets/style.css' />
</head>
<body>
<!-- Script -->


    <script type="importmap">
        {
          "imports": {
            "socket.io-client": "https://cdn.socket.io/4.4.1/socket.io.esm.min.js"
          }
        }
      </script>
  
      <script type="module">
        import { io } from "socket.io-client";
  
        const socket = io('http://127.0.0.1:4000')
      </script>



    <script src="javascripts/script.js"></script>
</body>
enter code here

I myself added that importmap script.Because in the course I was following <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==" crossorigin="anonymous"></script> this script was used and const socket = io('http://127.0.0.1:4000') inside script.js showed Uncaught ReferenceError: io is not defined error. script.js is nothing but game logic.

Help me by editing the server.js code so that it can log the message when user connects to the app.

1

There are 1 best solutions below

0
adsy On

It sounds like you are probably loading your client-side application (the HTML/JS) from your local filesystem, as that's why the origin is said to be null. You would know for sure if the URL in your browser shows file://.

You can't easily use remote resources from local file URIs due to purposefully enforced security restrictions on modern browsers, without messing around with special browser flags to disable certain security features (more hassle than it's worth).

Typically, developers don't use local file:// URIs for development, in part because it does not simulate a real production environment effectively, where resources are served over HTTP. What you do instead is run a local webserver on http://localhost that serves the local files over HTTP.

Since you already have a server (NodeJS based), which is dealing with your web sockets, it would make sense to modify that server also to serve your local static assets. This has the major advantage that both your websocket and static files (the HTML/js/css) are served from the same host (localhost), which means those requests aren't cross-origin anyway, so CORS won't block it. This is also how it would usually be in production.

It will also stop CORS from interfering with the download of remote scripts like socketio from CDNs (https://cdn.socket.io/4.4.1/socket.io.esm.min.js) which is a probable source of the io not defined error as well.

express.js is a popular node web framework that bundles in static asset serving.

First npm install --save express in your existing server package then modify server.js:

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

const io = require('socket.io')(server);

// Serve static files from the "public" directory
app.use(express.static('public'));

server.listen(3000, () => {
    console.log('Server is running on port 3000');
});

io.on('connection', (socket) => {
    console.log("A user is connected");
});

You will need to now create a public folder which is a sibling of your server.js file and you should move all your HTML/web assets into that folder.

Now your server is not just serving your websockets, but it's also serving the static HTML/CSS/JS asset etc. The HTML file, if it isn't already, should be called index.html and so will live in public/index.html.

You can modify the call to io() so that it doesn't specify a remote host URL since the default for socket.io is to just call the server that the HTML page is hosted from, which after these modifications are made, is the same server. That will totally workaround any issues relating to CORS.

      <script type="module">
        import { io } from "socket.io-client";
  
        const socket = io()
      </script>

Now start your server and navigate to http://localhost:3000.