superkytoz superkytoz - 3 months ago 11
Node.js Question

Cannot GET /login

When I click on the login link then I go to the to

/login
. Which looks like this link to screenshot:

enter image description here

Notice the response
Session not found
which was given to my Angular 2 app after it made a request. To check if a user
is logged in. This is all working good.

But when I refresh the page then I get the following error
Cannot GET /login
link to screenshot:

enter image description here

To fix that error I had added the following in my Express app:

//We use this to avoid the error: Cannot GET /login
//but if we use this, then we can't receive a session on the Angular 2 app..
app.route('/*').get(function(req, res) {
return res.sendFile(path.join(__dirname, 'public/index.html'));
});


Now I can refresh the page without getting the error
Cannot GET /login
. But the problem now is that I'm getting the following
error:
Unexpected token < in JSON at position 0
when my Angular 2 app wants to check if a user is logged in.
Here is also a screenshot of it:

enter image description here

Instead I should get the error as a response
Session not found
. But unfortunately this didn't happened.

Here is the code of my Express app:

app.js:

var express = require('express');
var path = require('path');
var bodyParser = require('body-parser');
var index = require('./routes/index');
var projects = require('./routes/projects');
var app = express();
var mongoose = require('mongoose');
var config = require('./config/config');
var session = require('express-session');

if (app.settings.env === "development") {
mongoose.connect(config.getDbPath(app.settings.env));
}

var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function () {
// we're connected!
});

// view engine setup
app.set('views', path.join(__dirname, 'views'));

app.use(function (req, res, next){
res.setHeader('Access-Control-Allow-Origin', "*");
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, content-type');
next();
});

app.use(session({
secret: 'keyboard cat',
resave: true,
saveUninitialized: true
}));

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));

app.use(express.static(path.join(__dirname, 'public')));

//We use this to avoid the error: Cannot GET /login
//but if we use this, then we can't receive a session on the Angular 2 app..
//app.route('/*').get(function(req, res) {
// return res.sendFile(path.join(__dirname, 'public/index.html'));
//});

// we are mapping the routes to end points.
app.use('/', index);
app.use('/api/auth', require('./controllers/AuthController'));
app.use('/api/v1/', projects);

// TODO: catch 404 and forward to error handler

var port = 3000;

if(process.env.NODE_ENV === "test") port = 3002;

var server = app.listen(port, function () {
var host = 'localhost';
var port = server.address().port;
console.log('App listening at http://%s:%s', host, port);
});
module.exports = app;


index.js:

var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function (req, res, next) {
res.render('index.html');
});
module.exports = router;


Here is also a screenshot of my folder structure of my project link to screenshot:

enter image description here

Also here is a link to my repository on Github in case you want to see more of the code of my project link:
https://github.com/superzaky/node-portfolio-zaky/tree/refresh-problem

Anyone that maybe knows how I can solve this?

Answer

When you refresh the page at /login, the call for this URI is made on the backend and as you can see you don't support handling that route there. The code you put was correct, but you have to place it below all your route handlers. So place:

app.route('/*').get(function(req, res) { 
    return res.sendFile(path.join(__dirname, 'public/index.html')); 
});

Below the lines:

app.use('/', index);
app.use('/api/auth', require('./controllers/AuthController'));
app.use('/api/v1/', projects);

Now the frontend will be loaded for every URI that isn't explicitly defined in the backend, which makes it possible for you to still use your backend API calls. Just make sure the frontend and backend don't use the same URI's.