Refreshing web page causes it to crash - node.js

When I refresh the page, the page crashes every time, I have tried replacing 'end' with 'write', have I just not learnt enough code yet to prevent this? It seems like in the tutorial I am following that this should be working whenever I refresh. Initially starting the webpage is no problem though
const http = require('http');
//connection settings
//port is a end point of communication
const port = 3000;
// hostname: IP associated with any deivce on a network
const hostname = '127.0.0.1';
const respond = (request, response) => {
//response.setHeader('Content-Type', 'text/plain');
//writeHead (stațus code, {headers})
//response.writeHead(200, { 'Content-Type': 'text/html' })
if (request.url === '/about') {
response.end("about")
}
if (request.url === '/') {
response.end("home page");
}
response.end("error page")
/*
socket.on('error', function(e){
console.log(e);
});
was searching up a solution but this^ did not work
*/
};
const url = require('url');
const server = http.createServer(respond);
server.listen(port, hostname, () => { console.log('Server listening on port 3000') })
enter image description here

It's the response.end("error page"). That's running unconditionally on every request, even when one of your if statements is true.
Perhaps you meant to do an if...else if...else? This would fix your problem.
if (request.url === '/about') {
response.end('about');
} else if (request.url === '/') {
response.end('home page');
} else {
response.end('error page');
}

Related

NodeJS server results in timeout

I have a NodeJS server script, which works like a charm on my local dev environment. But in (beta) production the webserver times out at every request. I've set this up fairly straight forward but I'm unsure how to fix it - or even where to look for a solution. Below is a simplified implementation, my logic for handling post request has been removed. What am I overlooking?
var requestListener = '';
// define the request listener, to handle incoming requests
requestListener = function (req, res) {
try {
if (req.method == 'POST') {
var queryString = '';
req.on('data', function (data) {
queryString += data;
});
req.on('end', function () {
// my logic is in here
res.end(JSON.stringify({ err: false, msg: 'all fine' }));
});
}
res.writeHead(200);
res.end();
} catch (error) {
res.writeHead(400);
res.end(error);
}
}
// boot the webserver
server = http.createServer(requestListener);
server.listen(8080);

nextJS / NodeJS keeps triggering ip_ban

So not sure why, but my nodeJS / NextJS app keeps triggering plesks ip_ban. I recoded our site and moved it away from ReactJS to NextJS. But seems by doing so their must be a command that is making it look like an IP address is trying to connect to many times which makes the plesk server add the IP to a ban list (the rule that keeps getting triggered is - recidive).
I am wondering what is the correct way to solve this issue. Disabling ip_ban is a temp solution but not the ideal solution.
my server.js script is very clear and has no issues (once ip_ban is disabled).
const { createServer } = require("http");
const { parse } = require("url");
const next = require("next");
const dev = process.env.NODE_ENV !== "production";
const port = !dev ? process.env.PORT : 3000;
// Create the Express-Next App
const app = next({ dev });
const handle = app.getRequestHandler();
app
.prepare()
.then(() => {
createServer((req, res) => {
const parsedUrl = parse(req.url, true);
const { pathname, query } = parsedUrl;
handle(req, res, parsedUrl);
console.log("pathname", pathname);
}).listen(port, (err) => {
if (err) throw err;
console.log(`> Ready on http://example.com:${port}`);
});
})
.catch((ex) => {
console.error(ex.stack);
process.exit(1);
});
The rule that keeps getting triggered:
[recidive]
enabled = true
filter = recidive
action = iptables-allports[name=recidive]
logpath = /var/log/fail2ban.log
maxretry = 3

Automatic exit - NodeJS https webserver

