Cannot GET /login

2020-04-18 05:52发布

问题:

When I click on the login link then I go to the to /login. Which looks like this link to screenshot:

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:

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:

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:

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?

回答1:

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.