Why this not working nothing to explain more? - node.js

When I open two tabs in session after logout in one tab when I try to change data of another tab without reload page at a time redirect not working console shows the message and after that API call.
app.use(function(request, res, next) {
console.log(req.session.user);
if (req.session.user) {
next();
} else {
console.log("index.html")
res.redirect("/");
//res.end ();
}
});

Related

NodeJS Express Routing - Only first request gets rendered

In the server script I try to deliver different html files. When app.post('/login'...) comes in, res.sendFile() is working and the html gets rendered. On the second call, whenn app.get('/go') comes in, the file gets served, but not displayed. I cannot explain why the second HTML file is not displayed. What am I doing wrong?
the second request comes from a fetch request in a javascript
socket.on('gameStarted', (data) => {
console.log("Game started");
fetch('/go', {method: 'GET'});
})
served but not displayed
app.post('/login', async (req, res, next) => {
var roomNR = req.body.player.gameCode;
var playerName = req.body.player.nickname;
var codeValid = await checkCode(activeRoomsCollection, gameCodes, roomNR);
var playerExists = await playerCollection.findOne({ playerName: playerName })
if (codeValid) {
if ((playerExists === null) || !playerExists) {
playerCollection.insertOne({ room: roomNR, playerName: playerName, state: false });
console.log(`Added player '${playerName}' with roomnumber '${roomNR}'`);
res.sendFile(path.join(__dirname + '/../../public/lobby.html'), function (err) {
if (err) {
console.log(err);
res.status(err.status).end();
}
else {
console.log('Sent Lobby');
}
});
} else {
// updateDomElement(player, elementId, data)
//res.send('Benutzername existiert bereits');
}
} else {
res.send('Code ungültig');
}
});
app.get('/go', (req, res, next ) => {
res.sendFile(path.join(__dirname + '/../../public/raetsel1.html'), function (err) {
if (err) {
console.log(err);
res.status(err.status).end();
}
else {
console.log('Sent Raetsel1');
}
});
});
fetch() never displays anything on its own. It's a way for your Javsascript to issue http requests to remote servers and those servers then return content back to your Javascript. The result from those http requests ONLY goes to your Javascript. Nothing in the view of the page is affected at all by a fetch() call.
If you want the result of a fetch() call to display something in your page, you would need to write Javascript to do that (to insert content into the current page).
If, instead, you just want the browser to go to a new page, then change from this:
fetch('/go', {method: 'GET'});
to this:
window.location = "/go";
This will cause the browser to go to the URL, retrieve the content and display it. This will shut-down the current page and load and display a new page and the URL in the URL-bar in the browser will show the updated location.
Note that if you have socket.io code in both pages, it will disconnect the current socket.io connection and then run the Javascript in the new page - causing it to create a new socket.io connection (if you have code in the new page to do that) as that is what happens to socket.io connections when you load and display a new web page in the browser.

Express Flash Message over multiple redirects

I have been using express-flash for a project and it has been working fine with redirects and page renders. However, I have a route /dashboard which redirects further into /dashboard/admin & /dashboard/staff as shown in the code below. Passing a message using req.flash and redirecting to /dashboard does not show up on the page. Other pages with single redirects are able to display the messages without any issue. I am guessing this problem is because of the second redirect from /dashboard to /dashboard/.*
req.flash('success_msg','Successful');
res.redirect("/dashboard");
in router.js:
app.get('/dashboard', (req, res) => {
if (req.user.role === "ADMIN") {
res.redirect("/dashboard/admin");
}
if (req.user.role === "STAFF") {
res.redirect("/dashboard/staff");
}
})
Is there a way to work around this issue, adding any statement in my router file to forward messages further into the redirects?
The flash message with value Successful is only available inside the req object in the middleware that handles the /dashboard endpoint. If you want to further redirect, you have to assign again the flash message to the next middleware.
app.get('/dashboard', (req, res) => {
// If there is any flash message with key success_msg,
// give it to the next middleware
if (res.locals.success_msg) {
req.flash('success_msg', res.locals.success_msg)
}
if (req.user.role === "ADMIN") {
res.redirect("/dashboard/admin");
}
if (req.user.role === "STAFF") {
res.redirect("/dashboard/staff");
}
})

res.sendFile() not sending file (no errors)

