Shade Shade - 3 months ago 11
Node.js Question

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?

Answer

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.