I have the following express routes defined:
// Questions Routes
app.route('/questions')
.get(questions.list)
.post(users.requiresLogin, questions.create);
app.route('/questions/:questionId')
.get(questions.read)
.put(users.requiresLogin, questions.hasAuthorization, questions.update)
.delete(users.requiresLogin, questions.hasAuthorization, questions.delete);
app.route('/questions/list/:page')
.get(questions.questionList);
app.route('/questions/count/')
.get(questions.count);
Along with this callback trigger for the questionId
route parameter:
app.param('questionId', questions.questionByID);
The expected behavior was to have /questions/count
requests route to the count method in a controller, but it is instead being routed to the questionByID
method and I'm seeing this error:
CastError: Cast to ObjectId failed for value "count" at path "_id"
...
at exports.questionByID (/path/controllers/questions.server.controller.js:137:56)
...
I think this appears because mongoose is trying to convert the literal "count" from the route to an ObjectId type, which would make sense if I was using the /questions/:questionId
route but it doesn't if I'm using /questions/count
to make the request.
These are the two relevant methods in questions.server.controller.js
exports.count = function (req, res) {
console.log('attempting to count these damn questions!');
Question.count({}, function (err, count) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
console.log(count);
res.jsonp(count);
}
});
};
/**
* Question middleware
*/
exports.questionByID = function (req, res, next, id) {
Question.findById(id).populate('user', 'displayName').exec(function (err, question) {
if (err) return next(err);
if (!question) return next(new Error('Failed to load Question ' + id));
req.question = question;
next();
});
};
I've fixed it by setting the route to:
app.route('/questionscount')
.get(questions.count);
But it looks bad and I don't want to do it like that, does anyone know why this is happening?
Thanks in advance.
Since express evaluates the routes in addition order, you should put the more specific routes first. In your example it just evaluates "count" as the questionId parameter because it matches the expression.
If you put the app.route('/questions/count/') route before the app.route('/questions/:questionId') it should work.