Express Router Middleware acts on unintended routes - node.js

I'm trying to use Express Middleware to validate that users are authorized for some of my requests. But, some requests do not require any validation. In a router, I have something like this:
// Routes that end in /transactions
module.exports = function(router, isAuthenticated, acl) {
router.post('/transactions', isAuthenticated, acl.isAdminOrFrom, TransactionHandler.transactions.post);
// Get most recent transactios by general, category, or userId
router.get('/transactions/:timeStamp', isAuthenticated, TransactionHandler.transactions.findMostRecent);
router.get('/transactions/categories/:category/:timeStamp', isAuthenticated, TransactionHandler.transactions.category.findMostRecent);
router.get('/transactions/users/:user_id/:filter/public/:timeStamp', isAuthenticated, TransactionHandler.transactions.userId.findMostRecent);
// Get the total reps traded on Repcoin so far
router.get('/transactions/totaltraded', TransactionHandler.transactions.total.get);
Notice that the last route I've listed does not have isAuthenticated there. But, putting that middleware in the above routes has made it act in the last one as well. I also tried something like this:
router.use('/transactions/:timeStamp', TransactionHandler.transactions.findMostRecent);
router.get('/transactions/:timeStamp', TransactionHandler.transactions.findMostRecent);
But the middleware still seems to execute on anything that calls router.get(). How can I use my middleware on a per-route basis?

I think this could be because router.post('/transactions', ... matches before router.get('/transactions/totaltraded', .... You could try to change the ordering so that the latter route definition is before former and see if it makes any difference. Also try to debug which handlers it triggers on a given route.

Related

Some Express.Router() routes do not execute middleware function

I'm trying to wrap my head around my implementation of express.router() not triggering of the middleware function assigned to it.
I wrote a pretty big app and trying to add a few more endpoints to my path, but for some reason the 9th route gets loaded but does not trigger the function.
app.js
server.use(cors());
server.use(function (req, res, next) {
next();
});
server.use("/", express.static("./assets"));
server.use("/api", api);
server.use("/debug", debug);
server.use("/config", config);
server.use("/control", control);
server.use("/tools", files);
And this is where I declared my routes with the respective functions.
router.get("/teams", onGetTeams);
router.get("/players", onGetPlayers);
router.get("/achievements", getTop3);
router.get("/xpression", onXprPayload);
router.get("/snapshot", onRequestSnapshot);
router.get("/round-timeline", onRequestTimelinePayload);
router.get("/:half", onRequestHalf);
router.get("/dashboard-message", onSetDashboardMessage);
router.get("/get-match-odds", getTeamOdds);
function getTeamOdds(req, res) {
console.log("Sent odds");
res.json(odds);
res.end();
}
When I make the request for the last route, the function does not get executed, and I get back a 200 response.
Is there something big I'm missing?
Thank you !
Your route definition here:
router.get("/:half", onRequestHalf);
is a wildcard route that matches ALL routes so none of the routes after it will get called unless that specific route calls next() to continue routing.
Top level wildcard routes are problematic for this reason. I would suggest avoiding them. There are temporary work-arounds like moving their definition to be the last top level route definition, but they can still be limiting for defining future routes because they are so greedy.
My recommendation would be to not make it a top level route:
router.get("/half/:half", onRequestHalf);
So, it won't conflict with the other top level routes and it essentially has it's own URL scope all to itself.

Express route: some routes are not recognised [duplicate]

I'm trying to wrap my head around my implementation of express.router() not triggering of the middleware function assigned to it.
I wrote a pretty big app and trying to add a few more endpoints to my path, but for some reason the 9th route gets loaded but does not trigger the function.
app.js
server.use(cors());
server.use(function (req, res, next) {
next();
});
server.use("/", express.static("./assets"));
server.use("/api", api);
server.use("/debug", debug);
server.use("/config", config);
server.use("/control", control);
server.use("/tools", files);
And this is where I declared my routes with the respective functions.
router.get("/teams", onGetTeams);
router.get("/players", onGetPlayers);
router.get("/achievements", getTop3);
router.get("/xpression", onXprPayload);
router.get("/snapshot", onRequestSnapshot);
router.get("/round-timeline", onRequestTimelinePayload);
router.get("/:half", onRequestHalf);
router.get("/dashboard-message", onSetDashboardMessage);
router.get("/get-match-odds", getTeamOdds);
function getTeamOdds(req, res) {
console.log("Sent odds");
res.json(odds);
res.end();
}
When I make the request for the last route, the function does not get executed, and I get back a 200 response.
Is there something big I'm missing?
Thank you !
Your route definition here:
router.get("/:half", onRequestHalf);
is a wildcard route that matches ALL routes so none of the routes after it will get called unless that specific route calls next() to continue routing.
Top level wildcard routes are problematic for this reason. I would suggest avoiding them. There are temporary work-arounds like moving their definition to be the last top level route definition, but they can still be limiting for defining future routes because they are so greedy.
My recommendation would be to not make it a top level route:
router.get("/half/:half", onRequestHalf);
So, it won't conflict with the other top level routes and it essentially has it's own URL scope all to itself.

Router in nodejs does not seem to work as I expect it

I am building simple app to teach myself node and I've got this problem.
Console.log is not executed at all. Do you have any idea why?
I have 404 error but nothing else. App doesnt crash, I just cant get this view.
router.get('/charts/top/:exercise', function(req, res, next) {
console.log("exercise: " + req.params.exercise);
res.render("top", {});
});
SOLUTION: Since this was in separate routes folder in charts.js file, there should not be /charts but just /top/:exercise
Assuming your router comes from :
var express = require('express');
var router = express.Router();
You will need to export this module for your server to know that these routes are handled. with the following :
module.exports = router;
Under all your routes definitions.
Now, your app just needs to call this said file with the routes to be handled.
var handler = require('./handler');
-Some code-
app.use('/', handler);
.use will set the primary pivot of the route to your router. It gives the ball to it. In this exemple, everything from / will be passed to router. If you really want to make this clean, change your router variable in your file to charts and use it in your app to everything that starts with /charts
Then in your charts file you will be able to handle /top/:exercice
You can make multiple levels of routing like this with .use to set your new point of handling.
Also, I would like to point out that you don't need "next" in your function because you do not have any callback.
Edit : And remember, if 2 routes could be handled, it will always be the first one declared to catch it. That way, declare some routes with a if else logic behind it. Giving the more specific choice first.

Express 4 route handling with named parameters and router.param()

Is there a clean way to handle key/value query params in Express 4 routes?
router.route('/some/route?category=:myCategory')
I want to detect the presence of 'myCategory' in this route and use router.param([name], callback) to handle the associated logic.
router.param('myCategory', function(req, res, next, id) {
/* some logic here... */
});
The above 'router.param()' works fine if I have a route like /some/route/:myCategory but fails if I use
router.route('/some/route?category=:myCategory')
Am I doing something wrong here, or is this not supported in the Express 4 router out of the box?
Express treats properties after a ? as query params. So for:
/some/route?mycategory=mine
you would have to use:
req.query.mycategory or req.query['mycategory']
See this for more examples.

Placeholder segments in express middleware mount points

When using Express I can define routes with a placeholder in the route string, something like:
app.get("/users/:user_id/photos", function(req,res){<blah>});
and then in my handler I can user req.params["user_id"] to get whatever was in the URL and use it in my request.
Middleware can be mounted at certain paths such that only requests matching that path will use the middleware. Can I use placeholders in the mount path of a middleware? For example, could I do something like:
app.use("/users/:user_id/photos", <middleware>);
and then inside the middleware have some way of accessing what the segment that maps to :user_id was?
EDIT 1:
I am aware that I can put the middleware directly in the route declaration, à la:
app.get("/users/:user_id/photos", <middleware>, function(req,res){<blah>});
It doesn't take much imagination to see how that would get out of hand as an app grows.
Middlewares are chaining in the order you add them.
middleware = function(req,res,next){
if(valid(req))
next();
else
res.send(400, "Emergerd");
}
// First middleware
app.get("/users/:user_id/photos", middleware);
app.get("/users/:user_id/photos", function(req,res){
// function after middleware
});

Resources