Socket.io and request and response objects - node.js

I'm quite new on node.js and now I'm learning socket.io.
I'm developing an app step by step so, at this time, I have an app that can login an user, do crud operation in mysql and mongodb and upload files, all these operations are manage with some web pages with HTML and javascript technologies launched directly from restify.
After that I'm tring to add socket functionality to, at this time, simple print who is online.
So, before I have something like:
server.get('/login', function(req, res, next){ ... });
and now I have something like:
socket.on("login", function (req, res, next){ ... });
but, naturally, req and res are undefined!
Are there the same objects into socket.io?

To my understanding, you want to pass values back and forth in your request and response using socket.io.
Yes it is possible to do that and you syntax should be something like this...
Using express.js:
io.on('login', function(req){
client.emit('response event', { some: 'data' });
Note: when using emit you send the data to everyone, you have other methods like .broadcast(), .to(), etc.. for other use cases refer to socket.io github for better understanding
And lastly, inside emit you define the function you want to call on the client side and the data you want to send to the client.

Related

Is all communication from frontend to backend done via routes?

I'm working on a vuejs/express fullstack web app, and I know you can specify endpoints on the server like:
app.get('/', function (req, res) {
res.send('GET request to the homepage')
})
Which you can then hit from the client to display the home page.
But I'm wondering what about when you don't need to go to a 'route'? For example, you just want to send some data from client to server to do some calculations and then send data back to the client - do you still specify an endpoint e.g /FunctionName and access it from the frontend in the same way or is there some other way to call a function in the backend?
This is the 'express' way to define endpoints (or routes), regardless if it will return an html page like the example you've specified, or do some computation by calling other functions with user-specified parameters.
As a basic example:
app.post('/myendpoint', function (req, res) {
returnValues = callMyFunction(req)
res.send(returnValues)
})

node JS express framework sendFile("home.html",{context?})

I'm reading the Express framework docs, making my basic login/redirect page routes.
The following route accepts the submission:
app.post('/',function(req,res){
//console.log("USERNAME: "+req.body.username);
//console.log("PASSWORD: "+req.body.password);
res.redirect('/chat');
});
and this:
app.get('/chat', function(req, res){
res.sendFile(__dirname + '/templates/chat.html');
//console.log("request");
});
takes the user to a new page.
How do I send context? Should I be using res.render()? Neither function seems to contain an option for data like {username:req.body.username}. How should data be passed between routes?
Generally to handle logins with express you'd use something like passport's local strategy, which attaches a user object to the request object (req.user) for you for each route. I don't know that what you're trying will work in a larger context -- you'd need some kind of session-based middleware like express-session at the very least, so you can attach variables per session (I think it gives you req.session). By default, express has the capability to store information for one request/response cycle (res.locals) or for the entire instance of the app (i.e. for all users) (app.locals).
As far as getting data into views, you would use res.render with something like EJS, pug, or another view engine. For example, if in your route, you had something like:
route.get('/', (req, res) => {
res.render('template', { username: 'yourname' })
}
you can refer to that in your ejs template like so:
<h1>Hello, <%= username %>!</h1>
which will get sent back as this:
<h1>Hello, yourname!</h1>
So, to answer your question:
You would use res.render to get variables & data into your views
You don't share data across routes by default except app-level data that applies to all users, which can be set on app.locals
You can use authentication middleware like passport and session middleware like express-session to keep track of user information across routes per session.
Hope this helps! Good luck with express!

How to use express req variables with socket.io

So what I'm trying to do is when someone loads my site, and gets authenticated by passport, their userId is stored in req.user.id in my app.get('/home', funciton(req, res). Now what I am trying to do in a way is this:
app.get('/home'. function(req, res){
io.on('connection', function(socket){
socket.emit('userId', req.user.id);
});
}
Thats essentially what I'm trying to do, but I know it is very wrong. Now my question is how can I get the req.user.id to the client so I can use it in future interactions with the server.
Looks like you're receiving a GET request and using Express right? You're probably passing the userid in the querystring, so you'll want to use:
req.query.userid
This basically pulls the value assigned to a key in the querystring.
Source: http://expressjs.com/en/api.html#req.query
I would also recommend sending something like ?userid=12345 in the querystring, rather than an object (user.id) in the querystring, as encoding an object will unnecessarily add more complications and not needed.
You can use express session with socket.io
There's a npm module called express-socket.io-session

How to push a sequence of html pages after one request using NodeJS and ExpressJS

I am turning around in stackoverflow without finding an answer to my question. I have used expressJS fur several days in order to make an access webpage that returns first an interstitial and then a webpage depending on several informations I can get from the requester IP and so on.
My first idea for the interstitial was to use this piece of code:
var interstitial = function(req, res, next) {
res.render('interstitial');
next();
}
router.get('/', interstitial, nextPage);
setting a timeout on the next nextPage callback function of router.get().
However it looks that I could not do that. I had an error "Error: Can't set headers after they are sent.". I suppose this is due to the fact that res.render already give a response to the request and in the philosophy of express, the next function is passing the req, res args for another reply to another function that possibly could do it. Am I right?
In that case, is there a way to give several answer, with timeout to one request? (a res.render, and after that in the next callback a rest.send...).
Or is this mandatory to force client to ask a request to give back another response? (using js on the client side for instance, or timers on client side, or maybe discussing with client script using socket.io).
Thanks
Not sure I fully understand, but you should be placing all your deterministic logic within the function of the handler you're using for your endpoint.
Kinda like so:
router.get('/', function(req, res){
var origin = request.origin;
if (origin == '11.22.33.44'){
res.send('Interstitial Page.');
}else{
res.send('Home Page');
}
});
You would replace the simple text responses with your actual pages, but the general idea is that once that endpoint is handled you can't next() it to secondary handler.

Where does the /api directory come from in an Express application?

For example:
router.get('/api/todos', function (req, res){
db.todos.find(function (err, data){
res.json(data);
});
});
I am having a hard time understanding what '/api/todos/ actually means. I don't have a directory name either one of these in my application. What exactly is this and where is it?
/api/todos/ does not refer to a local file, it corresponds to a URL request. In the function you provided, if you were to add this route to an express app then visit http://localhost/api/todos, the server would respond with the JSON data returned from the database query you are making.
router.get('/api/todos', function (req, res){
This first line accepts all GET requests to /api/todos, and passes the req and res objects into a callback for you to work with. See http://www.murvinlai.com/req-and-res-in-nodejs.html for an explanation of those objects.
db.todos.find(function (err, data){
Here, it is assumed that you have a db object which may perform database lookups based on some kind of input parameters.
res.json(data);
The res.json method simply sends the JSON back to the client that requested it.
See https://www.packtpub.com/books/content/understanding-express-routes for further info on routing in express.
That's not a directory. That's a URL. Routers route URLs to resources. It could be files, it could be other URLs or most commonly it could be some javascript logic that generates the response you want (JSON, XML, HTML, PDF etc.)

Resources