node.js - perform global procedure before invoke the mapped methods - node.js

everyone ! I've this sentence in my app.js:
app.get('/aux/:subject/:data', aux.query);
app.post('/register/:Id', register.create);
app.post('/register/:Id/smsConfirm', register.confirmSms);
app.post('/register/:Id/login', register.login);
app.post('/register/:Id/resetPassword', register.resetPassword);
app.get('/register/:Id/getSms', register.getSms);
And I will have much more because it's the beginning. And i'd like to implement a global function to be executed before any class like aux.query, register.create, etc be invoked.
Basically I'd like to check if the IP is on my black list. If true: Don't execute anything - Throw a 403 instead.
Actually the only way I know to implement this is to put in any method a verification using promises and after check, allow the execution, but I believe that there is a better way to do the things in a global way (maybe not ??)
Can someone give me a good hint ? ty !

You should handle your black list check as middleware if it is a valid test for every endpoint.
function blacklist(req, res, next) {
// check blacklist
// call next() if passed
next();
}
app.use(blacklist);
app.get('/aux/:subject/:data', aux.query);
app.post('/register/:Id', register.create);
app.post('/register/:Id/smsConfirm', register.confirmSms);
app.post('/register/:Id/login', register.login);
app.post('/register/:Id/resetPassword', register.resetPassword);
app.get('/register/:Id/getSms', register.getSms);

Related

Express route with multiple middlewares and separated layers

I'm reading the GitHub https://github.com/goldbergyoni/nodebestpractices and trying to apply the tips on my project. Currently i'm working on the "1.2 Layer your components, keep Express within its boundaries" tip, but I have a question.
I'm using routes/controllers, and using this tip (1.2), a route with multiple middlewares will look like this.
router.post("/do-multiple-stuff",
(req, res, next) => {
stuffController.getStuffDone(req.body.stuff);
next();
},
(req, res, next) => {
stuffController.getOtherStuffDone(req.body.otherStuff);
return res.send("stuff done");
});
Is this correct? Or there's a better way to do this?
Thanks! <3
The point of that 1.2 section is to create your business logic as a separate, testable component that is passed data only, not passed req and res. This allows it to be independently and separately tested without the Express environment around it.
Your calls to:
stuffController.getStuffDone(req.body.stuff);
and
stuffController.getOtherStuffDone(req.body.otherStuff);
Are indeed making that proper separation between the web and the business logic because you aren't passing req or res to your controller. That looks like it meets the point of the 1.2 training step.
The one thing I see missing here is that there isn't any output from either of these function calls. They don't return anything and since you don't pass req or res to them, they can't be modifying the req object (like some middleware does) and can't be sending a response or error by themselves. So, it appears that these need a mechanism for communicating some type of result back, either a direct return value (if the functions are synchronous) or returning a promise (if the functions are asynchronous). Then, the calling code could get their result and do something with that result.

Execute code on error

I want to execute a code of automated mail whenever there is any kind of error from any of the API.
Though this is possible to write that code in catch block of a remote method but my code base is too long and hence this is not a best fit.
Another issue with this is approach is for API which are not custom remote method and are generated by loopback, it is hard to use catch block with them.
Can someone help me with an easy approach where I need to write code once and the end result will be whenever there is an error in any of my API my code for mail runs automatically.
Got the answer after struggling for a day.
Loopback provides RemoteHook (afterRemoteError) for a model-method,
_modelName_.afterRemoteError( _methodName_, function( ctx, next) {
//...
next();
});
So whenever a particular method returns any error this block of code is executed.
Read more about remote hooks : https://loopback.io/doc/en/lb2/Remote-hooks.html
To make this block of code run every time any method returns error, we can use wildcards
_modelName_.afterRemoteError(** , function( ctx, next) {
//...
next();
});
Read more about wildcards here : https://loopback.io/doc/en/lb2/Remote-hooks.html#wildcards
You should take a look at Loopback https://github.com/strongloop/strong-error-handler
I also strongly suggest integrating a service like Rollbar.

