In express, when I use routing middleware, is it OK to append to the request object? Or is it a bad pattern? Alternatives? Thanks.
app.get('/', getLayout, function(req, res){
if(req.layout == 'simple') ...render simple layout...
else ...render full layout...
});
where
getLayout = function(req, res, next){
req.layout = (req.params.blah == 'blah') ? 'layout_simple' : 'layout_full';
next();
}
I don't see why you shouldn't.
I do it a lot.
I am under the impression this is what middleware typically does.
From the express docs:
http://expressjs.com/guide.html#route-middleware
They set req.user in their middleware as the current user.
I agree with j_mcnally that this is a fine pattern as long as you don't go overboard. Specifically, I append most things that are more closely related to the response to the res object. This would be things like layout info, HTML fragments, my intermediate jsdom env representation of the response, etc. For req, tacking on things that are representations of query string or request body info makes sense. This would be things like input parameters, parsed search queries, the current user object, etc.
The express docs suggest it's somewhat a standard practice:
http://expressjs.com/guide.html#route-middleware
But it can significantly effect performance because of the way V8 works:
http://blog.tojicode.com/2012/03/javascript-memory-optimization-and.html
http://www.scirra.com/blog/76/how-to-write-low-garbage-real-time-javascript
Related
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.
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.
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'}]
});
Hellow I have code in my app.js, looking like that:
app.use('/someurl', require('./middleware/somemodule'));
-app.use instead app.all
and module looks like:
if(process.env.BLALAL === undefined){
throw "Error: process.env.BLALAL === undefined";
}
module.exports = function(req, res, next){
...
}
is it a bad practice ?
As said on the express api reference:
app.VERB(path, [callback...], callback)
The app.VERB() methods provide the routing functionality in Express,
where VERB is one of the HTTP verbs, such as app.post().
app.use([path], function)
Use the given middleware function, with optional mount path,
defaulting to "/".
The "mount" path is stripped and is not visible to the middleware
function. The main effect of this feature is that mounted middleware
may operate without code changes regardless of its "prefix" pathname.
IMO
The functionality may be nearly the same, but there is an underlying semantic meaning. The routes itself should be set through the app.VERB api, while any middleware should be set through the app.use api.
Normally middlewares modify the request or response objects, or inject functionality from other module that may answer the request, or not.
connect.static is a good example. It could be really an app or an HttpServer by itself, but is injected as middleware on other app object.
I personally don't like require inside other commands then var bla = require('bla');, it makes code much worse readable in my opinion and you did not get anything in return.
I am not sure what was your intention, but if your code depends on environment variable, it is better to throw immediately than later when your route is called. So app.use is better then app.all. But I don't understand why aren't you simply test your condition inside app.js and why you hide it in somemodule.
I am using Express to serve web pages in node.js application.
Let's say I want to have a variable foo available in all views rendered by render method of response object. I know that I can define dynamic helpers for this task. However, I found them unsuitable when you need to set helper variable asynchronously like this (Mongoose example):
Thing.count(filter, function(error, thingCount) {
foo = thingCount;
}
I've tried using connect middleware approach, which suits me perfectly, however the question here is how to affect the response context. By looking into render method definition in express/lib/view.js I've found that it can be manipulated by writing into app._locals object:
function putFooIntoContext (req, res, next) {
Thing.count(filter, function(error, thingCount) {
res.app._locals.foo = thingCount;
next();
}
}
It works as intended, however, I am a bit afraid that such straightforward approach is not the best solution. Can someone give me any ideas how to affect response context by interacting only with request/response objects in proper way designed by Express developers?
Express 3.x allows for asynchronous helpers to be utilized in the form of 'app.use'. So for a simple global 'foo' variable, your code would be as follows:
app.use(req, res, next) {
Thing.count(filter, function(error, thingCount) {
res.locals.foo = thingCount;
next();
});
}
Of course the middleware option is also valid, this is just another viewpoint and saves inserting the middleware per each app.get(....)