Shade
Shade

Reputation: 10011

How can I avoid ExpressJS misinterpreting routes?

I am building a RESTful API using Express. I have several modules, which get combined in a Router, which is the loaded by the app like so:

./user/User.js:

var router = express.Router();

router.post('/login', variousMiddleware, login);
router.get('/:id', variousMiddleware, getUserDetails);
router.put('/:id', variousMiddleware, updateUser);

module.exports = router;

./app.js:

var app = express();

var routes = express.Router();
var User = require("./user/User.js");

routes.use('/user', User);

app.use('/v1/', routes);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handlers
...

So, when I perform a POST /v1/user/login request, or a GET /v1/nonexisting/randomness, everything works correctly.

However, when I perform a GET /v1/user/login or a PUT /v1/user/login request, Express routes these as if they were GET /v1/user/:id and PUT /v1/user/:id respectively, instead of throwing 404 as I would expect it to.

I figure that Express interprets the login part of the route as being a valid value for the :id parameter in these routes.

How can I avoid this?

Upvotes: 1

Views: 55

Answers (2)

Shade
Shade

Reputation: 10011

The required result is achievable by making the route specification unambiguous:

var router = express.Router();

router.post('/login', variousMiddleware, login);
router.get('/:id([a-f0-9]+)', variousMiddleware, getUserDetails);
router.put('/:id([a-f0-9]+)', variousMiddleware, updateUser);

module.exports = router;

By defining the range of acceptable values for ID we avoid the misinterpretation.

Upvotes: 0

Wake
Wake

Reputation: 1696

The reason GET /v1/user/login and PUT /v1/user/login are being handled by your '/v1/user/:id' routes is you haven't set up a PUT or GET handler for '/login'. You've only set up the POST handler.

If you change it to:

var router = express.Router();

router.post('/login', variousMiddleware, login);
router.get('/login', variousMiddleware, login);
router.put('/login', variousMiddleware, login);
router.get('/:id', variousMiddleware, getUserDetails);
router.put('/:id', variousMiddleware, updateUser);

module.exports = router;

then you will be able to handle GET and PUT requests.

Another alternative would be to change your "/:id" route to something specifically meant to handle your RESTful operations. Something like:

var router = express.Router();

router.post('/login', variousMiddleware, login);
router.get('/data/:id', variousMiddleware, getUserDetails);
router.put('/data/:id', variousMiddleware, updateUser);

module.exports = router;

Upvotes: 0

Related Questions