I have a simple login page using passport.js.
$("#loginUser").on("click", function () { //login button handler
var User = {
username: $('#username').val().trim().toLowerCase(),
password: $("#password").val().trim()
};
//$("#password").val("");
$.post("/login", User);
});
The code for the post route for "/login" is below (taken from passport docs):
app.post('/login', function (req, res, next) {
passport.authenticate('local', function (err, user) {
if (err) { return next(err); }
if (!user) { return res.redirect('/'); }
req.logIn(user, function (err) {
if (err) { return next(err); }
return res.redirect('/home/' + user.user_id);
});
})(req, res, next);
});
Below is the code for the "home" route:
app.get("/home/:user?", function (req, res) { //home page
console.log(req.params.user)
if (req.user) {
console.log(path.join(__dirname, "../public/home.html"))
res.sendFile(path.join(__dirname, "../public/home.html"), (err) => {
if (err) {
console.log(err);
} else {
console.log('file sent!');
}
});
}
else {
console.log("no user");
res.sendFile(path.join(__dirname, "../public/login.html"));
}
});
The issue I'm having is when the page is supposed to redirect to the home page, it just does nothing. The console.log("file sent") will trigger with no errors, even though nothing happens and the page stays on the login screen. However, if I physically type in localhost://8080/home the page will then load perfectly fine.
It's not a matter of your server not sending the file - it's a matter of your web page isn't redirecting properly.
Ajax calls which you are using with this code:
$.post("/login", User);
do not redirect automatically. All they do is return the 302 response to your Ajax completion handler Javascript (which you don't have any code for). So, your request is delivered to the server. Your server sends a 302 redirect response, that 302 response comes back to your Javascript and gets dropped on the floor by your Javascript.
Only URLs put in the browser bar or URLS clicked on by the user or browser-only form posts (not done from Javascript) will redirect automatically. Ajax calls do not redirect automatically - they just deliver the redirect status and location back to your Javascript where your Javascript has to then process it in order to do anything.
You have a couple of choices to fix:
Switch to a plain browser form post with no Javascript and then the browser itself will see and follow the redirect.
Use a completion handler for your Ajax call, check the status and if it's a 3xx response, then get the Location header and set window.location = xxx to the location in that header to cause the redirect to happen.
I haven't tested this, but here's the general concept for checking the status and manually redirecting based on a 3xx status.
$.post("/login", User).then((data, textStatus, jqXHR ) => {
if (jqXHR.status >= 300 && jqXHR.status <= 399) {
window.location = jqXHR.getResponseHeader("Location");
} else {
console.log("not a redirect status of:", jqXHR.status);
}
});

Response headers of previous request affecting current request

The following code is the user-facing part of a new node app we are building:
var loadInvoice = function(req, res, next) {
Invoice.findById(req.params.invoiceId, function (err, invoice) {
if (err) {
res.send(404, 'Page not found');
} else {
req.invoice = invoice;
next();
}
});
};
app.namespace('/invoices/:invoiceId', loadInvoice, function () {
app.get('', function(req, res){
var templateVals = {
//some template data
};
res.render('paymentselection', templateVals);
});
app.post('', function(req, res){
var data = {
// some data for the apiCall
};
someAPI.someRequest(data, function(err, data) {
console.log(res.status());
res.redirect(data.url);
});
});
});
The first method returns a confirmation page where the user presses a button to post to the same url, which triggers a redirect to an external website.
This all works exactly once. Every second request will crash the app with the message Cant set headers after they are sent. After carefull inspection of the code I could find no reason for this to happen so I added the console.log line which indeed confirms the location header has been set. But it is set to the value i got from someAPI on the previous request not the current one.
This makes absolutely no sense to me. I do not store this value anywhere nor do I do caching or persistence of this data in any way.
Does anybody know what could be causing this?
I use express, express-namespace, mogoose and swig
I found out the problem was being caused bij the 'Restler' libaray used within 'someAPI'. I have no idea how this is possible but swapping it out with something else fixed the problem.

Handle jade errors in res.render()

I have a working node.js / express based server and am using jade for templating. Usually there is no problem but a couple of times every day I get an error message when requsting any page. The error is 'failed to locate view'. I don't know why i get this error since it worked fine just minutes before.
The question however is how I can force a crash on this event, for example:
res.render('index.jade', {info: 'msg'}, function(error, ok) {
if (error)
throw new Error('');
// Proceed with response
};
How would I do this? And how would I proceed with the response?
thank you.
You can add an error handling middleware.
app.use(function handleJadeErrors(err, req, res, next) {
// identify the errors you care about
if (err.message === 'failed to locate view') {
// do something sensible, such as logging and then crashing
// or returning something more useful to the client
} else {
// just pass it on to other error middleware
next(err);
}
});
Try this:
app.use(function (req, res, next) {
fs.exists(__dirname + '/views/' + req.url.substring(1) + '.jade', function (exists) {
if(!exists) {
console.log(err);
return next();
}
res.render(req.url.substring(1), { title: "No Controller", user: req.session.user });
}
});

Resources