HelloWorld
HelloWorld

Reputation: 11247

Routing issue, not collecting req.params

I am making a wikipedia clone for a project. My initial edit Route looks like this:

router.get('/edit/:id', function(req, res){
    var id = req.params.id;

    console.log(id);

    models.Page.findById(id, function(err, doc){
        console.log(doc);
        res.render('edit', {page: doc});
    });

});

All I am doing is creating an edit page view for a Page with matching id of the id params. This works until...

I had to add this new route:

router.get('/:url_name/:id', function(req,res){
    var id = req.params.id;

    models.Page.findById(id, function(err, doc){
        res.render('show_page', {page: doc});
    });
});

Now when I have this route active, my edit/:id page route doesn't collect the id parameter(req.params.id).

I am lost on why this isn't working and where I should start trying to debug because I am not getting any errors, it will still take me to my edit/:id page, but when I console.log(id) I do not receive a value, or even and undefined, nothing. Furthermore, the {page:doc} I am passing to my edit view is not being found.

If anyone can provide insight or a place to start looking to debug, I'd appreciate it. Just a reminder, the edit/:id route works as it should (req.params.id grabs the id) when I don't have the :url_name/:id route active.

Current Routes -

I added var wiki_routes = require('./routes/wiki'); in my app.js and in that route I have:

// **** URL ROUTES ****

router.get('/', function(req, res) {
  models.Page.find(function(err, docs) {
    res.render('index', { docs: docs });
  });
});

router.get('/:url_name', function(req, res){
    var url_name = req.params.url_name;
    var isUpdated = req.query.updated;
    var updated = (isUpdated === 'true')?true:false;

    models.Page.find({url_name: url_name}, function(err, page){
        if(page.length > 1){
            console.log(page);
            res.render('disambiguation', {pages: page, updated: updated });

        } else {
            console.log(page);
        res.render('show_page', {page: page[0], updated: updated});
        }
    });
});

router.get('/:url_name/:id', function(req,res){
    var id = req.params.id;

    models.Page.findById(id, function(err, doc){
        res.render('show_page', {page: doc});
    });
});

// **** EDIT ROUTES ****

router.get('/edit/:id', function(req, res){
    var id = req.params.id;

    console.log(id);

    models.Page.findById(id, function(err, doc){
        console.log(doc);
        res.render('edit', {page: doc});
    });

});

router.post('/edit_submit/:id', function(req, res){
    var id = req.params.id;
    var new_title = req.body.title;
    var new_body = req.body.body;

    console.log(req.body);

    models.Page.findByIdAndUpdate(id, {title: new_title, body: new_body }, function(err, docs){
    // redirects to the wiki page
    res.redirect('/wiki/'+ docs.url_name +'?updated=true');
    });
});

// **** DELETE ROUTE ****

router.get('/delete/:id', function(req, res){
    var id = req.params.id;

    models.Page.findByIdAndRemove(id, function(err, data){
        res.redirect('/?deleted=true');
    });
});

Upvotes: 1

Views: 150

Answers (1)

adeneo
adeneo

Reputation: 318212

Routes are set up as they occur in the code, as node will give presedence to whichever route it encounters first, so order matters a lot when you're setting up your routes.
An URL could potentially match several routes, especially when using variables that catch a large number of different URL's, or static routes etc.

Say in your case you have an URL that looks like

http://example.com/edit/1234

That URL would most certainly be caught by this route

router.get('/:url_name/:id' ....

as it matches the http://example.com/something/something layout, and it would also be caught by the following route

router.get('/edit/:id', ....

as it matches the http://example.com/edit/something layout.

What route actually cathes the URL depends on the order they where encountered when set up, whichever route that was declared first will catch the URL.

Just shifting the order of the routes will in most cases solve issues like this

// if the URL matches, this will execute first
router.get('/edit/:id', function(req, res){ 
     // do stuff
});

// You'll only get here if the URL doesn't match the above route
router.get('/:url_name/:id', function(req, res){
     // do stuff
});

There is a workaround if you simply can't swap the routes around, using the next() callback, like this

router.get('/:url_name/:id', function(req, res, next){

     if ( req.params.url_name == 'edit' ) {
         next(); // this sends the request back to look for routes below this one
     }else{
         // do stuff
     }

});

router.get('/edit/:id', function(req, res){
    // now we'll get here when the "url_name" is "edit" ...
});

Upvotes: 2

Related Questions