how to make redis session store available in socket.io - javascript

I am using node.js with socket.io and redisStore for my express-sessions. on my socket handshake, i want to read the cookie to get the session cookie, so i am able to read from and write to the session.
here is what i got so far:
in my app.js:
var express = require('express');
var app = express();
var redis = require('redis');
var redisClient = redis.createClient(6379, 'localhost');
server = http.createServer(app);
server.listen(8080, function() {
console.log('listening on *:8080');
});
var io = require('./routes/index').listen(server);
var routes = require('./routes/index').router;
app.use(session({
secret: 'my-secret-string',
key: 'express.sid',
cookie: { maxAge: 2628000000 },
store: new (require('express-sessions'))({
storage: 'redis',
instance: redisClient,
host: 'localhost',
port: 6379,
}),
resave: true,
saveUninitialized: true
}));
app.use('/', routes);
module.exports = app;
and in my index.js:
var express = require('express');
var router = express.Router();
var socketio = require('socket.io');
var io;
router.get('/', function(req, res) {
//do stuff here...
res.render('index', { params: params });
}
var listen = function(app) {
io = socketio.listen(app);
io.sockets.on('connection', function (socket) {
console.log(socket.handshake); // there is an handshake object with cookie information
// which i can parse the express.sid (=sessionID) from
socket.on('someEvent', function(args, callback) {
//do stuff here
callback(err, msg);
});
});
return io;
}
module.exports = {
listen: listen,
router: router
}
Now, when the client emits "someEvent", i want to read the session ID from the session cookie and do stuff with the session data.
I followed this guide, and this, but they seem to be outdated or do not fit quite my setup.
Had have no luck so far. Help is greatly appreciated! This is my first node.js project..

Related

Implementing socket.io in mongoDB and Angular it is throwing errors Cannot GET /socket.io/

I am developing an angular application which I need to use notifications for example.
I have a user which can add friends and then I can sent a friend request as in facebook and then the other user will be notificate in realtime for example You have one new notification, this user wants to be friends.
If anyone has better idea than socket.io I am free to listen and to learn
The problem it is that I get everytime Cannot GET /socket.io/
Request URL: http://localhost:4200/socket.io/?EIO=3&transport=polling&t=NVvJf99
Request Method: GET
Status Code: 404 Not Found
Remote Address: 127.0.0.1:4200
I can show the list who sent me friend but I need everytime to reload page to see new requests.
I am using socket.io in both frameworks.
Angular I have installed with npm and the same in the mongoDB.
My server.js that is what I use for the requests and responses in frontend.
Server.js
const express = require('express');
const mongoose = require('mongoose');
const http = require('http');
const cors = require('cors');
const routes = require('./src/app/routes/routes');
const path = require('path');
const socketIO = require('socket.io');
const app = express();
const server = http.Server(app);
mongoose.connect('mongodb+srv://vip:admin#test-name-sn4qu.mongodb.net/test?retryWrites=true&w=majority'
, {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false
});
app.use(cors());
const io = socketIO(server);
app.set(io);
app.use(express.json({limit: '50mb'}));
app.use(express.urlencoded({limit: '50mb', extended: true}));
app.use('/images', express.static(path.resolve(process.cwd(), '../images')));
app.use(routes);
mongoose.set('useNewUrlParser', true);
mongoose.set('useFindAndModify', false);
mongoose.set('useCreateIndex', true);
app.get("/", (req, res) => {
res.json({ message: "Welcome to application." });
});
const PORT = process.env.PORT || 5000;
server.listen(PORT);
And then in the friendController I use something like this.
function createNewRequest(req, res, next) {
const io = req.app.get('io');
friendService.createNewRequest(req.body)
.then(res.status(200).json({ message: 'Friend added successfully' }),
io.emit('newTaskAdded'))
.catch(err => next(err));
}
And then in the frontend I do have something like this.
And I am having an error which says
Cannot find namespace 'SocketIOClient'. private socket:SocketIOClient.Socket;
import * as io from "socket.io-client";
constructor() {
this.socket = io();
}
ngOnInit(): void {
this.LoadRequestingFriends();
this.socket.on('newTaskAdded', () => {
this.LoadRequestingFriends();
})
}

Passing a Socket.IO instance to route files

I am looking to share the a socket.io instance with my express route files.
I previously had the socket.io listener in one routes file, orders.js on port 5200 and the express server listening in app.js on port 5000, however my cloud service required me to use one port for both, so I did have moved them both to app.js. The code below has been drastically simplified to remove noise
./app.js
const port = process.env.PORT || 8000;
const socket = require('socket.io');
const server = app.listen(port, () => console.log(`[!] Listening on
port: ${chalk.green(port)}`))
const io = module.exports = socket(server);
app.use(express.json());
app.use(cors());
app.use('/', router)
./routes/index
const express = require('express');
const router = express.Router();
router.use('/orders', require('./orders'));
module.exports = router;
./routes/orders.js
const express = require('express');
const router = express.Router();
const io = require('../index');
io.on('connection', (client) => {
console.log("CLIENT CONNECTED");
})
router.get(... etc etc
I expect to get a connection console but instead I'm getting an error that IO is not a function. When I console.log(io) I get {}
Try this way
const user = require('{SET FILE PATH}');
io.on('connection', function (socket) {
console.log('Socket connected...', socket.id);
socket.on('login', function (req) {
user.login(socket, req, 'login'); // socketObj , req , methodName
})
});
user.js
class User {
login(socket, req, methodName) {
console.log("Socket ref is ::: " , socket);
}
}
module.exports = new User();

How can I make session variables accessible to sub application

I am building an api that will interface with the MongoDB database and have mounted it as a subapplication. I have defined a session variable in my server controller.
However, any time that the server files need to talk to the api files the session variables are never passed off.
Heres the app.js file
//app.js file
'use strict';
process.env.NODE_ENV = 'development';
var express = require('express');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var MongoStore = require('connect-mongo')(session);
var flash = require('connect-flash');
var helmet = require('helmet');
var app = express();
app.use(helmet());
var port = process.env.PORT || 3000;
mongoose.connect("mongodb://localhost:27017/striv4");
var db = mongoose.connection;
// mongo error
db.on('error', console.error.bind(console, 'connection error:'));
app.use(session({
secret: 'secret',
resave: true,
saveUninitialized: false,
store: new MongoStore({
mongooseConnection: db
})
}));
app.use(flash());
// make user ID available in templates
app.use(function (req, res, next) {
res.locals.currentUser = {
username:req.session.username,
id: req.session.userId
};
next();
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser('secreter'));
app.use(logger('dev'));
var api = require('./app_api/routes/index');
var serverRoutes = require('./server/routes/index');
//static file middleware
app.use(express.static(__dirname + '/public'));
app.set('views',__dirname +'/server/views');
app.set('view engine','pug');
app.use('/',serverRoutes);
app.use('/api',api);
//custom error handler
app.use(function(error, req, res, next) {
res.status(error.status || 500);
res.send('Error: '+error.message);
});
app.listen(port);
console.log('Listening on port: '+port);
You've got the whole program listed so there is more than one way for this to have gone wrong. Here are my suggestions to fix this:
Check the version of express-session you've installed. (Just run npm ls in the terminal and in your root Node app folder where you're package.json file is). If it's equal to or greater than v1.5.0, you don't need the cookie-parser for sessions anymore. Comment out the app.use line for the cookie parser and see if this works.
If you still need cookie parser for some other reason, you should use the same secret for sessions and the cookie parser. In your code, you've set two different values for secret.
I've seen that the other big failure for sessions occurs if the session store is not correctly connected to your Node app. Cross-check that the database is available and working. In my experience, Express sessions will fail silently if it can't get to the DB.
Hope this helps.

cookie doesn't get sent on first request

I've got the following code on my server.js express application:
var express = require('express');
var fallback = require('express-history-api-fallback');
var compress = require('compression');
var favicon = require('serve-favicon');
var prerenderio = require('prerender-node');
var config = require('getconfig');
var app = express();
app.use(function (req, res, next) {
if (config.environment !== 'local') {
res.cookie('config', JSON.stringify(config), { secure: true });
}
else {
res.cookie('config', JSON.stringify(config));
}
next();
});
app.get('/versioncheck', function(req, res) {
return res.json({ version: config.version });
});
app.use(compress());
app.use(prerenderio.set('prerenderToken', config.prerender_token).set('protocol', 'https'));
app.use(express.static(__dirname, { maxAge: 31536000 }));
app.use(favicon(__dirname + '/favicon.ico'));
app.use(fallback('index.html', { root: __dirname }));
const PORT = process.env.PORT || 1010;
app.listen(PORT, function () {
console.log('Server started on port %s', PORT);
});
The first middleware I'm setting up with express is quite simple: It sends down a cookie to the client with some config information. The issue I'm facing is that this cookie doesn't get sent down to the client upon first request. For all subsequent requests it does work fine. What am I missing?
I had a similar problem some time ago.
At the begin of the first request, the cookie does not exist.
The cookies get sent during the request, not before.
So, at the begin of the second request, the cookie is set (from request 1).

How to properly setup redis for session store

I am trying to setup Redis Store like this:
var express = require('express');
var app = express();
.......
.......
var session = require('express-session');
var redis = require("redis").createClient();
var RedisStore = require("connect-redis")(session);
app.use(session({
store: new RedisStore({
host: 'localhost',
port: 6379,
client: redis
}),
secret: 'keyboard cat'
}));
But using like this the passport.js wont work and the express-flash will throw an error: `Error: req.flash() requires sessions.
I believe Redis is not working at all.
I am very confuse with the configuration also, should i put localhost in the host key? I am using Cloud 9, not my localhost.
What i am doing wrong?
Not sure I can help you with passport.js and express-flash, but this is how I've setup my session with express, redis and socket.io :
var express = require('express');
var session = require('express-session');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var RedisStore = require('connect-redis')(session);
............
var cookieSecret = "secret phrase";
var sessionMiddleware = session({
store: new RedisStore({
host: '127.0.0.1',
port: 6379,
prefix: 'sess'
}),
secret: cookieSecret,
cookie: {httpOnly: true, secure: true}, //I'm using https, so you should remove secure: true
resave: true,
saveUninitialized: true
});
.....
app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser(cookieSecret));
app.use(sessionMiddleware);
....
var io = require('socket.io')(https);
io.use(function(socket, next) {
sessionMiddleware(socket.request, socket.request.res, next);
});
io.on('connection', function(socket){
console.log("connected");
console.log(socket.request.session);
});
Hope this could help a bit
Had a similar problem. Yes, chances are you do not have a Redis server running for the client you created. Try installing and running redis-server on your machine, that did the trick for me.

Categories