How to skip part of the middlewares that are on the stack in Express js - node.js

I am working on a backend of web application. And I have made a bunch of middlewares to be executed for each request that comes in -- [logging(before), authentication, Etag(Before), Nonce, httpRequest, Etag(after), logging(after)]. Now my problem is that, while processing each request, there are some special cases happen when the request should skip the rest of the middleware and just do logging. I can do it the dump way just make all the middleware to check if certain condition has happened and if true just call next(), and otherwise process the request using the middleware. But I am wondering if there is a clever way to do this?
Here is the snippet of the code I am currently using to configure the order of the middleware to be executed:
async.series(operations, function(err) {
if(err) {
console.log('Something blew up!!!!!!');
return next(err);
}
console.log('middleware get executed');
// no errors so pass control back to express
next();
});
Where the "operations" variable is the list of middlewares I need to execute in order. I need to use the async.series() since I need to make the order the middleware configurable. Is there a clever I can keep the order of middlewares configurable and fulfill my request as I said above?
EDIT:
An example where I need to skip the rest of the middleware is when authentication fails and write the statusCode to be "401 unauthorized", then for the stack of the middleware [logging(before), authentication, Etag(Before), Nonce, httpRequest, Etag(after), logging(after)], I will jump from authentication to logging(after). and then that would be the end of the request.

I had tried to understand your's concern
I am giving a snippet to execute middle ware function in row on the basis of need.
async.each(operations, function(operation, callback) {
if(operation) {
// if operation is required execute here
callback();
} else {
// otherwise skip just to call callback() here
callback();
}
}, function(err){
if( err ) {
console.log(err);
} else {
next();
}
});
all the operations in an array and to execute all one by one async provides .each.
Its not mandatory to call each operation. You just skip by call callback() in else condition. I want to say that in if clause you can put your mandatory execution condition.
Thanks

Related

How can I execute queries one after the other and extract value from 1st query and use it in the 2nd using expressJS?

