0

I have two routes as follow in my ExpressJs application

router.get("/task/", Controller.retrieveAll);
router.get("/task/seed/", Controller.seed);

If I make a request on /task/seed/ instead of Controller.seed, Controller.retrieveAll is getting called.

So basically router matches the /task/ string before it checks the proceeding string, in my case /seed.

How can I make sure that the router does check the full string (kind of exact match)?

Asad Ullah Khalid
  • 140
  • 1
  • 3
  • 13
  • Can you provide a reproducible example? See https://stackoverflow.com/help/minimal-reproducible-example – JBaczuk Aug 26 '21 at 21:12
  • 2
    Does this answer your question? [Order of router precedence in express.js](https://stackoverflow.com/questions/32603818/order-of-router-precedence-in-express-js) – Asad Jivani Aug 26 '21 at 21:17
  • @AsadJivani yes it does. Actually, I raised this question because I was hoping to see some alternative to the order of paths but it seems like there's none. – Asad Ullah Khalid Aug 26 '21 at 21:38

2 Answers2

3

The example you show using router.get() or app.get() does not actually occur. router.get() does not do partial matches unless you're using wildcards or regexes.

I verified that in this simple test app:

const express = require('express');
const app = express();

app.get("/task/", (req, res) => {
    res.send("got /task");
});

app.get("/task/seed", (req, res) => {
    res.send("got /task/seed");
});

app.listen(80);

When you request /task/seed, you get the message got /task/seed so, it does route correctly.


On the other hand, router.use() does do partial matches so this problem could occur if your actual code was using .use(), not .get(). In that case, you just need to either switch to the verb-specific .get() instead of using the generic .use() or you need to order your routes from the most specific to the least-specific so that the most-specific declaration gets a chance to match first:

router.use("/task/seed/", Controller.seed);
router.use("/task/", Controller.retrieveAll);

In case you're curious, the two main differences between router.use() and router.get() are:

  1. .get() only matches GET requests while .use() matches all HTTP verbs.
  2. .get() only does full path matches while .use() will match any URL path that starts with what you specify.
jfriend00
  • 683,504
  • 96
  • 985
  • 979
2

Execution of express router middleware functions is sequential. There is no keyword like exact, as we have in react-router to make the router check for exact path match.

To make your code work, and always when creating express routes, have the path with the higher specificity above the path with lesser specificity.

So, this should work:

router.get("/task/seed/", Controller.seed);
router.get("/task/", Controller.retrieveAll);

These earlier StackOverflow answers will be very helpful:

  1. https://stackoverflow.com/a/32604002/6772055
  2. https://stackoverflow.com/a/27317835/6772055
Karan Sapolia
  • 640
  • 9
  • 18
  • Thanks! I was hoping to get to know about some alternatives other than the order of routes. But since your answer solves the problem I will upvote it for sure. – Asad Ullah Khalid Aug 26 '21 at 21:40
  • This is not correct. `router.get()` does not do partial matches. `router.use()` does, but that is not what the OP shows in their question. – jfriend00 Aug 27 '21 at 01:11