Access current req object everywhere in Node.js Express

I wonder how to access req object if there's no 'req' parameter in callback.
This is the scenarioļ¼š
In ExpressJs, I have a common function, it uses to handle something with 'req' object, but not pass req into it.
module.exports = {
get: function(){
var req = global.currentRequest;
//do something...
}
}
My current solution is that I write a middleware for all request, I put the 'req' in global variable, then I can access the 'req' everywhere with 'global.currentRequest'.
// in app.js
app.use(function (req, res, next) {
global.currentRequest= req;
next();
});
But I don't know if it's good? Can anyone have suggestions?
Thanks a lot!
The only proper way is to pass the req object through as an argument to all functions that need it.
Stashing it in a global simply will not work because multiple requests can be in process at the same time if any requests use async calls as part of their processing and those multiple requests will stomp on each other making a hard to track down bug. There are no shortcuts here. Pass the current request as an argument to any code that needs it.
You cannot put request-specific data into a global in node.js, ever. Doing so will create an opportunity for two requests that are in-flight at the same time to stomp on each other and for data to get confused between requests. Remember, this is a server that is potentially handling requests for many clients. You cannot use synchronous, one-at-a-time thinking for a server. A node.js server may potentially have many requests all in flight at the same time and thus plain globals cannot be used for request-specific data.
There is no shortcut here. You will just have to pass the req object through to the function that needs it. If that means you have to change the function signature of several intervening functions, then so-be-it. That's what you have to do. That is the only correct way to solve this type of problem.
There are some circumstances where you may be able to use a closure to "capture" the desired req object and then use it in inner functions without passing it to those inner functions, but it does not sound like that is your function structure. We'd have to see a lot more of your real/actual code to be able to know whether that's a possibility or not.
Actually, this is possible with something like global-request-context
This is using zone.js which let you persist variables across async tasks.

node.js middleware and js encapsulation