To elaborate on the question in the title,
I have made a simple app with js that runs on a node server. I have a thumbdrive that contains a folder and a start.bat file. Start.bat, as the name implies, switches the directory to my server folder and starts the server. Start.bat also starts another process that opens the edge browser to localhost in kiosk mode. When a user starts start.bat, the app will appear on the screen with the server running in the background. When the user exits the edge browser, they are then required to CTRL + C out of the server cmd prompt to properly shut down the server.
I need a system which effectively automatically shuts down the server after the Edge browser has been closed. I am not sure if it is possible to tie together the closing of the browser and the node server and am yet to find a solution online. If anyone has any ideas regarding possible fixes to my problem I would love to hear it!
https-server.js
const https = require("https");
const path = require("path");
const fs = require("fs");
const ip = require("ip");
const process = require("process");
const app = express();
const port = 443;
process.chdir("..");
console.log("Current working dir: " + process.cwd());
var rootDir = process.cwd();
//determines what folder houses js, css, html, etc files
app.use(express.static(rootDir + "/public/"), function (req, res, next) {
const ip = req.ip;
console.log("Now serving ip:", "\x1b[33m", ip, "\x1b[37m");
next();
});
//determines which file is the index
app.get("/", function (req, res) {
res.sendFile(path.join(rootDir + "/public/index.html"));
});
var sslServer = https.createServer(
{
key: fs.readFileSync(path.join(rootDir, "certificate", "key.pem")),
cert: fs.readFileSync(path.join(rootDir, "certificate", "certificate.pem")),
},
app
);
//determines which port app (http server) should listen on
sslServer.listen(port, function () {
console.log(
"Server has successfully started, available on:",
"\x1b[33m",
ip.address(),
"\x1b[37m",
"listening on port:",
"\x1b[33m",
+port,
"\x1b[37m"
);
console.log("CTRL + C to exit server");
sslServer.close();
});
Will provide any needed information.
Have an endpoint registered to exit the process
app.get('/shutdown', (req, res, next) => {
res.json({"message": "Received"});
next();
}, () => {
process.exit();
});
Then register a listener for onbeforeunload to do a request to this endpoint.
let terminateCmdReceived = false;
async function shutdown(e) {
let response;
if (!terminateCmdReceived) {
e.preventDefault();
try {
response = await fetch('http://localhost:3000/shutdown');
const json = await response.json();
if(json.message === "Received") {
terminateCmdReceived = true;
window.close();
}
} catch (e) {
console.error("Terminate Command was not received");
}
}
}
window.onbeforeunload = shutdown

XMLHTTPRequest not working on server on localhost

