Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Express route not getting called when url param is not passed

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?

like image 857
Brijesh Prasad Avatar asked Oct 06 '17 09:10

Brijesh Prasad


People also ask

How routing is working in Express?

Routing refers to how an application's endpoints (URIs) respond to client requests. For an introduction to routing, see Basic routing. You define routing using methods of the Express app object that correspond to HTTP methods; for example, app.get() to handle GET requests and app.post to handle POST requests.

What is router () in Express?

The express. Router() function is used to create a new router object. This function is used when you want to create a new router object in your program to handle requests.

Are Express routes case sensitive?

Because Express routes are not case-sensitive, a request for /SECURE/manageInvoices will return the same resource as /secure/manageInvoices. However, the authentication-checking middleware will not be applied to /SECURE/manageInvoices, allowing an attacker to access the page without logging in.

Which function arguments are available to Express route handlers?

The arguments available to an Express. js route handler function are: req - the request object. res - the response object.


2 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);
});
like image 75
Mohit Bhardwaj Avatar answered Oct 16 '22 12:10

Mohit Bhardwaj


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.

like image 5
skirtle Avatar answered Oct 16 '22 10:10

skirtle