Express handler function parameter execution - javascript

The express route is setup with the following
var users = require('../../app/controllers/users.server.controller');
// Set up the 'signout' route
app.get('/signout', users.signout);
However, since the parenthesis aren't present, this means that the function users.signout is being passed and not executed?
The file on github can be found here
The users.signout function looks like the following
// Create a new controller method for signing out
exports.signout = function(req, res) {
// Use the Passport 'logout' method to logout
req.logout();
// Redirect the user back to the main application page
res.redirect('/');
};
The file on github can be found here
Why is users.signout executed? And how does it get passed the req and res parameters?

When you use
app.get('/signout', users.signout);
Express.js basically stores the given function, users.signout, internally and keeps the association with the /signout path.
When a request is made on this route, Express.js will get the corresponding stored function and call it, roughly in the following form:
// `storedFunction` corresponds to your `users.signout` function
storedFunction(expressReq, expressRes, expressNextCallback);
If you were to call you users.signout function in the call, i.e.
app.get('/signout', users.signout());
you wouldn't be able to get the req and res parameter and the users.signout function would actually execute right away, meaning the app.get function would actually receive the result of your function.
You can read more about this in the documentation. Hope it helps!

The express app.get function takes a string as the first argument and a function as the second. When the app listens to the routes and finds the route '/signout' it executes at that instant the function you gave in the second argument passing to it the req and res objects.
The function is not executed at the moment of the declaration app.get('/signout', users.signout);.
The same code could have been written as (assuming that you are using Passport to be able to use the logout method):
app.get('/signout', function(req, res) {
// Use the Passport 'logout' method to logout
req.logout();
// Redirect the user back to the main application page
res.redirect('/');
});
and it is actually a function which is passed to the second argument of app.get, but with explicit declaration of its logic in the same place.

Related

ExpressJS + JWT. What's the proper way to get auth data?

Let's jump to an example. I'll skip some parts like imports, exports.
I have a controller called controllers/book.js with one route:
router.get('/my-books', function(req, res) {
if(Auth.authenticated(req,res)) {
Book.getMyBooks(function(rows) {
response.operationSucceed(req, res, rows);
});
}
});
Then, in a model called models/book.js I have that function:
function getMyBooks(successCallback) {
db.query('SELECT * FROM book b WHERE b.id_user=?', [Auth.getLoggedUID()], function(rows) {
successCallback(rows);
});
}
My question is about Auth.getLoggedUID function.
Assuming that I have a JWT authentication and assuming that I have an UID in payload (is that even acceptable?), what's the best option to retrieve it? Is there any, EXCEPT passing the req every time to every function where I need auth data?
I may have a function execution inside a function, do I need to pass the req through both of them to get the user ID? Like this?:
function getBooks(req) {
getMyBooks(req);
getCriminalBooks(req);
getEvenOtherBooksByAuthor(req, authorId);
}
Honestly I wouldn't like that.
Maybe my whole concept is wrong and I should be doing things differently?
Can someone point me the right direction in scenarios like this?
You can pass UID in header and retrieve it inside your controller as:
var uid =req.header('UID');
Then pass this UID where ever you want there is no need to carryforward whole req object everywhere.
You can use a middleware function. Let's say that every request that hits your endpoints, will have a token which you should check and possibly decode it. After that, you can set the decoded content to the req object. So something like this:
app.use(function(req, res, next) {
// get the token from the request headers most likely.
// verify and decode the token
// set the decoded content to the request
var payload = ..
req.payload = payload;
});
After this you can access the payload in every single endpoint you have. So for example in some controller you can do:
app.get('/hey', function(req, res) {
var payload = req.payload;
});

How to create a global function which will access DB in express.js

I use express.js, mongodb, ejs. In the navbar, there's an email icon and will display the count of new emails.
<%=newEmailCount%>
Then I need to add this newEmailCount to every route.
Emails.count({userId: userId, new: true})
my question is in express.js, how can I add a global function that can be executed by every route?
If you want to get the count for every GET requests then you can use following approach
router.get('*', function(req, res, next) {
res.locals.newEmailCount = Emails.count({userId: userId, new: true})
next();
})
You need to make sure this is always executed by placing it above all the other routes.
You can then pass res.locals.newEmailCount to your render function which renders HTML file for matched route.
This will work also for application instance level routes handling if that's what you're using.

AngularJS: Issue with http chain calling and NodeJS: issue with using variable in multiple http call

I have a get call and a post call in my node.js file, both of which use the same variable that I initialized to an empty string outside these calls. In the post call, I set the variable, while in the get call, I return the value of the variable to my clientside angularjs that is requesting the value. In my angularjs file, I make the post call first and then the get call, which means the value should be set and should be available when the get call is issued and returns. Here's what I'm doing:
NodeJS
var myUrl= "";
app.post('/post', function(req, res){
myUrl = res.url;
});
app.get('/get, function(req, res){
res.json({result: myUrl});
});
AngularJS:
var promise = $http.post('/post')
.then(function(response){
return $http.get('/get');
}).then(function(response){
console.log(response.data.result);
});
I've tried AngularJS promise chain calling but it still doesn't work. The problem I'm having is that when I make the get call in the first round of requests, the url variable hasn't been set yet even though the post call has been already issued, so the get call returns an empty string. In the second round of requests, the get call returns the value that has been set from the first post call, and so on and so forth.
Any ideas on why this is happening and suggestions on how to solve this issue so that the get call returns the value that is set in the post call in the same round of requests (the get call is issued when the post call is done)? I'm fairly new to NodeJS so any help is appreciated!
Your angular code is fine, though you have missed a small thing. I modified your code and tested, it works as expected.
Solution:
var myUrl= "";
app.post('/post', function(req, res){
//not res.url
myUrl = req.url;
//Your missed this!
res.status(204).end();
});
app.get('/get, function(req, res){
res.json({result: myUrl});
});
Explanation:
Without res.status(204).end(); or res.send({}) or res.json({}) the /post call just updates the url and then hangs there and does nothing, never returns and will eventually timeout. So when next time you call /get you get the URL.
You must consider the fact that all your route handlers are just middleware and you must generate a response or execute next middleware.
In your case, you wanna handle the request and want to end there, it was required to send some response. so we sent res.status(204).end();, meaning: There is no content to serve
Hope this helps!

