Express: How does this function work? - javascript

router.post('/register', function(req, res) {
User.register(new User({ username : req.body.email }), req.body.password, function(err, account) {
if (err) {
return res.render('register', { account : account });
}
passport.authenticate('local')(req, res, function () {
res.redirect('/');
});
});
});
I get the general idea of this routing post, but I don't understand all of it.
What information generally comes in through req? It seems like if I do req.body.email and if in the body of my register html page I've submitted a form with an email and password field, I can simply access them this way?
And in the function(err, account) callback, where exactly is it getting the err and account variables? I've never really understood for the callback functions how the variables were decided or what even they are, it seems like when you route it somehow takes two variables err and account?
Thanks so much!

1st-
Well you should read the ExpressJS documentation and see the difference between body, query and params but basically goes like this
body refers to the body of the request, which is the submitted data through POST or PUT
query refers to the search part of the url or query string everything after the "?"
params refers to the part of the path that is parameterized.
hope that gives you a clue of how and where to look for the information
2nd- is nodes convention that always the first variables passed to a callback is the error variablem the rest is according to the function in this case is account because the function is suppose to create db account and return the entire account information so ir can bu used by the callback

What information generally comes in through req?
The request object (req) comes with data on the request you are processing. For instance:
Fields used in the form that triggered the request (under req.body)
Parameters used in the request URL (under req.params)
Session/cookie information (under req.session)
See here for more.
And in the function(err, account) callback, where exactly is it getting the err and account variables?
By convention in Node, callbacks pass any errors as the first parameter, and any non-error results from the second parameter onwards. So you'll typically see the first parameter called err. The structure of the err object is not completely standard, but it is normal to assume there will be a message field in the err object, and perhaps some error code.
In your example, you are handing that callback to, it seems, Mongoose, or some other database handling library. This library will try to execute a register function on the User object/model/schema. When it's done, if it encountered any errors, they'll come back to you on the err object. Else, you can expect the account object to hold details on the user account.
Also: you could name err and account whatever you want, of course.

Related

Auth0.js - Why make second call to /userinfo in parseHash?

In the Auth0 docs (link here), the following example is given for retrieving user info after parsing the access token, id token and expiry from the URI:
webAuth.parseHash({ hash: window.location.hash }, function(err, authResult) {
if (err) {
return console.log(err);
}
webAuth.client.userInfo(authResult.accessToken, function(err, user) {
// Now you have the user's information
});
});
I don't understand what the use of the call to webAuth.client.userInfo() is. When viewing the contents of authResult as passed to the callback for parseHash() there appears to be a property called idTokenPayload that already includes all the user information.
In fact, when looking at the network log it appears that parseHash() is making its own call to /userinfo to retrieve the full user information and include it in the authResult object passed to the callback.
Why then do the docs suggest that you repeat the call to /userinfo and get the user information again? Isn't this redundant?

Error when calling the next() method in passport.authenticate('local')

I have some middleware which uses passport.js, which aims to authenticate a user, then move onto the next piece of middleware:
exports.authenticate = (req, res, next) => {
passport.authenticate('local', (err, user, info) => {
console.log('You are authenticated!!')
next()
})(req, res, next)
}
When the user registers, I see You are authenticated!! in my console. So by this logic, the user should be attached to the req. So I call next and it moves onto this piece of middleware (I want to do something else before the user is redirected):
exports.createMatch = async (req, res) => {
console.log(req.user._id)
}
However, an error on my console and webpage shows TypeError: Cannot read property '_id' of undefined. Why is this and how do I rectify it?
routes.js:
router.post(
'/register',
userController.validateRegistration, // validate them
userController.register, // register them to the db
authController.authenticate, // authenticate them
catchErrors(dataController.createMatch) // do some other bits then redirect
)
Fairly new to Express. If more code is needed let me know. Apologies if something similar was answered elsewhere.
Regards,
James.
This is the line in the source where req.user gets set:
https://github.com/jaredhanson/passport/blob/821a474342b1ae900849911b5c3d3ccc4ef5ab86/lib/http/request.js#L44
It's in the method req.login. The documentation is here:
http://www.passportjs.org/docs/login
It states:
When the login operation completes, user will be assigned to req.user.
Further it says:
passport.authenticate() middleware invokes req.login() automatically.
So far everything sounds like it should work...
However, if you read the section about providing a Custom Callback, which is what you're doing, it states:
Note that when using a custom callback, it becomes the application's responsibility to establish a session (by calling req.login()) and send a response.
There are several ways to fix it. You could get rid of the custom callback, you could call login inside the callback, or you could just set req.user = user yourself.

