how to extract part of url server side in nodejs express - node.js

Currently working on a nodejs express server. And I think I'm doing something in an inefficient way. I have this route set up
app.get('/admin/scanTable/:table', require('./AUTH/ValidateCookie.js'), require('./AUTH/verifyURI.js'), require('./ROUTES/render.js'));
so the url here is /admin/scanTable/:table. I know I can get the whole path with req.route.path. I know I can use req.params.table to collect the table parameter. But the thing I don't know how to get is the first part of the path, in this case admin. I know I could get it by looking for / symbols and slicing the parts I need from req.route.path but I figure with all these functionalities that express has, there's probably a better way of doing this.
I know I can use
app.use('/admin', function(req, res, next){console.log('admin called'), next();});
to check if this part of the uri was called to then execute some code, but it's not really what I want. Can anyone tell me the easiest way to find this? At the moment I have attached a variable to req.string whenever app.use('/admin' is called it will attach the string admin to this variable which then makes it available to all other functions that are called. But even this feels like overkill. Any Ideas?

Both options you describe are valid and straightforward:
Using a regex on req.route.path, a la /^admin/.test(req.route.path)
Using middleware to attach a new property to the req object, a la
app.use('/admin', function(req, res, next){ req.adminRoute = true; next();});
or if you need to do this same thing for all admin routes, do it once:
var adminRouter = require("express").Router();
router.get("/scanTable/:table", require("./AUTH/ValidateCookie.js"), ...);
router.use(function (req, res, next) { req.adminRoute = true; next(); }));
app.use("/admin", adminRouter);
I don't know the context of your application, but I would consider using the last example, and putting anything else that's specific to /admin routes as middleware also.

Related

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.

How to dynamically decide if a request should go thru a middleware in Express

All:
I am pretty new to Epxress, I build a middleware to check user credential, and I specify it like:
var check = function(req, res, next){/* checking user cred*/}
And I use it like:
app.use(check);
OR like:
app.get("some url", check, function(req, res, next){})
But there is only one thing confuses me, sometimes, I need to skip the check in same handler depends on req.query, I wonder if there is a way(or design pattern) to do this without specify this condition checking inside check middleware( I just want to make check modulized and focus on its biz logic)?
Thanks
If you're looking to modularize the check middleware so you can use it elsewhere, you could pretty easily include some sort of flag to check against the req.query parameter or whatever else you'd want to check and make it more generic:
function(req, res, next){
if(!req.query){
// do some kind of check
} else {
// do a check with req.query
}
}
Is that along the lines of what you are trying to do?
For authentication, a typical pattern would be to have a collection of routes that allow anonymous access, and a section that requires authentication, thus calls your middleware.
Additionally, look into the Passport library for your authentication concerns, it integrates really well into express.

Express 4.x routing and capturing URL parameters [duplicate]

I'm not sure if this is a bug in Express, or if I'm just doing something wrong (probably the latter), but I'm finding that req.params is only retaining parameters in the final step of the request. To demonstrate what I mean:
Working Example:
router.get('/:id/test', function(req, res){
// req.params.id is not undefined
});
Doesn't Work :(
File 1:
router.use('/:id', require('./file2'));
File 2:
router.get('/test', function(req, res){
// req.params.id is undefined?!
});
Now... the above seems totally illogical to me, seeing as the Express generator defines routes in the above way - and it must still be defined in the path somewhere. Surely I should still be able to access "id"?
So basically, am I missing something? Is this deliberate/is it documented? FWIW I'm using Express v4.12.0.
Disclaimer: the file thing is probably irrelevant, but better to be safe than sorry.
When you create your Router in File 2, you need to tell it to inherit params from parents.
var router = express.Router({mergeParams: true});
http://expressjs.com/api.html#router

Express Router undefined params with router.use when split across files

I'm not sure if this is a bug in Express, or if I'm just doing something wrong (probably the latter), but I'm finding that req.params is only retaining parameters in the final step of the request. To demonstrate what I mean:
Working Example:
router.get('/:id/test', function(req, res){
// req.params.id is not undefined
});
Doesn't Work :(
File 1:
router.use('/:id', require('./file2'));
File 2:
router.get('/test', function(req, res){
// req.params.id is undefined?!
});
Now... the above seems totally illogical to me, seeing as the Express generator defines routes in the above way - and it must still be defined in the path somewhere. Surely I should still be able to access "id"?
So basically, am I missing something? Is this deliberate/is it documented? FWIW I'm using Express v4.12.0.
Disclaimer: the file thing is probably irrelevant, but better to be safe than sorry.
When you create your Router in File 2, you need to tell it to inherit params from parents.
var router = express.Router({mergeParams: true});
http://expressjs.com/api.html#router

Express Framework app.post and app.get

I am fairly new to the express framework. I couldn't find the documentation for application.post() method in the express API reference. Can someone provide a few examples of all the possible parameters I can put in the function? I've read a couple sites with the following example, what does the first parameter mean?
I know the second parameter is the callback function, but what exactly do we put in the first parameter?
app.post('/', function(req, res){
Also, let's say we want the users to post(send data to our server) ID numbers with a certain format([{id:134123, url:www.qwer.com},{id:131211,url:www.asdf.com}]). We then want to extract the ID's and retrieves the data with those ID's from somewhere in our server. How would we write the app.post method that allows us to manipulate the input of an array of objects, so that we only use those object's ID(key) to retrieve the necessary info regardless of other keys in the objects. Given the description of the task, do we have to use app.get() method? If so, how would we write the app.get() function?
Thanks a lot for your inputs.
1. app.get('/', function(req, res){
This is telling express to listen for requests to / and run the function when it sees one.
The first argument is a pattern to match. Sometimes a literal URL fragment like '/' or '/privacy', you can also do substitutions as shown below. You can also match regexes if necessary as described here.
All the internal parts of Express follow the function(req, res, next) pattern. An incoming request starts at the top of the middleware chain (e.g. bodyParser) and gets passed along until something sends a response, or express gets to the end of the chain and 404's.
You usually put your app.router at the bottom of the chain. Once Express gets there it starts matching the request against all the app.get('path'..., app.post('path'... etc, in the order which they were set up.
Variable substitution:
// this would match:
// /questions/18087696/express-framework-app-post-and-app-get
app.get('/questions/:id/:slug', function(req, res, next){
db.fetch(req.params.id, function(err, question){
console.log('Fetched question: '+req.params.slug');
res.locals.question = question;
res.render('question-view');
});
});
next():
If you defined your handling functions as function(req, res, next){} you can call next() to yield, passing the request back into the middleware chain. You might do this for e.g. a catchall route:
app.all('*', function(req, res, next){
if(req.secure !== true) {
res.redirect('https://'+req.host+req.originalUrl);
} else {
next();
};
});
Again, order matters, you'll have to put this above the other routing functions if you want it to run before those.
I haven't POSTed json before but #PeterLyon's solution looks fine to me for that.
TJ annoyingly documents this as app.VERB(path, [callback...], callback in the express docs, so search the express docs for that. I'm not going to copy/paste them here. It's his unfriendly way of saying that app.get, app.post, app.put, etc all have the same function signature, and there are one of these methods for each supported method from HTTP.
To get your posted JSON data, use the bodyParser middleware:
app.post('/yourPath', express.bodyParser(), function (req, res) {
//req.body is your array of objects now:
// [{id:134123, url:'www.qwer.com'},{id:131211,url:'www.asdf.com'}]
});

Resources