Express route not getting called when url param is not passed

Viewed 3594

I have the following code in my server.js for route middleware:

app.use('/users', require('./routes/user.routes'));
app.use((req, res) => res.status(404).json({code: 404, message: 'HTTP 404 Not Found'}));

And following is my user.routes.js code

router.get('/admin/:id', (req, res) => {
    return userController.findUserById(req, res);
});

It works fine as long as I give : localhost:8080/users/admin/123 But when I give the url without id localhost:8080/users/admin/

it sends me this message : {"code":404,"message":"HTTP 404 Not Found"}

In my opinion it should direct me to proper route. Am I missing something?

3 Answers

If you want to have id parameter optional, you can add a ? after it in your route handler:

router.get('/admin/:id?', (req, res) => {
    return userController.findUserById(req, res);
});

Now, both /admin/123 and /admin will hit this same route. But your code might fail if there is no id passed along. If this is the case, you should specify 2 different routes:

router.get('/admin', (req, res) => {
    return userController.findUserById(req, res);
});


router.get('/admin/:id?', (req, res) => {
    return userController.findDefaultUser(req, res);
});

I believe you can get this to work by providing a custom validator:

router.get('/admin/:id(\\d{0,})', (req, res) => {
    ...
});

My validator checks that the id is 0 or more numbers, which will match an empty string. If your id is not numeric then you'll have to adapt the regex accordingly. Note that Express uses a special regex syntax which has slightly different rules from normal JavaScript RegExp, for example in Express 4 you can't use use * so I've had to use {0,} instead (see https://github.com/expressjs/express/issues/2495).

Update

Using a ? as suggested by Mohit Bhardwaj is a simpler solution but there are slight differences between the approaches. Using the validator I suggested above you will still receive an id param but it will be an empty string, whereas with ? the id will not be present in the params at all. Whether or not this matters will depend on how you use it.

It is also worth noting that using a ? will also allow /users/admin to match, without the trailing slash.

If you don't care about validating the id string as part of route matching then I think using ? would be the way to go.

The route now expects an id after /user/ (even if there is a /user route), so if there is no ID you will get the 404 Error. A nice way to fix this, is by using /user/detail/:id as route. Now it doesn't conflict with the user route.

Related