i m creating chat application, using nodejs (0.8.15), express (>3.0) framework and mongodb for register users.
var express = require('express')
, http = require('http')
, path = require('path')
, io = require('socket.io');
var app = express()
, server = http.createServer(app)
, io = io.listen(server);
app.configure(function() {
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser('secret'));
app.use(express.session({cookie: {maxAge: 60000*100}}));
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
});
app.configure('development', function() {
app.use(express.errorHandler());
});
app.get('/chat', function(req, res) {
res.render('chat');
});
server.listen(app.get('port'), function() {
console.log("Express server listening on port " + app.get('port'));
});
io.sockets.on('connection', function (socket) {
socket.on('start-chat', function() {
// here i need to know req and res
// for example, i need to write:
// socket.username = req.session.username;
});
});
Q: How to get res and req objects to work with them when chatting like on code above? or am i going wrong way of creating chat with user auth?
thank you!
EDITED: answer is here
http://www.danielbaulig.de/socket-ioexpress/
You need to use authorization.
var socketIO = require('socket.io').listen(port);
socketIO.set('authorization', function(handshakeData, cb) {
//use handshakeData to authorize this connection
//Node.js style "cb". ie: if auth is not successful, then cb('Not Successful');
//else cb(null, true); //2nd param "true" matters, i guess!!
});
socketIO.on('connection', function (socket) {
//do your usual stuff here
});
You cannot get res and req objects in a socket.io handler, as they simply do not exist - socket.io is not normal http.
Instead, what you can do is authenticate users and assign them a session auth token (a key that identifies that they're logged in and who they are).
Then the client can send the auth token along with every socket.io message, and the server-side handler can just check the validity of the key in the database:
io.sockets.on('connection', function (socket) {
socket.on('start-chat', function(message) {
if (message.auth_token)
//Verify the auth_token with the database of your choice here!
else
//Return an error message "Not Authenticated"
});
on socket.io v1.0 and above you can get the req object like this
var req = socket.request;
var res = req.res;
Related
I have built a webapp, based on wes bos's course:
https://github.com/wesbos/Learn-Node/tree/master/stepped-solutions/45%20-%20Finished%20App
Now, I want to add a simple messaging system, so I'm trying to add socket.io
On their website: https://socket.io/get-started/chat/ they suggest this code:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket){
console.log('a user connected');
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
So in my start.js file I'm trying to adapt it to the code above, and it partly works, only that on their website it says it should only log once for every connected user.
And in my case it logs like every frame.
Any idea what is wrong?
This is my start.js
const app = require('./app');
app.set('port', process.env.PORT || 7777);
const server = app.listen(app.get('port'), () => {
console.log(`Express running → PORT ${server.address().port}`);
});
// const http = require('http').Server(app);
const io = require('socket.io').listen(server);
io.on('connection', function(socket){
console.log('a user connected');
});
EDIT: Here is also my ap.js:
// create our Express app
const app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views')); // this is the folder where we keep our pug files
app.set('view engine', 'pug'); // we use the engine pug, mustache or EJS work great too
// serves up static files from the public folder. Anything in public/ will just be served up as the file it is
app.use(express.static(path.join(__dirname, 'public')));
// Takes the raw requests and turns them into usable properties on req.body
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// Exposes a bunch of methods for validating data. Used heavily on userController.validateRegister
app.use(expressValidator());
// populates req.cookies with any cookies that came along with the request
app.use(cookieParser());
// Sessions allow us to store data on visitors from request to request
// This keeps users logged in and allows us to send flash messages
app.use(session({
secret: process.env.SECRET,
key: process.env.KEY,
resave: false,
saveUninitialized: false,
store: new MongoStore({ mongooseConnection: mongoose.connection })
}));
// // Passport JS is what we use to handle our logins
app.use(passport.initialize());
app.use(passport.session());
// // The flash middleware let's us use req.flash('error', 'Shit!'), which will then pass that message to the next page the user requests
app.use(flash());
// pass variables to our templates + all requests
app.use((req, res, next) => {
res.locals.h = helpers;
res.locals.flashes = req.flash();
res.locals.user = req.user || null;
res.locals.currentPath = req.path;
next();
});
// promisify some callback based APIs
app.use((req, res, next) => {
req.login = promisify(req.login, req);
next();
});
// After allllll that above middleware, we finally handle our own routes!
app.use('/', routes);
// If that above routes didnt work, we 404 them and forward to error handler
app.use(errorHandlers.notFound);
// One of our error handlers will see if these errors are just validation errors
app.use(errorHandlers.flashValidationErrors);
// Otherwise this was a really bad error we didn't expect! Shoot eh
if (app.get('env') === 'development') {
/* Development Error Handler - Prints stack trace */
app.use(errorHandlers.developmentErrors);
}
// production error handler
app.use(errorHandlers.productionErrors);
// done! we export it so we can start the site in start.js
module.exports = app;
You need to remove the following line:
const server = app.listen(app.get('port'), () => {
console.log(`Express running → PORT ${server.address().port}`);
});
You're listening here, but you should be doing this:
const http = require('http').Server(app);
http.listen(3000, function(){
console.log('listening on *:3000');
});
or with your case of setting the port through express:
const http = require('http').Server(app);
http.listen(app.get('port'), function(){
console.log(`Express running → PORT ${server.address().port}`);
});
A more common syntax is to declare you port as a const:
const PORT = 7777
const http = require('http').Server(app);
http.listen(PORT, function(){
console.log(`Express running → PORT ${PORT}`);
});
In turn, your socket.io server will be created as:
const io = require('socket.io')(http);
As it stands your are (from what I can tell) creating two servers.
EDIT:
Your entire start.js should look like this:
const app = require('./app');
app.set('port', process.env.PORT || 7777);
const http = require('http').Server(app);
const io = require('socket.io')(http)
io.on('connection', function(socket){
console.log('as user connected' + Math.random());
});
http.listen(app.get('port'), function(){
console.log(`Express running → PORT ${server.address().port}`);
});
I'm writing an application that takes in a post request and sets a cookie pulled from the POST info. I'm stuck in a catch 22. In the first code sample I can set the cookie but can't access the data, in the second I can access the data but can't set the cookie. I'm sure I'm missing some basic concept of how the middle ware works but I can't for the life of me find the info I need.
The code below creates the cookie as expected but my post variable become undefined
var express = require('express')
, routes = require('./routes')
, user = require('./routes/user')
, handshake = require('./routes/handshake')
, http = require('http')
, path = require('path');
var app = express();
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(function (req, res, next) {
var cookie = req.cookies.cokkieName;
console.log("cookie_name" , cookie);
if (cookie === undefined)
{
//cookie is set but I can't use req.post.xxxx. It"s always undefined
res.cookie("price", 111, { maxAge: 10000 });
console.log('cookie has been created successfully');
}
else
{
console.log('cookie exists', cookie);
}
next();
});
app.use(app.router);
app.use(require('stylus').middleware(__dirname + '/public'));
app.use(express.static(path.join(__dirname, 'public')));
app.post('/handshake', handshake.token);
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
The following code executes the setCookie callback (because the console output shows up), and on the console the variables are properly defined, but the cookie is not set.
var express = require('express')
, routes = require('./routes')
, user = require('./routes/user')
, handshake = require('./routes/handshake')
, http = require('http')
, path = require('path');
var app = express();
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.methodOverride());
var setCookie = function (req, res, next) {
var cookie = req.cookies.cokkieName;
console.log("cookie_name" , cookie);
if (cookie === undefined)
{
res.cookie("price", 111, { maxAge: 10000 });
//in the console the post.body.xxxx data appears correctly but no cookie!!!
console.log('cookie has been created successfully',post.body.xxx);
}
else
{
console.log('cookie exists', cookie);
}
next();
};
app.use(app.router);
app.use(require('stylus').middleware(__dirname + '/public'));
app.use(express.static(path.join(__dirname, 'public')));
app.post('/handshake', setCookie ,handshake.token);
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
Trying to make the code more readable introduced too many typos that weren't relevant to my code. I took the suggestion and changed the code in the following way but it still doesn't write a cookie to the client.
var express = require('express')
, routes = require('./routes')
, user = require('./routes/user')
, handshake = require('./routes/handshake')
, http = require('http')
, crypt = require('crypto')
, io = require('socket.io')
, db = require('levelup')('./mydb')
, path = require('path');
var app = express();
app.use(express.cookieParser());
app.use(express.bodyParser());
var cookieMiddleware = function (req, res, next) {
var cookie = req.cookies.user;
console.log("cookie_name" , cookie);
if (cookie === undefined)
{
// no: set a new cookie
var random = Math.random().toString();
random=random.substring(2,random.length);
sessionToken = Date.now() + random;
salt = sessionToken + req.body.address;
sha2 = crypt.createHash('sha256');
sha2.update(sessionToken);
var price = req.body.price;
var encryptedSession = sha2.digest('hex');
console.log('post body',price );
res.cookie('user','price' , { maxAge: 100000 });
console.log('existing cookies', req.cookies);
}
else
{
console.log('cookie exists', req.cookies);
}
next();
};
//development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.logger('dev'));
app.use(express.session({secret: "TheSuperSecretStringForHashing"}));
app.use(express.methodOverride());
app.use(app.router);
//app.use(express.favicon());
app.use(require('stylus').middleware(__dirname + '/public'));
app.use(express.static(path.join(__dirname, 'public')));
app.post('/handshake', cookieMiddleware , handshake.token);
app.get('/', routes.index);
app.get('/users', user.list);
var server = http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
io = io.listen(server);
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
The handshake.js handler
exports.token = function(req, res){
req.body.title = 'Payment Portal';
res.render('payment_init', req.body);
};
You are checking for a cookie named cokkieName, but the cookie you are setting has the name price.
Try changing this to:
var cookie = req.cookies.price;
cookie should now contain your cookie value.
I've the following Server Side Code:
var express = require('express')
, http = require('http')
, routes = require('./routes')
, io = require('socket.io')
, factory = require('./serverfactory.js');
var app = express();
var server = app.listen(3000);
io = io.listen(server);
io.sockets.on('connection',function(socket){
console.log('new user');
socket.emit('hail','mysimplemsg');
socket.on('customevent',function(msg){
console.log(msg);
});
});
//var app = module.exports = express.createServer();
// Configuration
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
// Routes
app.get('/', routes.index);
And this is the client side :
var socket = io.connect('http://localhost:3000');
socket.emit('customevent','work');
socket.on('hail',function(msg){
console.log(msg);
});
I am expecting that my git console outputs new user (which it does) then it should output work (which it does not) then i get a msg in my browser console mysimplemsg (which it does not).
Whats going on why the event at server side that is customevent is not called and why the event at the client side that is hail is not called ?
I believe the issue is that you are emitting customevent from the client before you are connected. Try adding a connect handler and moving your client side emit into it:
var socket = io.connect('http://localhost:3000');
socket.on('hail',function(msg){
console.log(msg);
});
socket.on('connect',function(){
console.log('connected to socket.io server');
socket.emit('customevent','work');
});
If the connect handler is not hit then verify that you are referencing the client side socket.io javascript library correctly (jade syntax):
script(type='text/javascript',src='/socket.io/socket.io.js')
Finally figured it out.
It was working fine on opera but not on chrome and firefox. I found this link in which the guy says to insert this code snippet on the server side.
io.configure('development', function(){
io.set('transports', ['xhr-polling']);
});
It's working fine now.
I am just trying to send a simple message from client to server on button Click.
Edit:
When my index.jade loads I use the following code and for creating the socket.io object and then forward it to my Menu_Contoller which in turn assigns the socket object to the Menu_Model.Then whenever the function SendOptionSelectedToServer of Menu_Model.js is called i use the socket object to of Menu_Model.The values in this function are correct.Just don't know why it is not emitting.
index.jade
script(src = '/socket.io/socket.io.js')
script(src = '/javascripts/Menu_Controller.js')
script(src = '/javascripts/Menu_Model.js')
script
var socket = io.connect('http://localhost:3000');
socket.emit('GameType','chutia');
var Menu_Control = Object.create(Menu_Controller);
Menu_Control.Init(socket);
Menu_Controller.js
var Menu_Controller = {
Model : null,
Init:function(socket)
{
this.Model = Object.create(Menu_Model);
this.Model.Init(socket,this);
},
SendOptionSelectedToServer:function(option) <-- called from a view menu which we don't have to care about because value in 'option' are correct.
{
this.Model.SendOptionSelectedToServer(option);
}
};
Menu_Model.js
var Menu_Model = {
Socket : null,
Controller : null,
Init:function(sock,controllerRef)
{
this.Socket = sock;
this.Controller = controllerRef;
},
SendOptionSelectedToServer:function(option)
{
this.Socket.emit(option.type,option.ghostName); <-- this line.
}
};
And here's my complete server side code in app.js.
var express = require('express')
, http = require('http')
, routes = require('./routes')
, io = require('socket.io')
, factory = require('./serverfactory.js');
var app = express();
var server = app.listen(3000);
io = io.listen(server);
io.sockets.on('connection',function(socket){
console.log('new user'); <-- this is printed in the log.
socket.on('GameType',function(msg){
console.log(msg); <-- but this is not.
});
});
//var app = module.exports = express.createServer();
// Configuration
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
// Routes
app.get('/', routes.index);
When a new connection occurs it writes new user in the log.But when a call is made using emit from the client side it doesn't write any msg in the console.I've already checked the params at the client side and they are correct. the option.type at the client side will contain GameType.
Why it is not calling the event on the client side ?
I buils small application in which I use socket.io and expressjs
Server side
var express = require('express'),
sio = require('socket.io');
var app = express.createServer();
app.configure('development', function(){
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.static(__dirname + '/'));
app.set('views', __dirname + '/views');
app.use(express.errorHandler({dumpExceptions: true, showStack: true}));
app.use(app.router);
});
app.listen(4000);
var io = sio.listen(app);
app.get('/', function (req, res) {
res.redirect('index.html');
});
io.sockets.on('connection', function (socket) {
app.post('/mysegment',function(req,res){
var userData = req.body;
socket.emit('sendUser', userData);
res.send("yes I got that segment");
});
socket.on('getUser',function(msg){
console.log("Yes Socket work Properly "+msg);
});
});
And index.html
var socket = io.connect();
socket.on('connect', function () {
console.log("client connection done.....");
});
socket.on('sendUser', function (data) {
alert("On send user");
socket.emit('getUser',"Hello");
});
This demo work perfectly
But When I refresh page
And send post request to "/mysegment" that I time socket does not work properly.
I do not get message on my console "Yes socket work properly(and my msg)"
But I got response "Yes I got that segment"
Any suggestion please...
io.sockets.on('connection', function (socket) {
app.post('/mysegment', ...
What is happening here, is that each time any client connects with websockets, a new handler is added to all /mysgment POST request. Then, when anybody send a POST to /mysegment, all connected clients will get userData... which is probably not what you want.
To keep it simple, stick to using sockets for one thing, and normal HTTP for others.
Otherwise you'll have to share the session and/or find the corresponding socket.
You can access the socket object in your express routes like this (in scoket.io v4):
var socket = io.sockets.on('connection', function (socket) {
socket.on('getUser',function(msg){
console.log("Yes Socket work Properly "+msg);
});
});
app.post('/mysegment',function(req,res){
var userData = req.body;
socket.emit('sendUser', userData);
res.send("yes I got that segment");
});