totalnoob
totalnoob

Reputation: 2741

expressjs / nodejs general routes conflicting with wildcard

full code looks like this

		/* /login [get] */
		app.get('/login', function(req, res) {
		  res.render('login');
          return;
		});


	app.get('/stats', requireLogin, function(req, res) {
		User.findOne({ _id: req.user.id})
		.populate('current')
		.exec(function(err, stats) {
			if (err) res.json(err)
			res.render('stats', stats);
			return;
		})
	});
		/* /username */
		app.get('/:username', requireLogin, function(req, res) {
			console.log("sdf");
			User
			.findOne({ username: req.params.username }, 'friends')
			.exec(function(err, user) {
				console.log(user)
			})
      
going to /login  renders the login page, but also triggers the console.log of "sdf from the next route

In my app, one can access /someusername

I have that route defined as

app.get('/:username', function(req, res) {

but because I also have these general ones like /stats and /login

app.get('/stats', function(req, res) {})
app.get('login',  function(req, res) {})

going to these also accesses the /:username route.

how do I prevent that?

(the /:username route is the last one in the code)

Upvotes: 1

Views: 836

Answers (2)

jfriend00
jfriend00

Reputation: 707298

Routes are processed by Express in order. So, if you put the /stats route before the /:username route and you don't manually force routing to continue further by calling next(), then things will work for you. The more specific route will be found and processed first.

But, this is probably a bad URL design when you have conflicting URLs. What if a user was named "stats", then their username URL would never work. And, what if you then want some other URL such as /login or /about. All of those would conflict with potential user names. That's just a bad design.

Probably, you should change to something like this:

app.get('/user/:username', function(req, res) {...}

So, no user name route can ever conflict with your /stats route or any other top level route you choose. This will keep your top level path available to direct routes into categories and would be a much better URL design.


And, as we discovered in further discussion, the browser requesting the favicon for the page will also hit your /:username route. You can make a special route for the favicon or you can insert meta tags in the page to prevent a favicon request or you can stop using a top level wildcard route that catches these types of things. Note, you'll probably also catch things like when bots request /robots.txt too.

Upvotes: 4

Santosh
Santosh

Reputation: 1839

(the /:username route is the last one in the code)

It should work if you have put username route at last of all the other routes.

If you want username route to be at top,you can validate in the /:username route , but it is not recommended and bad design.

var reseredKeywords = ['stats', 'login'];
app.get('/:username', function(req, res, next) {
  if (reseredKeywords.indexOf(req.param.username.toLowerCase())) {
    next();
  }
  // else handle your username here
})

Upvotes: 1

Related Questions