I am looking for some documentation on the app.get function of express.js.
app.get(
'/path',
middleware(),
function(req, res) {
res.redirect('/');
}
);
The example above takes three parameters. The normal docs only show two. I'm interested in what this middle param does and how to use it.
The docs for that are part of the app.METHOD documentation, where get is one of the supported HTTP methods.
The second, optional parameter, is called middleware (and you can pass an array of middleware functions). This is a function that's called before the third parameter callback (the actual route handler) and the responsibility of a middleware function is to allow your code to follow the DRY (don't repeat yourself) principle.
Example of middleware functions are permissions checks, access validations, validation of sessions (if user is not in logged in, take him to a log in page), and such.
Since several routes might desire the same behavior, you use a middleware so that you don't have to write the same code several times.
Related
I need to pass variable to a Twig layout about user country and language.
These datas are determined from the route, so I can't get them before routing is done.
I could set them from the route callbacks but code would be repeated in each route.
So I added a middleware to routes. It reads request arguments and sets variables (through $twig->getEnvironment()->addGlobal(...)).
I am not fully convinced, is there a better way to achieve this?
thanks
Routes in Express:
/search/:company-name
/search/:category-name
I can see that first one is fired for both requests so they are same, but is there a way to solve this without involving for example:
/search/company/:company-name
/search/category/:category-name
Yes, they are the same.
The router just see a route that starts with search/ and ends with a wildcard. The only thing that change is the name you give to that wildcard, which doesn't matter for the router, it's still the same URL.
You can solve this by either changing the route, or you can parse the route argument (the wildcard) and do something different depending on its value.
You could use a query instead of a param.
Your urls would be:
/search?company=company-name
/search?category=category-name
Your route is /search and you use req.query instead of req.params.
It's either that,
or your solution of changing the route,
or somehow parsing the parameter to decide whether it's a company or a category
or changing your route to a post and using key-value pairs in the post body
I'm building an app in Express. In one of the views a logged in Superadmin is able to view all available clients/user. In this view I am loading a bunch of client data from my MongoDB/Mongoose with a simple:
app.get('/superadmin', function(req, res) {
Client.find({}, '_id company monthly_cost sms_cost', function (err, docs) ...
As you can see above i have choosen only the values that I need from the query. These four are: "_id", "company", "monthly_cost" and "sms_cost"
From the "_id" i can get a "creation date" by using .getTimestamp(), but the Dateobject this function return is bit to complex formated. I need a simpler date, something like: (YYYY-MM-DD). Im thinking of using a small node plugin like dateformat or possibly writing a very simple function that extract the YYYY, MM and DD from the IsoDate object and saving this in a new variable/array
Now to my questions:
Q1) WHERE is actually the right place for this code? I'm currently putting it inside the route handler above... consequently it will follow right below the code above. I'm thinking this is principally the right way according to a MVC pattern. I'm thinking I dont want to put this code in the Jade view template?
Q2) IN WHAT FORM should i save this data and HOW should i pass it along to Jade. Should I somehow add it to the "docs"-data... that is, the data I extract from my DB. Or should I rather put this creationDate in a separate array which i pass to jade side by side with the original DB-data.
I hope my questions are clear enough!
Q1:
If your Mongoose-query is solely dependent on your route /superadmin, this is exactly the right place to put your code. If you are using the same snippet in different routes or functions you might as well wrap it in a function that is accessible to every route in question. But donĀ“t forget to also wrap req, res and other required variables. Have your calculations within your callback and use Jade only for representation of data.
Q2:
What do you mean by "save"? When you are already iterating over every document to do your calculations and transformations, create an extra field creationDate for every document and pass docs as a single parameter to the Jade file afterwards.
Given a nodejs, mongoose, mongodb, expressjs setup, we have permission/security related routes that validate a particular request. For example:
permissionUtils.checkStudentWritePermissions = function(req, res, next){
//load this student from the mongoose db
//ensure the current user has permission to update this student
}
server.put("/api/student/:studentId/enroll",
permissionUtils.checkStudentWritePermissions, function(req, res, next){
//load student from the database, validate the changes
//update student in mongodb, send new version back to user
});
The middleware is useful because we're ensuring the current user has the rights to update the student in every case. (Code re-use etc.) You'll note that in both examples I'm loading the student from the mongodb. Is there an accepted pattern to avoid this double-loading? Some kind of request-cycle cache or a slick way of passing the model around?
There are many different solutions here. I'll try to quickly give you a few.
1) First of all, separate your code to actually fetch (and any pre-processing you need) into a function in a user model. Second, if you don't have a user model, an MVC approach will make your code much easier to follow when it grows. From here, you could easily cache the response on the first call, and just serve it back on the second without re-fetching from the database. Look at something like Memcached or Redis.
2) While it may not be convention, you could pass the object from the middleware into your main function. If you do choose to do this, document what you did clearly so that people in future understand why your middleware is calling next(req, res, obj), and don't 'fix' it by replacing it with just next().
3) A third approach would be to save the object into the res.locals (I believe that's what its called now). These are values that Express keeps for the current request. Saving it there would be similar to a cache, however would only be accessible during that request. On subsequent requests, the object would have to be refetched.
Note that whatever of these options you choose, implementing some sort of cache for commonly accessed objects will, in almost all circumstances, speed up your application.
middleware depend on each other, for example methodOverride() checks
req.body.method for the HTTP method override, however bodyParser()
parses the request body and populates req.body. Another example of
this is cookie parsing and session support, we must first use()
cookieParser() followed by session()_.
I wonder how can we know which middleware should be use before another? I wonder if there already exist an ordered list (a list with all middlewares in correct working order) somewhere?
The list of middleware on connect's home page is in the correct order, though it doesn't explicitly call out dependencies.