Home > Net >  How do I manage GET random and GET by ID calls in REST API?
How do I manage GET random and GET by ID calls in REST API?

Time:11-08

I want to get a random character from MongoDB, but my call keeps getting used in another GET method.

// Get Specific Character by ID
router.get('/:char_id', async (req, res, next) => {
    try {
        const character = await Character.find({ char_id: req.params.char_id });
        if (character.length == 0) return res.status(404).json({ message: 'No characters found with ID: '   req.params.char_id });
        else { res.status(200).json(character) };
    } catch (err) {
        res.status(500).json({ message: err.message });
    }
});

// Get Random Character
router.get('/random', async (req, res, next) => {
    try {
        const characters = await Character.find();
        if (characters.length == 0) return res.status(404).json({ message: 'No characters found in the database. Something must have went wrong.' });
        else {
            const random = Math.floor(Math.random() * characters.length);
            res.status(200).json(characters[random]);
        };
    } catch (err) {
        res.status(500).json({ message: err.message });
    }
});

When I call /characters/random, I get this error because first GET method above tries to pass word random to find character by ID (If I'm not wrong).

"message": "Cast to Number failed for value "random" (type string) at path "char_id" for model "Character""

How do I avoid this?

CodePudding user response:

You can just put the second route above the first route. That works in similar cases for me.

CodePudding user response:

A route like this:

router.get('/:char_id', ...)

is a wildcard route. It matches EVERYTHING at its level. So, it will match your intended ID, but it will also match /random. Thus, it "eats" your /random request and that request never gets to your actual handler for /random.

A quick fix here is to make sure the wildcard route is LAST on the router. That way, all the other routes get first dibs at the incoming request and only the left-over requests that didn't match some other handler will go to your wildcard route.

This is the desired order of your route declarations:

router.get('/random', async (req, res, next) => { ... });

// put this one last on the router
router.get('/:char_id', async (req, res, next) => { ... });

Even better would be to not use a wildcard route (that matches everything) at all, but rather define a regex for your char_id that would ONLY match your intended id strings and would not match other route paths.

  • Related