I'm developing a node.js RESTful server for home use on a RPI with Raspbian, and for testing, I've created a test HTML page that makes various XMLHttpRequests to it.
When developing I'm using a test nodemon server on my dev machine (a desktop machine, not the RPI), running on localhost:4000, and the test HTML page points to it.
Whenever I'm ready to commit the changes, I push them to the server (the RPI), even the test page. It should connect to the server on localhost.
Something bizzare happens whenever I'm testing the page on the server: localhost is not recognized in the XMLHttpRequest.open method, but if I put the address of the server machine in the network (not 127.0.0.1, but 192.168.1.X for example), it works.
The Command netstat -vltn shows that the node server is listening on port 4000, I've enabled CORS, I've already tried to write 127.0.0.1 instead of localhost, and I've even modified the app.listen function to listen to 0.0.0.0, like this:
app.listen(port, '0.0.0.0', function () {
console.log('RESTful API server started on: ' + port);
});
but still, every request from the test page hosted on the server, to localhost:4000 doesn't work.
My problem here is that, if I need to push the test page on the server, I need to manually change the IP address for the XMLHttpRequest each time, instead of just keeping localhost. Is there a way to enable the use of localhost?
EDIT: I'm adding some client code to flesh out the problem.
testpage.html (the one that should work both on the dev machine and the RPI)
<html>
<head>
<script type="text/javascript">
function sendData() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
// Typical action to be performed when the document is ready:
document.getElementById("demo").innerHTML = xhttp.responseText;
}
};
xhttp.onerror = function(e) {
console.log('error', e);
};
xhttp.open("POST", "http://127.0.0.1:4000/auth/loginTest", true);
xhttp.setRequestHeader("Content-Type", "application/json");
//I've omitted the part where I'm prepping a json with username/password data
xhttp.send(jsonString);
}
</script>
</head> <!--I'm skipping the rest of the code as there's only a div that
catches the json info sent by the server -->
server.js (the one that gets started on the RPI with node server.js)
var express = require('express');
var cors = require('cors');
var bodyParser = require('body-parser');
var port = process.env.PORT || 4000;
var auth = require(/*path to Auth middleware*/);
var app = express();
app.use(bodyParser.json({ type: 'application/json' }));
app.options('*', cors());
app.use(cors());
app.use('/auth', auth);
process
.on('unhandledRejection', (reason, p) => {
console.error(reason, 'Unhandled Rejection at Promise', p);
})
.on('uncaughtException', err => {
console.error(err, 'Uncaught Exception thrown');
process.exit(1);
});
app.listen(port, function () {
console.log('RESTful API server started on: ' + port);
});
Try changing this code:
app.listen(port, '0.0.0.0', function () {
console.log('RESTful API server started on: ' + port);
});
to this:
app.listen(port, function () {
console.log('RESTful API server started on: ' + port);
});
This will allow your app to listen on both IPv4 and IPv6. It is possible that localhost is resolving to the IPv6 address and your code is only listening on the IPv4 address. I know that a MAC uses IPv6 for localhost.
The other thing to try is stop using the word localhost on the client and use 127.0.0.1 and see if that makes any difference.
UPDATE:
Below is my server code that I generated from yours and it seems to work:
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const port = process.env.PORT || 4000;
function sendPage(req, res, next) {
console.log('sending page');
res.send(`<html>
<head>
<script>
function sendData() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
// Typical action to be performed when the document is ready:
document.getElementById("demo").innerHTML = xhttp.responseText;
}
};
xhttp.onerror = function(e) {
console.log('error', e);
};
xhttp.open("POST", "http://127.0.0.1:4000/auth/loginTest", true);
xhttp.setRequestHeader("Content-Type", "application/json");
//I've omitted the part where I'm prepping a json with username/password data
xhttp.send('{"user":"dog","pw":"woof"}');
}
</script>
</head>
<body onload="sendData()">
<h1>Test page</h1>
<div id="demo"></div>
<hr/>
</body>
</html>`);
}
function auth() {
console.log('auth called');
var router = express.Router();
router.post('/loginTest', (req, res, next) => {
console.log('auth was called');
console.log(req.body);
res.json({error: false, data:'hi'});
});
return router;
}
const app = express();
app.use(bodyParser.json({ type: 'application/json' }));
app.options('*', cors());
app.use(cors());
app.get('/', sendPage);
app.use('/auth', auth());
process
.on('unhandledRejection', (reason, p) => {
console.error(reason, 'Unhandled Rejection at Promise', p);
})
.on('uncaughtException', err => {
console.error(err, 'Uncaught Exception thrown');
process.exit(1);
});
app.listen(port, function () {
console.log('RESTful API server started on: ' + port);
});
If this doesn't come close to matching your code let me know where I got it wrong.
Sorry for the delay. I forgot to post the solution.
My approach will never work, because when the test page is loaded, it will try to execute a script on http://localhost:4000, which is fine if the page is loaded from the machine where the server is listening, but obviously won't work if it's on another machine (hence the ERR_CONNECTION_REFUSED error).
If I load this page from the server machine it will try to execute the script on my machine, which is an invalid request.
So I've solved it by simply substitute http://localhost:4000 in the request with the actual IP of the machine, e.g http://Write.Real.Address.Here:4000.

Webtracker using nodejs

I'm trying to create a webtracker to track what pages my users are seeing and how much time they are spending at each page, at the end they will make a registration and i will associate their navigation with the created user.
I want to use node because i can see when the user connect to the url and disconnect to calculate the time, i have tried that with pure javascript but i can see when the user leaves the page only on Chrome.
I have already managed to create some of what i need using the socket.io lib but i can't find a way to use it without creating an html page. What i need is to create something like google analytics where i will only incorporate the script. Is it possible?
I have managed to figure it out so i will post it to help others with the same problem:
Server
let socket = require('socket.io');
let http = require('http');
let serveStatic = require('serve-static');
let finalhandler = require('finalhandler');
var port = process.env.PORT || 1337;
let serve = serveStatic(__dirname, { 'index': ['client.js'] });
let server = http.createServer(function (req, res) {
serve(req, res, finalhandler(req, res));
});
let io = socket(server);
server.listen(port);
io.on('connection', client => {
console.log('new user connected!', client.id);
client.on('hello', data => {
console.log('data: ', data);
});
client.on('disconnect', () => {
console.log('user disconnected', client.id);
});
});
Client
(function (plugin) {
plugin.socket = null;
function loadDependencies() {
head.js(
{ socket: 'https://cdn.socket.io/socket.io-1.4.5.js' }
);
head.ready('socket', function() {
plugin.socket = io('http://localhost:1337');
setSocketHandlers();
});
}
function setSocketHandlers() {
plugin.socket.on('my-event', function(data){
console.log('called my event');
});
}
plugin.init = () => {
loadDependencies();
}
}(this.WebTracker = this.WebTracker || {}));
WebTracker.init();

Resources