0

I'm using:

express 4.14 node 7.0+ session 1.14+


I created Nodejs project with webstorm:

app.js

var express = require('express');
var session = require('express-session');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var index = require('./routes/index');
var user = require('./routes/user');

var app = express();

var check = function() {
    !req.session.status ? res.redirect('/user/login') : next();
}

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

app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({secret: "inline", resave: false, saveUninitialized: true,     status: false}));

app.use('/', check, require('./routes/index'));
app.use('/user', require('./routes/user'));

module.exports = app;

index.js

var express = require('express');
var router = express.Router();

router.get('/', function(req, res, next) {
    res.render('index', { title: 'Express' });
});

module.exports = router;

user.js

var express = require('express');
var router = express.Router();

router.get('/', function(req, res, next) {
    res.render('index', { title: 'Express' });
});

router.get('/login', function(req, res, next) {
    res.render('login');
});

module.exports = router;

When I request to localhost:3000, the page prompt me that "too many redirects', now the url is localhost:3000/user/login?

What's my problem?

bren
  • 4,176
  • 3
  • 28
  • 43

2 Answers2

1

fix:

var check = function(req, res, next) {
    !req.session.status ? res.redirect('/user/login') : next();
}




But I'll write more beautiful solution for You, hope You'll get in idea:

app.js:

app.use(require('./routes'));

routes folder:

routes/
 |- index.js
 |- common/
    |- auth.js
 |- root/
    |- index.js
    |- posts.js
 |- backend/
    |- index.js
    |- posts.js
    ...

1) routes/index.js :

const
  express = require('express'),
  router = express.Router();

// guarded routes
function guardFn(req, res, next) {
  let authenticated = req.session && req.session.authenticated === true;
  authenticated ? next() : res.redirect('/auth');
}
router.use('/backend', guardFn, require('./backend'));

// public routes
router.use('/auth', require('./common/auth'); // for auth purposes
router.use('/', require('./root')); // for routes that starts from /, try not to rewrite /backend, /auth

module.exports = router;

2) routes/common/auth :

const
  express = require('express'),
  router = express.Router();
  mongoose = require('mongoose'),
  User = mongoose.model('user');

router.get('/', (req, res) => {
  res.render('common/auth');
});

router.post('/', (req, res) => {
  User
    .findOne({
      username: req.body.username, 
      password: req.body.password
    })
    .exec((err, user) => {
      if(err) {
        console.error(err);
        return res.status(500).send('System error! Try again later');
      }
      if(!user) return res.redirect('back');
      req.session.user = user._id;
      req.session.authenticated = true;
      res.redirect('/backend');
    });
});

function logout(req, res, next) {
  delete req.session.user;
  req.session.authenticated = false;
  next();
}
router.delete('/auth', logout, (req, res) => res.send({success: true}));
router.get('/auth/destroy', logout, res => res.redirect('/auth'));

module.exports = router;

3) routes/root/index.js :

const
  express = require('express'),
  router = express.Router();

router.get('/', (req, res) => {
  res.render('site/welcome');
});

module.exports = router;

4) routes/root/posts.js :

const
  express = require('express'),
  router = express.Router(),
  mongoose = require('mongoose'),
  Post = mongoose.model('post');

router.get('/', (req, res) => {
  Post
    .find()
    .skip((req.query.page-1)*10)
    .limit(10)
    .exec((err, posts) => {
      res.render('site/posts/list', {posts});
    });
});

router.get('/:id', (req, res) => {
  Post
    .findById(req.params.id)
    .exec((err, post) => {
      if(err) {
        console.error(err);
        return res.status(500).send('System error! Try again later');
      }
      res.render('site/posts/show', {post});
    });
});

module.exports = router;

5) routes/backend/index.js :

const
  express = require('express'),
  router = express.Router();

router.get('/', (req, res) => {
  res.render('backend/dashboard');
});

module.exports = router;

6) routes/backend/posts.js :

const
  _ = require('lodash'),
  express = require('express'),
  router = express.Router(),
  mongoose = require('mongoose'),
  Post = mongoose.model('post');

router.get('/', (req, res) => {
  Post
    .find()
    .skip((req.query.page-1)*50)
    .limit(50)
    .exec((err, posts) => {
      res.render('backend/posts/list', {posts});
    });
});

router.get('/:id', (req, res) => {
  Post
    .findById(req.params.id)
    .exec((err, post) => {
      if(err) {
        console.error(err);
        return res.status(500).send('System error! Try again later');
      }
      res.render('backend/posts/show', {post});
    });
});

function updatePost(id, data, callback) {
  Post
    .findById(_id)
    .exec((err, post) => {
      if(err) return callback(err);
      if(!post) return callback('not found');

      post = _.extend(post, data);
      post.save(() => callback(null, post));
    });
}
router.put('/:id', (req, res) => {
  updatePost(req.params.id, req.body, (err, post) => {
    if(err) return res.status(500).send({success: false, err});
    res.send({success: true, post});
  });
});

router.post('/:id', (req, res) => {
  updatePost(req.params.id, req.body, (err, post) => {
    if(err) return res.status(500).send(err);
    res.redirect('/backend/posts');
  });
});

function createPost(data, callback) {
  let post = new Post();
  post = _.extend(post, req.body);
  post.save((err) => callback(err, post));
}
router.post('/', (req, res) => {
  createPost(req.body, (err, post) => {
    if(req.xhr) {
      if(err) return res.status(500).send({success: false, err});
      return res.send({success: true, post});
    }
    if(err) return res.status(500).send(err);
    res.redirect('/backend/posts');
  });
});

module.exports = router;
num8er
  • 18,604
  • 3
  • 43
  • 57
  • i have idea to solve it, but i want to know the result. if i change the `app.use('/', index)` to `app.use('/index', index)`, also change the `router.get('/', (...)=>{...})` to `router.get('/index', (...)=> {...})` and i request to 'localhost:3000/index' , it will change to 'localhost:3000/user/login' without `redirect too many` so i want to know why '/' it will show me 'redirect too many' – CharlesMoone Nov 15 '16 at 12:51
0

As I understand it, app.use('/', ...) will match all requests which is why your check method is being called for all requests.

More good info here.

From Express docs:

A route will match any path that follows its path immediately with a “/”.

For example: app.use("/apple", ...) will match “/apple”, “/apple/images”, “/apple/images/news”, and so on.

I would suggest refactoring to:

var check = function(req, res, next) {
  if (!req.session.status && req.path != '/user/login') {
    res.redirect('/user/login');
  }
  else {
    next();
  }
}

app.use(check);
app.use('/', index);
app.use('/user', users);

So check will execute for all requests but only redirect if the request session is falsey and request path doesn't match /user/login

Keep in mind your code will fail if req.session is not set...

Community
  • 1
  • 1
timothyclifford
  • 6,799
  • 7
  • 57
  • 85
  • :D, so it is not like REX match, `'/user'`will match `'/'` and `'/user'`, right? seems no flexibility.....but eh...whatever – CharlesMoone Nov 16 '16 at 01:55