Passing function on express js Route not working

I'm just really new on Node and Express. Trying to pass a function instead of text on my route but it seems not working. I just looked up at documentation there, They mentioned only text with req.send() method. I'm trying to pass here function's but it's not working. and also the alert() not working like this req.send(alert('Hello world')) it say's alert isn't defined or something similar.
**Update: ** I'm trying to execute this library with express and node https://github.com/przemyslawpluta/node-youtube-dl
I'm trying to do here pass functions like this
function blaBla() {
var youtubedl = require('youtube-dl');
var url = 'http://www.youtube.com/watch?v=WKsjaOqDXgg';
// Optional arguments passed to youtube-dl.
var options = ['--username=user', '--password=hunter2'];
youtubedl.getInfo(url, options, function(err, info) {
if (err) throw err;
console.log('id:', info.id);
console.log('title:', info.title);
console.log('url:', info.url);
console.log('thumbnail:', info.thumbnail);
console.log('description:', info.description);
console.log('filename:', info._filename);
console.log('format id:', info.format_id);
});
}
app.get('/', (req, res) => {
res.send(blaBla());
})
**Instead of **
app.get('/', function (req, res) {
res.send('Hello World!')
})
I hope you guy's understood my question.
res.send() expects a string argument. So, you have to pass a string.
If you want the browser to execute some Javascript, then what you send depends upon what kind of request is coming in from the browser.
If it's a browser page load request, then the browser expects an HTML response and you need to send an HTML page string back. If you want to execute Javascript as part of that HTML page, then you can embed a <script> tag inside the page and then include Javascript text inside that <script> tag and the browser will execute that Javascript when the page is parsed and scripts are run.
If the route is in response to a script tag request, then you can return Javascript text as a string and you need to make sure the MIME type appropriately indicates that it is a script.
If the route is in response to an Ajax call, then it all depends upon what the caller of the Ajax call expects. If they expect a script and are going to execute the text as Javascript, then you can also just send Javascript text as a string. If they expect HTML and are going to process it as HTML, then you probably need to embed the <script> tag inside that HTML in order to get the Javascript executed.
In your example of:
response.send(blaBla());
That will work just fine if blaBla() synchronously returns a string that is formatted properly per the above comments about what the caller is expecting. If you want further help with that, then you need to show or describe for us how the request is initiated in the browser and show us the code for the blaBla() function because the issue is probably in the blaBla() function.
There are lots of issues with things you have in your question:
You show req.send(alert('Hello world')) in the text of your question. The .send() method belongs to the res object, not the req object (the second argument, not the first). So, that would be res.send(), not req.send().
In that same piece of code, there is no alert() function in node.js, but you are trying to execute it immediately and send the result with .send(). That won't work for a bunch of reasons.
Your first code block using blaBla() will work just fine as long as blaBla() returns a string of the right format that matches what the caller expects. If that doesn't work, then there's a problem with what blaBla() is doing so we need to see that code.
Your second code block works because you are send a string which is something the caller is equipped to handle.
Update now that you've shown the code for blaBla().
Your code for blaBla() does not return anything and it's asynchronous so it can't return the result. Thus, you cannot use the structure response.send(blaBla());. There is no way to make that work.
Instead, you will need to do something different like:
blaBla(response);
And, then modify blaBla() to call response.send(someTextValue) when the response string is known.
function blaBla(res) {
var youtubedl = require('youtube-dl');
var url = 'http://www.youtube.com/watch?v=WKsjaOqDXgg';
// Optional arguments passed to youtube-dl.
var options = ['--username=user', '--password=hunter2'];
youtubedl.getInfo(url, options, function(err, info) {
if (err) {
res.status(500).send("Internal Error");
} else {
console.log('id:', info.id);
console.log('title:', info.title);
console.log('url:', info.url);
console.log('thumbnail:', info.thumbnail);
console.log('description:', info.description);
console.log('filename:', info._filename);
console.log('format id:', info.format_id);
// construct your response here as a string
res.json(info);
}
});
}
Note also that the error handling does not use throw because that is really not useful inside an async callback.
No one just could help me with that and after finding things are alone I got to know how to do this. In express there is something called middleware we have to use that thing to get this kind of matter done. Those who are really expert or have working experience with express they know this thing.
to using functions with express you need to use middleware.
like below I'm showing
const express = require('express')
const youtubedl = require('youtube-dl');
const url = 'https://www.youtube.com/watch?v=quQQDGvEP10';
const app = express()
const port = 3000
function blaBla(req, res, next) {
youtubedl.getInfo(url, function(err, info) {
console.log('id:', info.id);
console.log('title:', info.title);
console.log('url:', info.url);
// console.log('thumbnail:', info.thumbnail);
// console.log('description:', info.description);
console.log('filename:', info._filename);
console.log('format id:', info.format_id);
});
next();
}
app.use(blaBla);
app.get('/', (request, response) => {
response.send('Hey Bebs, what is going on here?');
})
app.listen(port, (err) => {
if (err) {
return console.log('something bad happened', err)
}
console.log(`server is listening on ${port}`)
})
And remember that you must need to use app.use(blaBla); on top of getting your route. Otherwise this might not work.