I'm new to javascript, and jumped right into node.js. I've read a lot of theory, and began well with the practical side (I'm writing an API for a mobile app), but I have one basic problem, which has lead me to middleware. I've successfully implemented a middleware function, but I would like to know if the use I'm giving the idea of middleware is OK, and also resolve the original problem which brought me to middleware. My question is two-fold, it's as follows:
1) From what I could gather, the idea of using middleware is repeating a process before actually processing the request. I've used it for token verification, as follows:
Only one of my urls doesn't receive a token parameter, so
app.js
app.get('/settings', auth.validateToken, auth.settings);
auth.js
function validateToken(req, res, next){ //code };
In validateToken, my code checks the token, then calls next() if everything is OK, or modifies res as json to return a specific error code.
My questions regarding this are: a) Is this a correct use of middleware? b) is there a [correct] way of passing a value onto the next function? Instead of calling next only if everything is OK, is there a [correct] way of calling next either way, and knowing from inside the next function (whichever it is), if the middleware was succesful or not? If there is, would this be a proper use of middleware? This precise point brings me to my original problem, and part two of this question, which is encapsulating functions:
THIS PART WAS FIXED, SEE MY SECOND COMMENT.
2) I discovered middleware trying to simply encapsulate validateToken, and be able to call it from inside the functions that the get handlers point to, for example auth.settings.
I'm used to common, sequential programming, and not in javascript, and haven't for the life of me been able to understand how to do this, taking into account the event-based nature of node.js.
What I want to do right now is write a function which simply verifies the user and password. I have it perfectly written inside a particular handler, but was about to copy-paste it to another one, so I stopped. I want to do things the right way from scratch, and understand node.js. One of the specific problems I've been having, is that the error code I have to return when user and password don't match are different depending on the parent function, so I would need this function to be able to tell the callback function "hey, the password and user don't match", so from the parent function I can respond with the correct message.
I think what I actually want is to write an asynchronous function I can call from inside another one.
I hope I've been clear, I've been trying to solve this on my own, but I can't quite finish wrapping my head around what my actual problem is, I'm guessing it's due to my recent introduction to node.js and JS.
Thanks in advance! Jennifer.
1) There is res.locals object (http://expressjs.com/api.html#res.locals) designed to store data local to the request and to pass them from one middleware to another. After request is processed this object is disposed of. If you want to store data within the session you can use req.session.
2) If I understand your question, you want a function asynchronously passing the response to the caller. You can do it in the same way most node's functions are designed.
You define a function in this way:
function doSomething(parameters, callback) {
// ... do something
// if (errorConddition()) err = errorCode();
if (callback) callback(err, result)
}
And the caller instead of using the return value of the function passes callback to this function:
function caller(req, res, next) {
//...
doSomething(params, function(err, result) {
if (! err && result) {
// do something with the result
next();
} else {
// do something else
next();
// or even res.redirect('/error');
}
});
}
If you find yourself writing similar callback functions you should define them as function and just pass the function as parameter:
//...
doSomething(param, processIt);
function processIt(err, result) {
// ...
}
What keeps you confused, probably, is that you don't treat functions as values yet, which is a very specific to JavaScript (not counting for languages that are little used).
In validateToken, my code checks the token, then calls next() if everything is OK, or modifies res as json to return a specific error code.
a) Is this a correct use of middleware?
b) is there a [correct] way of passing a value onto the next function?
Yes that is the correct way of using middleware, although depending on the response message type and specifications you could use the built in error handling of connect. That is in this example generate a 401 status code by calling next({status:401,stack:'Unauthorized'});
The middleware system is designed to handle the request by going through a series of functions until one function replies to the request. This is why the next function only takes one argument which is error
-> if an error object is passed to the next function then it will be used to create a response and no further middleware will be processed. The manner in which error response is created is as follows
// default to 500
if (res.statusCode < 400) res.statusCode = 500;
debug('default %s', res.statusCode);
// respect err.status
if (err.status) res.statusCode = err.status;
// production gets a basic error message
var msg = 'production' == env
? http.STATUS_CODES[res.statusCode]
: err.stack || err.toString();
-> to pass values down the middleware stack modifying the request object is the best method. This ensures that all processing is bound to that specific request and since the request object goes through every middleware function it is a good way to pass information down the stack.

What is the difference between next() and next('route') in an expressjs app.VERB call?

The docs read:
The app.VERB() methods provide the routing functionality in Express,
where VERB is one of the HTTP verbs, such as app.post(). Multiple
callbacks may be give, all are treated equally, and behave just like
middleware, with the one exception that these callbacks may invoke
next('route') to bypass the remaining route callback(s). This
mechanism can be used to perform pre-conditions on a route then pass
control to subsequent routes when there is no reason to proceed with
the route matched.
What do they mean by "bypass the remaining route callbacks?"? I know that next() will pass control to the next matching route. But... what function will get control with next('route')...?
I hated it when I answer my own question 5 minutes later.
next('route') is when using route middleware. So if you have:
app.get('/forum/:fid', middleware1, middleware2, function(){
// ...
})
the function middleware1() has a chance to call next() to pass control to middleware2, or next('route') to pass control to the next matching route altogether.
The given answer explains the main gist of it. Sadly, it is much less intuitive than you might think, with a lot of special cases when it is used in combination with parameters. Just check out some of the test cases in the app.param test file. Just to raise two examples:
app .param(name, fn) should defer all the param routes implies that if next("route") is called from a param handler, it would skip all following routes that refer to that param handler's own parameter name. In that test case, it skips all routes refering to the id parameter.
app .param(name, fn) should call when values differ when using "next" suggests that the previous rule has yet another exception: don't skip if the value of the parameter changes between routes.
...and there is more...
I'm sure there is a use-case for this kind of next('route') lever, but, I agree with previous comments in that it certainly makes things complicated and non-intuitive.

Resources