Carlo Gonzales
Carlo Gonzales

Reputation: 365

Express JS routes issue. Returns 404 when accessing resource with subpaths and params in the middle

I'm using MEAN stack from meanjs and have this routes:

// Teams Routes
app.route('/teams')
    .get(teams.list)
    .post(users.requiresLogin, teams.create);

app.route('/teams/:teamId')
    .get(teams.read)
    .put(users.requiresLogin, teams.update)
    .delete(users.requiresLogin, teams.delete);

app.route('/teams/:teamId/participants')
    .get(teams.teamParticipants);


// Finish by binding the Team middleware
app.param('teamId', teams.teamByID);

The issue here is, whenever I'm accessing a resource with this path:

[GET]
http://localhost:3000/teams/547dd53b964b3514294d2dfe/participants

it always return a 404 status. When the request reaches the server, it's accessing

teams.teamByID

from param but wasn't been able to proceed to:

teams.teamParticipants

What I wanna know if there's something I'm doing wrong when it comes to defining my routes, and if there's any better way of defining routes.

Thank you in advance.


EDITS @mscdex Here's my teamByID

exports.teamByID = function(req, res, next, id) { 
    Team.findById(id).exec(function(err, team) {
        if (err) return next(err);
        if (! team) return next(new Error('Failed to load Team ' + id));
        req.team = team ;
        next();
    });
};

Upvotes: 0

Views: 1370

Answers (2)

Carlo Gonzales
Carlo Gonzales

Reputation: 365

I found the problem here. I dig into express' code and checked how it handle its routes.

Express handles the routes callbacks based on the number of arguments the function has.

If the function for the route has four(4), like the one I have:

exports.teamParticipants = function(req, res, next, id) {
    Participant.find({team: id}, function(err, participants){
        if (err) return next(err);
        if (! participants) return next(new Error('Failed to load Participants from Team  ' + id));
        res.jsonp(participants);
        next();
    });
};

It would use its 'handle_error' of its Layer class, passing four arguments: error, req, res, and next.

If the route has less than 4 arguments, it would use 'handle_request' method of it Layer class, passing 3 main arguments: req, res, next. So correcting my 'teamParticipants' method, I should have this kind of implementation for it to work:

exports.teamParticipants = function(req, res) {
    Participant.find({team: req.team._id}, function(err, participants){
        if (err){
            return res.status(400).send({
                message: errorHandler.getErrorMessage(err)
            });
        } else {
            res.jsonp(participants);
        }
    });
};

So far, the issue here was Express handles param and route differently. I thought that param and route passed the same arguments.

param handler has this signature: param(req, res, callback, value, key)

which is different from routes route's handler signatures:

route(req, res, next)

route(err, req, res, next)

Upvotes: 1

DexterBrylle
DexterBrylle

Reputation: 3

I've been using this npm module, expresspath. It separates your controllers/middlewares. :)

Upvotes: 0

Related Questions