Dynamic routing in Node.js

I want to create dynamic stubs as webservices. My idea is to load at every request a definition file and return data for corresponding URL.
The definition file could look like this:
/api/users {users:["john", "jack", "jake"]}
/api/users/1 {user:"john"}
/api/some-data/1 {data:"some data"}
In an application I created on behalf of a tutorial I find:
router.post('/some-irl', function (req, res) {
//some code
return {some JSON}
});
But this definition looks static to me, which should be there before I start Node.js Is it possible to define /some-irl at the time then request occures?
EDIT
Actually, I was intending to do somehting like this: https://github.com/typicode/json-server but it is already there!
You can attach a use middleware, which can check the path and decide whether to handle it or pass it on:
router.use(function(req, res, next) {
// req.path
// decide what to do
// respond or next()
});
you can define variables in the routes, use : before the variable name to define it, and then you'll get the value in req.params:
route.get('/api/users/:user/', function (req, res) {
var username = req.params.user;
});

cannot understand what callback does in a Connect module

I am reading a book about NodeJs Connect. There is this small part about basicAuth module. I know that basicAuth is now deprecated, but I cannot understand this simple code. The book says
Providing an asynchronous callback function
The final option is similar, except this time a callback is passed to
basicAuth() with three arguments defined, which enables the use of
asynchronous lookups. This is useful when authenticating from a file
on disk, or when querying from a database.
Listing 7.7. A Connect basicAuth middleware component doing
asynchronous lookups
And no other information. Thats the whole part about having a callback in the basicAuth
So, code gets the username and the password. Then hypothetical object User has a method authendicate that checks if this user actually exists. And when its finished, calls the gotUser function. gotUser contains either a returned error (=no user found with that username/password) or a returned user object (a user found with that username/password). Am I right?
gotUser checks if there is an error. If there is, returns and calls callback with an error argument. So wait, what will callback do at this point? Its not defined anywhere. Will it pass the error to an error handler function? And how?
If there is not an error, gotUser calls callback again with null(= no error) and user. Once again, what will callback do? Why pass the returned user to the callback and not grab its name, mail, age etc etc and use them on a session or fill the innerHTML of a tag or whatever?
Thanks
So wait, what will callback do at this point? Its not defined anywhere.
The value of callback is defined by the basicAuth middleware.
You can find its definition within the basic-auth-connect module, used by connect, in the module's index.js:
callback(user, pass, function(err, user){
if (err || !user) return unauthorized(res, realm);
req.user = req.remoteUser = user;
next();
});
When gotUser() invokes callback(...), it's call the function(err, user){...} from the above snippet, passing the err and/or user along to be used.
And, how they're used, in the two scenarios you were wondering about...
gotUser checks if there is an error. If there is, returns and calls callback with an error argument. So wait, what will callback do at this point?
If there is not an error, gotUser calls callback again with null(= no error) and user. Once again, what will callback do?
The if (err || !user) condition will pass for both (one has an error, the other is lacking a user). It then considers the request unauthorized and will end the response immediately.
function unauthorized(res, realm) {
res.statusCode = 401;
res.setHeader('WWW-Authenticate', 'Basic realm="' + realm + '"');
res.end('Unauthorized');
};
Why pass the returned user to the callback and not grab its name, mail, age etc etc and use them on a session or fill the innerHTML of a tag or whatever?
The middleware is applying separation of concerns, keeping itself as small and concise as possible. It's goal is just to determine a req.user and validate it.
When it's done that successfully, other middleware in the application's queue will be able to reference the user that was found. This can includes using it to render markup from a view:
// determine the user
app.use(connect.basicAuth(...));
// now make use of it
app.use(function (req, res, next) {
viewEngine.render('view', { user: req.user }, function (err, result) {
if (err) return next(err);
res.setHeader('Content-Type', 'text/html');
res.end(result);
});
});
Note: This is generalized and won't run as-is. You'll need to find and setup a view engine of your choice and substitute that into the snippet.
Also, side note on...
fill the innerHTML of a tag
Though Node.js is executing JavaScript, it's doing so within its own environment, completely detached from any browsers. It's not possible to interact directly with the DOM currently seen by the user.
There are a couple of different things going on. For one, app.use expect a function that will be called with req, res, and next. When you run connect.basicAuth, it runs this method.
Since this is a middleware method, this method will run every time a route that was defined after this method is hit.
The second thing that is going on is connect.basicAuth is a function that will be called with username, password, and a callback method. Callback is something that connect.basicAuth provides.
If you return callback(err), it will send a 401 Not Authorized back to the client. If you return callback(null, user), it will continue until either the next middleware function, or the appropriate route.

Categories

Resources