Param parsing twice for nested routes in Express - node.js

When I make GET http://localhost:8080/messages/3/sentiments for the code below why param method is called two times? So If I have 10 routes it will be called 10 times?
var comments = new Router();
comments.get('/comments', function (req, res, next) {
res.send('Comments by message_id=' + req.message._id);
})
var sentiments = new Router();
sentiments.get('/sentiments', function (req, res, next) {
res.send('Comments by message_id=' + req.message._id);
})
var messages = new Router();
messages.param('_message', function (req, res, next, _id) {
console.log("Set message");
fs.readFile(__filename, function () {
req.message = { _id: _id };
next();
});
})
messages.use('/messages/:_message/', comments);
messages.use('/messages/:_message/', sentiments);
app.use(messages);
app.listen(8080);

Confirmed to be a bug in Express < 4.3
https://github.com/visionmedia/express/issues/2121

Related

Switch between routers Express

I want to display a website completely different in function of an arbitrary value.
Let's say I have two routers
const express = require('express');
const app = express();
const router1 = express.Router();
router1.get('/', (req, res, next) => res.json({message: 'I am the router1'}))
const router2 = express.Router();
router2.get('/', (req, res, next) => res.json({message: 'I am the router2'}))
app.use((req, res, next) => {
if(Math.random() > 0.5) {
// Use router1
} else {
// Use router2
}
})
I have no idea how I can do that. I will have a lots of routes (router.get, router.post) I don't want to check that on each route
Thanks
Just return a call to the router:
app.use((req, res, next) => {
if(Math.random() > 0.5) {
return router1(req, res, next)
} else {
return router2(req, res, next)
}
})
This can also be done by usage of .next('router') method.
Here is an example:
const router1 = express.Router();
router1.use((req, res, next) => {
console.log("This gets called everytime!");
if(Math.random() > 0.5)
next('router');//skip to next router object
else
next();//continue with current router
});
router1.get('/',(req, res, next) => {
console.log("Continuing with current router");
res.send("Continuing with current router");
});
const router2 = express.Router();
router2.get('/', (req, res, next) => {
console.log("Skipped Router 1, continuing with router 2");
res.send("Skipped Router 1, continuing with router 2");
});
//binding both routers here
app.use("*", router1, router2);
.next('router') basically skips to next router object, which has been mentioned in the app.use line, if only next() is used then it continues with current router methods.
Why not just?
if(Math.random() > 0.5) {
app.use(router1);
} else {
app.use(router2);
}

how to group api in express

Here is the example:
var app = require('express')();
function validateToken(req, res, next) {
// Do something with request here
next();
};
app.get('/user/login', function(req, res) {
//code
});
app.post('/user/register', function(req, res) {
//code
})
app.put('/user/register', validateToken, function(req, res) {
//code
})
app.delete('/user/delete', validateToken, function(req, res) {
//code
})
If I have 10 api that need validToken, I should add validToken middleware 10 times, like:
app.method('......', validateToken, function(req, res) {
//code
})
app.method('......', validateToken, function(req, res) {
//code
})
....
app.method('......', validateToken, function(req, res) {
//code
})
app.method('......', validateToken, function(req, res) {
//code
})
How can I group api by using the same middleware?
Here's how to re-use the same callback function for multiple routes (like middleware):
var app = require('express')();
function validateToken(req, res, next) {
// Do something with request here
next();
};
app.get('/user/login', function(req, res) {
// code
});
app.post('/user/register', function(req, res) {
// code
});
// Be sure to specify the 'next' object when using more than one callback function.
app.put('/user/register', validateToken, function(req, res, next) {
// code
next();
});
app.delete('/user/delete', validateToken, function(req, res, next) {
// code
next();
});
Also, you can replace app.METHOD (e.g. .post, .get, .put, etc.) with app.all and your callback will be executed for any request type.
Just wrong, so do not put into mass participation of the (Google translated from: 刚才看错了,改成这样就不用放进传参了)
var group = {url:true,url:true,url:true};
app.use(function(req,res,next){
if(group[req.url]){
// Do something with request here
next();
} else {
next();
}
})

Express middleware - router.use issue

I have this simple code:
var express = require('express');
var router = express.Router();
router.get('/', function (req, res, next) {
req.lectalApiData = {
Model: Email,
conditions: req.query
};
router.use(function(req,res,next){ //this is not executing
console.log('do that')
res.json({ok:'OK'});
});
});
I clearly am doing something wrong, but according to the docs, it says I can use this syntax:
http://expressjs.com/guide/routing.html
what am I doing wrong?
perhaps it's because the router.use is nested inside a router.get -
so my question then becomes - how do I create more middleware for that same route inside the router.get middleware?
Just keep adding functions to router.get('/',, they get executed in order. Don't forget to call next.
router.get('/', function (req, res, next) {
req.lectalApiData = {
Model: Email,
conditions: req.query
};
next(); // pass off to next middleware
}, function(req,res,next){
console.log('do that')
res.json({ok:'OK'});
});
or better:
function doThis(req, res, next) {
req.lectalApiData = {
Model: Email,
conditions: req.query
};
next(); // pass off to next middleware
}
function doThat(req, res) {
console.log('do that')
res.json({ok:'OK'});
}
router.get('/', doThis, doThat);

Module route separation

When I use http://tes.com/routes, it will route to the api=>get('/'), instead of web=>get('/'). Why?
app.js:
var api = require('./app/routes/routes').api;
var transaction_web = require('./app/routes/routes').web;
app.use('/api/routes', transaction_api);
app.use('/routes', transaction_web);
routes.js:
var api = (function () {
router.get('/', function (req, res, next) {
...
});
return router;
})();
var web = (function () {
router.get('/', function (req, res, next) {
...
});
return router;
})();
module.exports = {
api: api,
web: web
};
The reason is because that's the order in which you're adding the routes.
This:
var api = (function () {
router.get('/', function (req, res, next) {
...
});
return router;
})();
is the same as:
router.get('/', function (req, res, next) {
...
});
var api = router;
The same thing happens with the other block where you assign web, so you end up with:
router.get('/', function (req, res, next) {
// api route
});
var api = router;
router.get('/', function (req, res, next) {
// web route
});
var web = router;
The solution would be to create separate Router instances. For example:
var api = new express.Router();
api.get('/', function (req, res, next) {
// web route
});
var web = new express.Router();
web.get('/', function (req, res, next) {
// web route
});

Seperate api and web in route

Trying to separate api and web route:
route/index.js
var api = function () {
router.get('/:id', function (req, res, next) {
...
});
return router;
}
var web = function () {
router.get('/:id', function (req, res, next) {
...
});
return router;
}
module.exports = {
api: api,
web: web
};
app.js
var indexAPI = require('./app/routes/accounts').api;
var indexWeb = require('./app/routes/accounts').web;
app.use('/api/index', indexAPI);
but it didn't route successfully.
I have change it to and it is working:
var api = (function () {
router.get('/:id', function (req, res, next) {
...
});
return router;
})();
var web = (function () {
router.get('/:id', function (req, res, next) {
...
});
return router;
})();
module.exports = {
api: api,
web: web
};

Resources