So, I have just added Redis to my expressjs app (this is the first time I use redis), and this is all I did to add the Redis:
import express, { Application } from 'express';
import session from 'express-session';
import {createClient} from 'redis';
import connectRedis from 'connect-redis'
const app: Application = express();
const RedisStore = connectRedis(session);
const redisClient = createClient({
url: 'redis://localhost:6379'
});
app.use(session({
secret: SESSION_SECRET,
resave: false,
saveUninitialized: true,
store: new RedisStore({ client: redisClient }), // added this line
cookie: {
maxAge: 1000 * 60 * 2,
httpOnly: false,
secure: false,
}
}));
export default app;
But when I make any request to any of my express routes, I get an instant error on console, and the app is closed for any further requests. This is the error:
As you can see, there is a line Server is listening on port 3000 at the top of the screenshot, the rest of the strings appears only when I make the first request to the api.
What am I missing here, what did I do wrong? Because every video/article on internet has the same exact code...
Well, as noticed by #Apoorva Chikara and mentioned by #Leibale Eidelman , connect-redis does not support latest node-redis yet, so to fix it I just downgraded my redis package to the version 3.1.2 by using $ yarn add redis#3.1.2.
Thanks!
Related
During the maintenance process, of a NodeJS backend application, I updated the connect-redis package to the last version 6.1.3 and bumped in the following error
Error: A client must be directly provided to the RedisStore
I tried to check online but I didn't understand what change I needed to make in my code to make it work
import redisStore from 'connect-redis';
import session from 'express-session';
import config from '../config/conf';
const RedisStore = redisStore(session);
const sessionStore = new RedisStore({ url: process.env.SESSION_REDIS_URL });
const sessionConfig = {
name: 'os.sid',
store: sessionStore,
saveUninitialized: false,
resave: false,
secret: config.sessionSecret,
secure: config.isProduction,
cookie: {
path: '/',
httpOnly: true,
secure: config.isProduction,
maxAge: null,
},
};
I tried to read this but I cannot figure out what to change in my code with the imports
connec-redis post about the issue
I notice that some of the project will use redis store and express session to save the user session
For example:
const session = require('express-session');
var redis = require("redis");
var redisStore = require('connect-redis')(session);
var client = redis.createClient();
var app = express();
app.use(session({
secret: 'scret',
store: new redisStore({
host: '127.0.0.1',
port: 6379,
client: client,
ttl : 7200
}),
saveUninitialized: true,
// rolling: false,
resave: true,
cookie: {
maxAge: 2 * 60 * 60 * 1000
}
}));
What is the reason that we need to use these two Session Management function at the same time?
express-session can be set up with different "stores" to save session data.
MemoryStore comes with the package express-session.
The authors of express-session warn about this default store.
Warning The default server-side session storage, MemoryStore, is
purposely not designed for a production environment. It will leak
memory under most conditions, does not scale past a single process,
and is meant for debugging and developing.
Redis is one of the compatible session stores and in this case is used "as a replacement" of a default store.
So I am running a node.js backend with a react frontend, and for some reason with this setup:
app.use(session({
store: new MongoStore({
mongooseConnection: mongoose.connection
}),
secret: process.env.SECRET_KEY,
resave: false,
saveUninitialized: false,
cookie: {
maxAge: 1000 * 60 * 60 * 24 * 7 * 2, // two weeks
secure: false,
httpOnly: false,
}
}));
I save the username using: req.session.username = username; which does save but then whenever I try to check the session on another page the username is gone.
Full source code: https://github.com/CTF-Cafe/CTF_Cafe/tree/master/backEnd
PS: it works in production completely fine, but not locally I tried with httponly false, and secure false. No change.
Any help appriciated
When you serve your frontend from your backend the session will be working because it has the same origin. However, for your local environment, you will be running React app in a different port, and the Express app would be also different. When a port is different it is already considered a different origin and cookies, sessions won't be shared.
You can proxy your frontend via the node app and this way you can have the same origin and your session will remain.
const proxy = require('express-http-proxy');
const app = express();
...
// Add after your routes
app.use(proxy('http://127.0.0.1:3000')); // assuming your Reacts runs on P3000
Check this answer too.
I have tried to build an Express 4 Web App using Azure. I found on several articles that I can store the sessions in Azure Redis Cache. However, how should I connect my web app to the redis cache?
var session = require('express-session');
var redis = require('redis');
var RedisStore = require('connect-redis')(session);
var client = redis.createClient(6380, 'MyHost', { auth_pass: 'MyPass', tls: { servername: 'MyHostName' } });
app.use(session({
secret: 'keyboard cat',
key: 'sid',
resave: false,
saveUninitialized: false,
store: new RedisStore(client);
}));
But then it returns an error when I run the app. Saying
TypeError: this.client.unref is not a function
How can I solve this? Thanks!
You might make a mistake in RedisStore constructor.
Change the following line of code store: new RedisStore(client); as below:
store: new RedisStore({client: client});
I'm looking for sessionstore for production app because I have error message:
Warning: connect.session() MemoryStore is not designed for a
production environment, as it will leak memory, and will not scale
past a single process
My code:
var express = require('express');
var ECT = require('ect');
var cookieParser = require('cookie-parser');
var compress = require('compression');
var session = require('express-session');
var bodyParser = require('body-parser');
var _ = require('lodash');
var passport = require('passport');
var expressValidator = require('express-validator');
var connectAssets = require('connect-assets');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(expressValidator());
app.use(methodOverride());
app.use(cookieParser());
app.use(session({
resave: true,
saveUninitialized: true,
secret: secrets.sessionSecret,
}));
app.use(passport.initialize());
app.use(passport.session());
var app = module.exports = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
server.listen(app.get('port'), function() {
console.log('Express server listening on port %d in %s mode', app.get('port'), app.get('env'));
});
module.exports = app;
I don't know what is the best solution for my production app. I'm using sequelize as ORM with PostgreSQL.
I will be very grateful with any opinion.
Though an answer has been accepted, I think a more elaborated answer is in order, so that people who actually want to use Express with PostgreSQL for consistent session storage can have a proper reference.
Express has the session module to handle the sessions though it defaults to in-memory storage that is suitable for development stages but not for production
Warning The default server-side session storage, MemoryStore, is purposely not designed for a production environment. It will leak memory under most conditions, does not scale past a single process, and is meant for debugging and developing.
So for PostgreSQL there is a dedicated simple connector called connect pg simple
Once you import the connect-pg-simple you . need to pass it the session import like this:
const session = require('express-session')
const pgSession = require('connect-pg-simple')(session)
When you add the session as middleware you'll have to pass it its settings
app.use(session(sessionConfig))
and in your sessionConfig, this would be where you set all your session parameters you need to add a store option that would look like this (adding the full set of options though for the matter at hand just note the store option):
const sessionConfig = {
store: new pgSession({
pool: sessionDBaccess,
tableName: 'session'
}),
name: 'SID',
secret: randomString.generate({
length: 14,
charset: 'alphanumeric'
}),
resave: false,
saveUninitialized: true,
cookie: {
maxAge: 1000 * 60 * 60 * 24 * 7,
aameSite: true,
secure: false // ENABLE ONLY ON HTTPS
}}
The new instance of pgSesision takes two options, the pool which is the config setup to access the PostgreSQL DB and the table name.
The DB connection setting should look like this:
const sessionDBaccess = new sessionPool({
user: DB_USER,
password: DB_PASS,
host: DB_HOST,
port: DB_PORT,
database: DB_NAME})
Also note that the session pool must be initiated:
const sessionPool = require('pg').Pool
I got it working with connect-pg-simple.
Create a session table with the provided table.sql, and pass in a connection string or an object.
If you have just to store session you can use redis or maybe mongoDB if you want persistence.