Node js, socket.io after fixing cors error I get a new error that I can't fix - node.js

I'm new to web development, javascript, and node js.
I know that there are a lot of questions on the cors error already I have spent 2 days looking at solutions to my problem but I can't figure out how to solve this cors error.
yesterday after 2 days of searching I finally found a solution that worked at first but now it only works 20% of the time and the other 80% I get another error.
I set up my socket.io and tried to send sockets through socket.io exactly as shown in this youtube video:
https://www.youtube.com/watch?v=rxzOqP9YwmM&t=5s
Although my code was exactly the same as in the video I kept getting a cors error when sending sockets.
Here is some of my server-side code:
const io = require("socket.io")(3000);
var fs = require('fs');
io.on("connection", socket => {...
Here is some of my client side code:
const socket = io("http://localhost:3000");
socket.on("new_partner", recieved_data => {
partner_user.username = recieved_data;
socket.emit("logged_in", this_user.username);
});
...
Here is the head of my html:
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<meta charset="utf-8">
<title>real time chat</title>
<link rel="stylesheet" href="chat_room.css">
<script defer src="http://localhost:3000/socket.io/socket.io.js"></script>
<script defer src="script.js"></script>
<script defer src="login.js"></script>
</head>
Here is the cors error I kept getting with the above code:
Access to XMLHttpRequest at 'http://localhost:3000/socket.io/?EIO=4&transport=polling&t=NP9ZPIk' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
After A LOT of searching I changed my server-side code to this:
const io = require("socket.io")(3000, { cors: { origin: "*", }, });
var fs = require('fs');
io.on("connection", socket => {
The first time I ran the new code everything worked PERFECTLY. After some additional testing, I soon realized this method only works 20-30% of the time. The other 70% of the time I kept getting some other random errors. today when I tried to reproduce the errors to be able to ask on StackOverflow (here) for some help, I wasn't getting the same error as yesterday anymore. I don't know what exactly is going on since I'm a huge beginner to web development but here are the errors I keep getting today when I try to send sockets to my server from my client:
GET http://localhost:3000/socket.io/socket.io.js net::ERR_CONNECTION_REFUSED
Uncaught ReferenceError: io is not defined
at script.js:1
Uncaught ReferenceError: socket is not defined
at login.js:1
I should also mention that with this new method unlike with the cors error I can get my site to load but once I try sending sockets that's when the error pops up in the console.
I know this is probably basic and that one of these days I really need to sit down and thoroughly look at the socket io documentation, but I really don't have the time with this project's deadline right now.
Again I apologize for my ignorance and thanks in advance.
Here is all of my code if it helps:
html(index.html): https://pastebin.com/RQ7zNzdy
client-side script(script.js): https://pastebin.com/1P0DJ6HH
client side login(script.js): https://pastebin.com/fqtNRQvg
server side script(server.js): https://pastebin.com/NTL6ynup
css of my website(not that it matters): https://pastebin.com/24rF8urG

Here is the post that might help.
To verify if that is the problem try running client from e.g. Firefox.

Related

How can I addEvent listeners in my node/express app?

I am still trying to get my head around what's possible with frontend vs backend. I still don't understand how to incorporate the likes of an eventListener into my app when I can't select the document.
I have created a script.js file and added it to my public directory:
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Hours Calculator</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/styles.css">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<script src="https://kit.fontawesome.com/391e6a689e.js" crossorigin="anonymous"></script>
<script src="/script.js"></script>
</head>
<body>
and I am serving this folder/files in my app.js like so:
app.use(express.static(__dirname + '/public'));
However I am unable to target anything in my script.js, for example:
let h1 = document.body.querySelector('h1');
h1.style.color = 'brown';
Doesn't work. h1 is undefined.
I am sure there is an extremely straight forward explanation but there are some gaps in my understanding and would like if someone can explain to me why this isn't working and how I can get the front end and the back end interacting.
The Node.js "events" module and the "EventEmitter" module facilitates communication between objects in Node. The EventEmitter module is at the core of Node's asynchronous event-driven architecture. Here is how you can create custom events and emit them:
const EventEmitter = require('events');
const myEmitter = new EventEmitter();
//Event Listener
const EventListenerFunc = () => {
console.log('an event occurred!');
}
//Registering the event with the listener
myEmitter.on('eventName', EventListenerFunc);
//Emitting the event
myEmitter.emit('eventName');
Javascript is a Scripting language. It is basically used on the client-side. JavaScript can run in any engine like JavaScript Core (Safari), Spider monkey (Firefox), V8 (Google Chrome).
NodeJS is a Javascript runtime environment. NodeJS code can be run outside the browser. It is mostly used on the server-side.
Node.js only runs in a V8 engine that is mainly used by Google Chrome. Nodejs comes with a lot of modules and mostly used in web development. Node.js makes the Javascript more powerful and adds many great features to it.
Node.js does not provide a built-in DOM, so you can't access document object in Node.js and there are several modules which can construct a DOM from a string of HTML source code. Two popular DOM modules are cheerio and jsdom. You can make use of these modules to have an access to DOM level manipulation of the data in your code.

Service worker can't fetch assets offline

I'm trying to make my website work offline, but it doesn't seem to work.
My project is based on node.js with external js files generated by angular.
It all seems to work fine, when the server is running and I go to localhost:3000, the service worker is installed correctly, then if I go to the Application tab in the Chrome Devtools, and I check "Offline" and I reload the page, it also works.
But if I turn off my server and I reload the page, I get the following error in my console: An unknown error occurred when fetching the script.
Here is my index.html:
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel='stylesheet' href='/stylesheets/style.css' />
<link rel="icon" type="image/x-icon" href="/dist/favicon.ico">
<link href="/dist/assets/fontawesome.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Roboto:100,100i,300,300i,400,400i,500&display=swap" rel="stylesheet">
</head>
<body>
{% block body %}{% endblock %}
</body>
<script src="/client.js"></script>
<script src="/service-worker.js"></script>
<script src="/dist/runtime-es2015.js" type="module"></script>
<script src="/dist/polyfills-es2015.js" type="module"></script>
<script src="/dist/runtime-es5.js" nomodule></script>
<script src="/dist/polyfills-es5.js" nomodule></script>
<script src="/dist/styles-es2015.js" type="module"></script>
<script src="/dist/styles-es5.js" nomodule></script>
<script src="/dist/vendor-es2015.js" type="module"></script>
<script src="/dist/main-es2015.js" type="module"></script>
<script src="/dist/vendor-es5.js" nomodule></script>
<script src="/dist/main-es5.js" nomodule></script>
</body>
</html>
client.js:
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('./service-worker.js')
.then(function() { console.log('Service Worker Registered'); });
}
service-worker.js:
var cacheName = 'myCacheVersion';
var filesToCache = [
'/dist/favicon.ico',
'/dist/runtime-es2015.js',
'/dist/polyfills-es2015.js',
'/dist/runtime-es5.js',
'/dist/polyfills-es5.js',
'/dist/styles-es2015.js',
'/dist/styles-es5.js',
'/dist/vendor-es2015.js',
'/dist/main-es2015.js',
'/dist/vendor-es5.js',
'/dist/main-es5.js',
'/client.js',
'/service-worker.js',
];
self.addEventListener('install', function(e) {
console.log('[ServiceWorker] Install');
e.waitUntil(
caches.open(cacheName).then(function(cache) {
console.log('[ServiceWorker] Caching app shell');
return cache.addAll(filesToCache);
})
);
});
self.addEventListener('activate', function(e) {
console.log('[ServiceWorker] Activate');
e.waitUntil(
caches.keys().then(function(keyList) {
return Promise.all(keyList.map(function(key) {
if (key !== cacheName) {
console.log('[ServiceWorker] Removing old cache', key);
return caches.delete(key);
}
}));
})
);
return self.clients.claim();
});
self.addEventListener('fetch', function(e) {
console.log('[ServiceWorker] Fetch', e.request.url);
e.respondWith(
caches.match(e.request).then(function(response) {
return response || fetch(e.request);
})
);
});
Any idea on why it doesn't work?
Here is what I have in the console when I'm in the fake offline mode:
And here is what I have when I'm really offline
First of all: never cache service-worker.js! Remove it from the files to cache. The browser has a local copy of it available and that one will be used as long as the browser updates the script from the server. There should never be a reason to put the script in the cache managed by SW. This, <script src="/service-worker.js"></script>, is also something you're not supposed to do. service-worker.js should not be included via regular script tags but only via the navigator.serviceWorker.register(...) call, as you do in your other file :)
You're getting the error because your browser, through Service Worker, is trying to load the root of your server and it's not available. Loading that results in a not available error and it's also not found in yuor Service Worker's cache because you're not caching it (not listed in the files to cache).
I really wonder how this code you provided can actually work offline at all since it's not caching your root page. It should not work offline at all – the Service Worker is NOT caching the root and hence should not be able to get anything from the cache while offline.
It is worth nothing that browsers having no connection (offline) and the website being unavailable (server down) are two completely different scenarios. In the former the SW knows that the network is not available and can take that into consideration when deciding how to response (if told so). In the latter, however, the browser is trying to get something from the network – which itself is working – but the destination itself is unavailable. This is a failure in connecting to the site, not offline mode. In the latter the SW has to decide how to handle, maybe fallback to an offline.html placeholder page, and most notably not cache the response.

React/Node Uncaught SyntaxError: Unexpected token <

I've tried everything but I'm a bit lost on where I should look into this issue.
What happens is that once you build the react app and deploy it (using node/express), it works perfectly. However, if you build again and take the build folder to the node server, it gives me that syntax error. This only happens if your browser already opened the app once.
I've done research and people were saying that the browser is trying to load the older static files and that's why this occurs. None of their solutions worked though from what I've tried.
I would very much appreciate anyone's help with this issue.
Cheers
Update
As Davin suggested. I looked into the chrome devtools and here is what I got back in the response
<!DOCTYPE html>
<html lang="en" id="html">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<script src="/js/modernizr.js"></script>
<link rel="manifest" href="/manifest.json">
<link rel="shortcut icon" href="/favicon.ico">
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"
integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49"
crossorigin="anonymous"></script>
<link rel="stylesheet" href="/css/mega-nav.css">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.4.1/css/swiper.min.css">
<title>Q Parts</title>
<link href="/static/css/style.css" rel="stylesheet">
<link href="/static/css/main.css" rel="stylesheet">
<link href="/static/css/main-ar.css" rel="stylesheet">
</head>
<body><noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script src="/js/jquery-3.3.1.min.js"></script>
<script src="https://code.jquery.com/jquery-migrate-3.0.1.min.js"></script>
<script src="/js/jquery.mobile.custom.min.js"></script>
<script src="/js/popper.min.js"></script>
<script src="/js/bootstrap.min.js"></script>
<script src="/js/main.js"></script>
<script>$(document).ready(function () { $(".has-children").hover(function () { $(".overlay-lg").addClass("is-visible") }, function () { $(".overlay-lg").removeClass("is-visible") }), $(".cd-primary-nav li").click(function () { $(".cd-primary-nav").animate({ scrollTop: $(".nav-is-visible").offset().top }, "200") }) })</script>
<script type="text/javascript" src="/static/js/main.957b5c6e.js"></script>
</body>
</html>
Thank you everyone, for helping me out with this issue. I took #Davin's suggestion and opened the dev tools (in chrome). I googled the same issue but added _sw-precache. Eventually, I found people were facing the same issue so here is what they suggested:
Just add <base href="/" /> into the of my index.html fixed it for me.
https://github.com/webpack/webpack/issues/2882#issuecomment-280906981
This error almost always means that some code is trying to JSON.parse something that is an HTML document.
It is very difficult to know what is happening based on the information you have provided.
I'd suggest to look at the chrome devtools Network tab, and see what call to the server is generating the error. Look at the response, it is probably HTML when js is expected.
In my case method with base href in index.html doesn't help.
My project has separate repositories for web and server.
Problem was in wrong paths in express config, I have made those changes and app start works:
app.use(express.static(path.join(__dirname, '../../../../web/build'))); // the same directory as below
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, '../../../../web/build/index.html'));
});
There are two things I see that might be the problem. One, I see from your comment that the code to handle the response is res.sendFile(${__dirname}/${buildPath}/index.html I think what you want is actually
res.sendFile(`${__dirname}/${buildPath}/index.html` // Note the backticks
If that's not it, I would think that you are serving that same HTML file to requests for your .js, .css, etc files. Are you using some type of static file middleware? If you use that, it will serve an actual file if it exists on the server, and serve your index.html file for everything else.
To check, you can open your chrome developer tools and look at the request for your javascript file (main.js or whatever you have it named). Is it the correct javascript, or is it the HTML from index.html? If it is the HTML, you need to look at this, assuming you are using express server: https://expressjs.com/en/starter/static-files.html

Is socket.io.js supposed to return an empty file?

I trying to make a small chat website using node.js and socket.io.
To include the socket.io.js on my client-sided files:
<script src="192.168.0.108:1337/socket.io/socket.io.js"></script>
But is it normal that it returns an empty file?
http://screencast.com/t/HPAjAqV13q8q
I would also like to add that if on my server-sided file, I do res.write('Hello World'), the 'Hello World' Will appear on the web-page AND in the socket.io.js file
You can try this:
<script src='/socket.io/socket.io.js'></script>
And you should created a client io.connect
var socket = io.connect('http://localhost:5000');
You can also use socket.io's auto-discovery feature and don't specify the server
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect();
</script>
What solved it was opening the port on which socket.io was listening, in my case it was 8080... Now my socket.io.js has javascript code inside of it.
Now I am getting a 404 error on a xhr.send(null) in that socket.io.js file, but that is another story...

Socket.io on Heroku: client-side code

I've been having trouble loading the socket.io library for my JS client code on a Node.js app hosted on Heroku.
For now, I have this line at the end of my index.html file:
<script type="text/javascript" src="/socket.io/socket.io.js"></script>
But then, when I do socket = io.connect('http://myherokuapp');in my JS client code, I get an expected 'io is not defined' error.
Any idea how to correctly load the library on Heroku?
Thanks!
Ok so I finally found my way through. I'm sharing in case it helps someone.
I load the script in index.html this way:
<script type="text/javascript" src="http://myapp.herokuapp.com/socket.io/socket.io.js"></script>
It makes sense because the client-side library is actually loaded from the node server and shouldn't be pushed manually.
In my client-side JS file, I instantiate the socket this way:
socket = io.connect('http://myapp.herokuapp.com/');
Also, and this goes beyond the scope of this question, but you can't use websocket on Heroku for now. They have a little note about that here.
Hope this helps!

Resources