router.post("/application_action", function(req,res){
var Employee = req.body.Employee;
var conn = new jsforce.Connection({
oauth2 : salesforce_credential.oauth2
});
var username = salesforce_credential.username;
var password = salesforce_credential.password;
conn.login(username, password, function(err, userInfo, next) {
if (err) { return console.error(err); res.json(false);}
// I want this conn.query to execute first and then conn.sobject
conn.query("SELECT id FROM SFDC_Employee__c WHERE Auth0_Id__c = '" + req.user.id + "'" , function(err, result) {
if (err) { return console.error(err); }
Employee["Id"] = result.records[0].Id;
});
//I want this to execute after the execution of above query i.e. conn.query
conn.sobject("SFDC_Emp__c").update(Employee, function(err, ret) {
if (err || !ret.success) { return console.error(err, ret);}
console.log('Updated Successfully : ' + ret.id);
});
});
I have provided my code above. I need to modify Employee in the conn.query and use it in conn.sobject. I need to make sure that my first query executes before 2nd because I am getting value from 1st and using in the 2nd. Please do let me know if you know how to accomplish this.
New Answer Based on Edit to Question
To execute one query based on the results of the other, you put the second query inside the completion callback of the first like this:
router.post("/application_action", function (req, res) {
var Employee = req.body.Employee;
var conn = new jsforce.Connection({
oauth2: salesforce_credential.oauth2
});
var username = salesforce_credential.username;
var password = salesforce_credential.password;
conn.login(username, password, function (err, userInfo, next) {
if (err) {
return console.error(err);
res.json(false);
}
// I want this conn.query to execute first and then conn.sobject
conn.query("SELECT id FROM SFDC_Employee__c WHERE Auth0_Id__c = '" + req.user.id + "'", function (err, result) {
if (err) {
return console.error(err);
}
Employee["Id"] = result.records[0].Id;
//I want this to execute after the execution of above query i.e. conn.query
conn.sobject("SFDC_Emp__c").update(Employee, function (err, ret) {
if (err || !ret.success) {
return console.error(err, ret);
}
console.log('Updated Successfully : ' + ret.id);
});
});
});
});
The only place that the first query results are valid is inside that callback because otherwise, you have no way of knowing when those asynchronous results are actually available and valid.
Please note that your error handling is unfinished since you don't finish the response in any of the error conditions and even in the success case, you have not yet actually sent a response to finish the request.
Original Answer
First off, your code shows a route handler, not middleware. So, if you really intend to ask about middleware, you will have to show your actual middleware. Middleware that does not end the request needs to declare next as an argument and then call it when it is done with it's processing. That's how processing continues after the middleware.
Secondly, your console.log() statements are all going to show undefined because they execute BEFORE the conn.query() callback that contains the code that sets those variables.
conn.query() is an asynchronous operation. It calls its callback sometime IN THE FUTURE. Meanwhile, your console.log() statements execute immediately.
You can see the results of the console.log() by putting the statements inside the conn.query() callback, but that is probably only part of your problem. If you explain what you're really trying to accomplish, then we could probably help with a complete solution. Right now, you're just asking questions about flawed code, but not explaining the higher level problem you're trying to solve so you're making it hard for us to give you the best answer to your actual problem.
FYI:
app.locals - properties scoped to your app, available to all request handlers.
res.locals - properties scoped to a specific request, available only to middleware or request handlers involved in processing this specific request/response.
req.locals - I can't find any documentation on this in Express or HTTP module. There is discussion of this as basically serving the same purpose as res.locals, though it is not documented.
Other relevants answers:
req.locals vs. res.locals vs. res.data vs. req.data vs. app.locals in Express middleware
Express.js: app.locals vs req.locals vs req.session
You miss the basics of the asynchronous flow in javascript. All the callbacks are set to the end of event loop, so the callback of the conn.query will be executed after console.logs from the outside. Here is a good article where the the basic concepts of asynchronous programming in JavaScript are explained.

how to redirect from a view in keystone.js

What is the right way to redirect from within a keystone.js view?
I have this use case:
//req, res are the express request and response objects defined earlier
view.on('init', function(next){
if (req.params['should-be-else-where']='true'{
// do some logging stuff
// redirect to somewhere else
}
});
as I understand the next param in the view.on() function is a callback for the async.js framework, and does not relate to the (req,res,next) middleware.
Should I call res.redirect('/somewhere-else) and then call next(), then call next() with a non-null error parameter, or should redirection be performed somewhere completely different?
Additional info: I'd like to stop processing because there is no reason to do the performance heavy database processing that following later in the queue
If you don't need a View but only redirect if the condition was met, you could do it like this:
module.exports = function (req, res, next) {
if (req.params['should-be-else-where']) {
// do some logging stuff
res.redirect('/somewhere-else');
} else {
var view = new keystone.View(req, res);
// do something else then render the view
}
}

always run a middleware in expressjs

i want an expressjs middlware to be executed always.
That is even if there is an error in the next() or not.
is it possible?
example
app.get('/',[middle1,middle2],doIt)
the middle2 should always execute even if the middle1 executes next with error.
NOTE: the middle2 should always execute last and takes the values calculated by the previous middlewares. also there are lot of middlewares between middle1 and middle2.
If middle1 is known to not use any async operations from which it calls next(), then you can wrap it and put a try/catch around it so that if it throws, you can just call next() on its behalf.
If it does use async operations or you don't know if it will use async operations, then you will only catch its exceptions if it throws synchronously (before it goes async) and you will not be able to catch any exceptions that it throws asynchronously. About the best you could do for async behavior is to set some sort of timeout in your wrapper. If it hasn't called next() within some period of time (either because it threw an exception or just failed in some other weay), then you call next after the timeout period.
Wrapping a non-async middle1 could look like this:
function wrap(fn) {
return function(req, res, next) {
var nextCalled = false;
try {
fn(req, res, function() {
nextCalled = true;
next();
});
} finally {
if (!nextCalled) {
next();
}
}
}
}
app.get('/',[wrap(middle1),middle2],doIt);
The wrap() function inserts a stub as the middleware function. That stud inserts its own next() function so it can tell if the actual middleware function calls next() or not. It then wraps an exception handler around the middleware function so if it throws an exception synchronously, then it can recover. After the function returns, it checks to see if next() was called and, if not, it calls it.
As explained earlier this approach only works if the middleware function is synchronous.
Assuming you do not care about the order of execution, you can simply have function middle2 execute inside app.use.
app.use(middle2);
app.get('/pathx, middle1, middle3, doIt);
middle2 will always be executed on every request. However, middle2 will execute before any of the other middleware
If you require middle2 to execute last in sequence, then a simple modification using the async module should accomplish what you want
async = require('async');
function middleware(req, res, next){
var functionList = [middle1, middle3];
async.series(functionList, function(err, results){
if(err){
middle2(req, res, next);
next(err);
}
middle2(req, res, next);
next();
}
}
app.get('/pathX', middleware, doIt);

How does Express/Connect middleware work?

I am learning Node.js, and I have read some tutorials, like The Node Beginner Book for learning the core funcionality. But the more I read some examples, the more doubts I start collecting.
On the further example, obtained from a tutorial, we can see that for a CRUD 'read' request for key /documents/titles.json, we are returning a value:
app.get('/documents/titles.json', loadUser, function(req, res) {
Document.find({ user_id: req.currentUser.id },[], { sort: ['title', 'descending'] },
function(err, documents) {
res.send(documents.map(function(d) {
return { title: d.title, id: d._id };
}));
});
});
On this example, the function loaduser() is used for authentication purposes:
function loadUser(req, res, next) {
if (req.session.user_id) {
User.findById(req.session.user_id, function(err, user) {
if (user) {
req.currentUser = user;
next();
} else {
res.redirect('/sessions/new');
}
});
}
}
What I don't understand is:
I suppose that node.js, before start executing the app.get, it goes to loaduser function. loadUser() function has three parameters: req,res,next, but I don't see, at least, how you pass from app.get() the "req" parameter to loadUser(). From where does it come?
Inside loadUser() function, when you execute next(), it means that the function app.get()" can continue its procedure, but this req.currentUser = user, is the same req that is used on app.get() function?
Inside loadUser() function, when you execute res.redirect() code, automatically breaks the procedure on app.get() function, right? it looks like it doesn't return to Document.find().
The questions you've asked are about the Express framework internals specifically:
When you call app.get(route, loadUser, final) Express will make a stack (array) with the loadUser and final function functions and it will know that when you call next it should execute the following function in the stack with the same req and res params.
When you call next it will just pass to the next function in the middleware stack.
Since you call res.redirect and you don't call return, it won't pass to the next function in the stack (the one with Document.find).
Resources:
http://howtonode.org/getting-started-with-express
I think in order to be comfortable with this you need get familiar with idea of middleware and how it's used in connect framework.
I've found few articles where this subject explained well enough. Take a look there:
http://howtonode.org/connect-it
and here http://stephensugden.com/middleware_guide/
the main idea is you have a set of layers and each time when new request arrives it goes through each level and on each level you can decide what to do with that. You can stop at some level, do something and return response or you can pass it to the next layer

Having trouble understanding how the pre() function in Mongoose is working in this code snippet

I am learning how to make web apps with node.js. I have been following the tutorial provided by Alex Young. I am having trouble understanding how the pre() function works in Mongoose. I have read the Mongoose API documentation and understand that it is a way of "chaining" functions to an existing one, but I do not understand how it is actually working when I look at a code example (see below code snippets).
My question is what is going on in the here? There are three functions involved here (userSaved(), userSaveFailed(), and the password validation function defined in the pre() function). How are these function related to each other in terms of order in which they run? Is the actual saving of the document into the database completed before userSaved() and userSavedFail() are run?
I admit that my lack of understanding understanding may be due to my lack of knowledge on javascript (I come from a PHP background), but I just can't follow what is going on in this code.
Modified save behavior define in models.js :
User.pre('save', function(next) {
if (!validatePresenceOf(this.password)) {
// Through error if password fails validation.
next(new Error('Invalid password'));
}
else {
next();
}
});
Call to save data to database from app.js :
app.post('/users.:format?', function(req, res) {
var user = new User(req.body.user);
function userSaved() {
switch (req.params.format) {
case 'json':
res.send(user.__doc);
break;
default:
req.session.user_id = user.id;
res.redirect('/documents');
}
}
function userSaveFailed() {
res.render('users/new.jade', {
locals: { user: user }
});
}
user.save(userSaved, userSaveFailed);
});
In my opinion,the function followed by "save", is the method which gets executed before the save function is called(as the function name "PRE" imply).
The first function that is ran is user.save() passing in two callbacks, one for if user.save() completes without errors (userSaved) and another if it fails (userSavedFailed)
User.pre('save', function(next) {
if (!validatePresenceOf(this.password)) {
// Through error if password fails validation.
next(new Error('Invalid password'));
}
else {
next();
}
});
This code is running a set of asynchronous functions in parallel, only returning a response once all the functions have completed. In this case it returns by calling a callback function (userSaved or UserSavedFailed). Which is called depends on whether there was an error during the process of any of the functions.
The Async Module also chains functions and allows them to run synchronously or in parallel and may provide some examples of how this is accomplished to help you better understand what's actually happening.

Resources