Zapra Gartiast
Zapra Gartiast

Reputation: 33

How to Use Multiple Route in ExpressJS?

Is it possible to make router in ExpressJS like this?

users.js

const userController = ('../controllers/userController.js');

router.get('/:userName', userController.paramByUsername);
router.get('/:id', userController.paramByUserId);


In the controller, the code look like this

userController.js

function paramByUsername(req, res) {
    User.findOne({
        where: {
            userId: req.params.userId
        }
    })
    .then((user) => {
        if(!user) {
            return res.status(404).json({ message: "User not found."});
        }

        return res.status(200).json(user);
    })
    .catch((error) => {
        return res.status(400).json(error);
    });
}

function paramByUserId(req, res) {
    User.findByPk(req.params.id)
    .then((user) => {
        if(!user) {
            return res.status(404).json({ message: "User not found."});
        }
    }).catch((error) => {
        return res.status(400).json(error);
    });
}


By the code above, what I wanted to achieve is the endpoint like this:
/users/1 this should response same as /users/username.

I have tried the code above, but what I see is an error when I get /users/:id

Upvotes: 0

Views: 70

Answers (1)

jfriend00
jfriend00

Reputation: 708036

You can't do both of these together:

router.get('/:userName', userController.paramByUsername);
router.get('/:id', userController.paramByUserId);

From a pure routing point of view, there is no way to tell the difference between these two. Whichever route you declare first will grab everything at the top level and the second will never get hit.

So, in route design, you HAVE to make sure that each route is uniquely recognizable to the Express route matcher based on what you put in the route pattern.

I suppose that if an id was always just numbers and a username could never be just numbers, then you could use a regex route and match only numbers for the id and everything else for the username, but that seems a bit fragile to me and I'd prefer something a bit more explicit.

I don't know the overall landscape of your app, but you may want to do:

router.get('/user/:userName', userController.paramByUsername);
router.get('/id/:id', userController.paramByUserId);

Or, you could use the query string with URLs like this:

/search?user=John
/search?id=4889

And, then you'd just have one route:

router.get("/search", ....);

And you would examine which properties are present in req.query to decide which item you were looking for.

Upvotes: 1

Related Questions