Why "req.user" always empty in the /user/me controller after validation with sails-auth?

I'm currently getting started with Sails.js, and I want to add user accounts to my toy app, so I installed the "sails-auth" package that creates a Passport-based user authentication system. I can create new users by sending POST /user, and I can sign in with POST /auth/local.
The documentation says:
Authenticate with the local strategy via a POST to /auth/local with params identifier (email) and password). This will also create a session. See passport.local for more.
However, when I try to GET /user/me, which routes to a controller action that should return the current user in the session, the page instead gives an empty response. Why is this happening? Is there some kind of configuration step that I'm missing?
By the way, I haven't changed or messed around with the sails-auth package. It's still completely new; the "me" action looks like this:
me: function (req, res) {
res.ok(req.user);
}
EDIT: I've found a temporary workaround by searching the issues in the sails-auth repo. Instead of getting a user object from req.user, you can get a string user ID from req.session.passport.user.
Your me action as written is only going to return whatever you are passing in as the user param. Sails builds on top of Express.js so req is the request from the browser and res is the response to the browser.
Most likely you are sending the data to your me action in the req body which is why your response is blank, simply put, req.user is empty so the response is empty. In that case you would access it with req.body.user, you could also try var user = req.params();
For debugging and just generally getting a feel for how the req and res objects are structured I suggest you always start sails (in development, never in production) with the verbose flag.
sails lift --verbose
Then you can do this:
me: function(req, res){
sails.log.verbose(req);
res.ok(req.user);
}
And have it print out the entire req object so you know what's in req.user.
Typically though you would do a database lookup as the user param would be an id. Which means your me function might look (something, obviously depending on your dbc it might be pretty different) like:
me: function(req, res){
var userId = req.body.user;
User.find({'user_id': userId}.exec(function(err, user){
if(err){
//tell peeps there was an error
}else{
res.ok(user);
}
});
}
Best debugging for routes and for the request object:
'/*' : function(req, res, next) {
sails.log.verbose("method: ", req.method, "\n body: ", req.body, "\n url:", req.url);
next();
},
Just paste that at the start of your routes module.

callback function req. and res

I'm having trouble to understand why my callback function needs 2 parameters, i.e. one for the request and one for the response?
For instance i bind a callback function to my server:
server.on("request", doThis(req, resp));
In my opinion he needs only one parameter (req for example here) to store the req information (GET, POST, url, etc.). Why does he need a second for response? I write the information in resp. (i.e. the server, so my other scripts) and not the client.
Every time a request is coming in, the callback function is invoked and so the req parameter is set. Am i wrong? But why do I need the response parameter? My server needs it when he is responding but not when I'm reading/saving the request informations?
The Response parameter is what's generally used to send back a response.
A request comes in, you get the request's data in the req (first) param and you then use the res (second) param to send back a response like:
server.on('message', function(req, res){
res.send('hello your ip is: ' + req.client.ip);
})
This is all dependant on your framework but in expressjs this is how it works (more or less).
To answer your question, you don't need it - you can simply not issue it as a parameter (although it will still be accessible) if you don't plan on responding (which is weird and quite uncommon)
server.on('message', function(req){
console.log('someone requested "message"')
})
Generally speaking, you would always send back a response although the end user might never visually see it, it's just to confirm that the action has been completed successfully.
server.on('save', function(req, res){
saveFile(req.file)
res.sendStatus(200)
})
Additionally, you could check if the process completed successfully - if it did you'd send back a success message, otherwise send back an error message.
server.on('save', function(req, res){
saveFile(req.file, function(error){
if(error) res.sendStatus(500)
res.sendStatus(200)
})
})

Categories