I have an application where I need to limit the number of active connections, and the most logical way of doing this to me, would be to simply count the number of active sessions.
I have searched for "node express session count" but did not find anything useful.
Is it possible to get the number of open sessions in node express ?
The alternative would be to save the IP address of each connected client, but the problem with this method is that the ip address would need to be manually removed from the datastore.
I guess if I use redis as the data store, I could use expire to achieve something similar.
set ip.192.168.42.1 true
expire ip.192.168.42.1 60
ttl ip.192.168.42.1
etc etc
Or is there a better way ?
EDIT
I have tried the suggestion of using MemoryStore but I can't seem to figure out how to use it ??
var express = require("express");
var MemoryStore = express.session.MemoryStore;
MemoryStore.prototype.length = function(fn) {
fn(null, Object.keys(this.sessions).length);
};
MemoryStore.length(function(len) {
console.log('sessions:'+len);
});
Use the Store.length(fn) method. In the default Connect memory storage, it's written like this:
MemoryStore.prototype.length = function(fn) {
fn(null, Object.keys(this.sessions).length);
};
So you would call it like this:
store.length(function(len) {
// we have len number of sessions
});
I am well aware of how old this post is but I thought I would share my way, as this comes up as the top result as I was trying to figure it out.
This what I did and it seems to be working.
So if you are using MySQLStore & Express Session you can approach it like this,
Add activeUsers to your options(app/index.js):
var options = {
host: process.env.DB_HOST,
port: 3306,
user: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME,
activeUsers: 0
};
On your login.js add:
req.sessionStore.options.userCount += 1
And on your logout:
req.sessionStore.options.userCount += 1
Now I am not sure if on session timeout if this will return back to 0 or not, but I would assume that it does. And then just create a app.local that refers to the userSession count
Related
This is a little hard articulate so I hope my title isn't too terrible.
I have a frontend/backend React/Node.js(REST API) Web app that I want to add Redis support to for storing retrieving app global settings and per-user specific settings (like language preference, last login, etc... simple stuff) So I was considering adding a /settings branch to my backend REST API to push/pull this information from a redis instance.
This is where my Node.js inexperience comes through. I'm looking at using the ioredis client and it seems too easy. If I have a couple of helpers (more than one .js which will call upon redis) will constructing the client as a const in each be safe to do? Or is there another recommended approach to reusing a single instance of it be the way to go?
Here's a sample of what I'm thinking of doing. Imagine if I had 3 helper modules that require access to the redis client. Should I declare them as const in each? Or centralize them in a single helper module, and get the client from it? Is there a dis-advantage to doing either?
const config = require('config.json');
const redis_url = config.redis_url;
//redis setup
const Redis = require('ioredis');
const redis = new Redis(redis_url);
module.exports = {
test
}
async function test(id) {
redis.get(id, function (err, result) {
if (err) {
console.error(err);
throw(err);
} else {
return result;
}
});
Thank you.
If no redis conflicts...
If the different "helper" modules you are referring to have no conflicts when interacting with redis, such as overwriting / using the same redis keys, then I can't see any reason not to use the same redis instance (as outlined by garlicman) and export this to the different modules in which it is used.
Otherwise use separate redis databases...
If you do require separate redis database connections, redis ships with 16 databases so you can specify which to connect to when creating a new instance - see below:
const redis = new Redis({ // SET UP CONFIG FOR CONNECTION TO REDIS
port: 6379, // Redis port
host: 127.0.0.1, // Redis host
family: 4, // 4 (IPv4) or 6 (IPv6)
db: 10, // Redis database to connect to
});
Normally what I would do (in Java say) is implement any explicit class with singleton access the hold the connection and any connection error/reconnect handling.
All modules in Node.js are already singletons I believe, but what I will probably go with will be a client class to hold it and my own access related methods. Something like:
const config = require('config.json');
const Redis = require("ioredis");
class Redis {
constructor(){
client = new Redis(config.redis_url);
}
get(key) {
return this.client.get(key);
}
set(key, value, ttl) {
let rp;
if (ttl === 0) {
rp = this.client.set(key, value);
}
else {
rp = this.client.set(key, value)
.then(function(res) {
this.client.expire(key, ttl);
});
}
return rp;
}
}
module.exports = new Redis;
I'll probably include a data_init() method to check and preload an initial key/value structure on first connect.
I'm trying to create an API using nodeJS, express and azure-mobile-apps to do some data synchronisation between an Ionic3 mobile app (which use an SQLite local database) and a Microsoft SQL Database.
My API has to create a synchronisation connection for each mobile application. Each application will be linked to a distant database. For example, if user_01 wants to synchronise his data, he's going to be linked to his client_01 database. So each time it'll have to, the API will create a new process running on a different port.
here is an example : https://zupimages.net/up/19/36/szhu.png
The problem is that i'm not able to create more than one connection with azure-mobile-apps. The first one always works, but the second, third etc are still using the first connection that i have instantiated. I've looked into the app stack and everything seems fine.
Is that an issue with azure-mobile-app, or did I misunderstand something with express ?
Thanks for your responses !
var azureMobileApps = require('azure-mobile-apps');
var express = require('express');
module.exports = {
async createConnection(client) {
try {
let app = express();
mobileApp = azureMobileApps({
homePage: true,
swagger: true,
data: {
server: '****',
user: client.User,
password: client.Password,
port: '1443',
database: client.Database,
provider: 'mssql',
dynamicSchema: false,
options: {
encrypt: false
}
}
});
await mobileApp.tables.import('./tables');
await mobileApp.tables.initialize();
app.listen(global.portCounter);
app.use(mobileApp);
console.log(app._router.stack);
console.log('Listening on port ',global.portCounter);
global.portCounter++;
} catch (error) {
console.log(error);
}
}
}
It's working now. The thing is, it's impossible to do multiple connection with the azure-mobile-apps SDK for nodeJS.
I had to use worker-thread which seems to isolate the memory in a sub-proccess.
Hope it can help somebody one day
Let's say I do:
eval(
db_config = {
host: 'localhost',
user: 'root',
database: 'forum',
password: 'test'
}
);
var gamefunctions = require('gamefunctions.js');
I can use db_config anywhere inside gamefunctions.js without having to pass it through a parameter. That's pretty neat. But, is this bad practice?
Reason I ask this is because if I do:
var db_config = {
host: 'localhost',
user: 'root',
database: 'forum',
password: 'test'
}
var gamefunctions = require('gamefunctions.js');
db_config becomes undefined anytime I use it in gamefunctions.js. And I would have to pass it through a parameter on each different function which just seems like evaling it first would save time and code, any downside to this?
Does eval basically just define the variables in a global scope for you, so they can be used in any file in nodejs?
You're doing 2 things wrong and there's much more elegant solution to this.
To explain what you're doing wrong, first is the use of globals. Second is that you're storing sensitive information in your code - your database password! And besides, it won't be very portable. Suppose you want to run it on another machine that has some other database credentials you'll end up changing your code unnecessarily.
You need to store it as environment variables. And if you end up hosting it some environments automatically have those set for you so you could use them in your app. For example openshift would have an $OPENSHIFT_MONGODB_DB_HOST that it tells you to use in your app to connect to its database.
And you need to create a separate file to store your db_config which you can require from other files.
So you might create a db_config.js which would look like this
var config = {};
config.host = process.env.HOST || 'localhost';
config.user = process.env.USER || 'root';
config.password = process.env.password;
module.exports = config;
Then you can safely just pass it the sensitive information like password from console
$ password=pass
$ node index.js
And as for having that information in your gamefunctions.js all you gotta do is require it
var db_config = require('./db_config');
Node.js is my first backend language and I am at the point where I am asking myself "where do I put the database connection information?".
There is a lot of good information regarding this issue. Unfortunately for me all the examples are in PHP. I get the ideas but I am not confident enough to replicate it in Node.js.
In PHP you would put the information in a config file outside the web root, and include it when you need database data.
How would you do this in Node.js? using the Express.js framework.
So far I have this:
var express = require('express'), app = express();
var mysql = require('mysql');
app.get('/', function(req,res) {
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'store'
});
var query = connection.query('SELECT * from customers where email = "deelo42#gmail.com"');
query.on('error', function(err) {
throw err;
});
query.on('fields', function(fields) {
console.log('this is fields');
});
query.on('result', function(row) {
var first = row.first_name;
var last = row.last_name;
res.render('index.jade', {
title: "My first name is " + first,
category: "My last name is " + last
});
});
});
app.listen(80, function() {
console.log('we are logged in');
});
As you can see I have a basic express application with 1 GET route. This route sets off the function to go to the database and pull out information based on an email address.
At the top of the GET route is the database connection information. Where do I put that? How do I call it? How do I keep it out of web root, and include it like PHP ? Can you please show me in a working example. Thanks!
I use the Express Middleware concept for same and that gives me nice flexibility to manage files.
I am writing a detailed answer, which includes how i am use the config params in app.js to connect to DB.
So my app structure looks something this:
How i connect to DB? (I am using MongoDB, mongoose is ORM, npm install mongoose)
var config = require('./config/config');
var mongoose = require("mongoose");
var connect = function(){
var options = {
server: {
socketOptions:{
keepAlive : 1
}
}
};
mongoose.connect(config.db,options);
};
connect();
under the config folder i also have 'env' folder, which stores the environment related configurations in separate files such as development.js, test.js, production.js
Now as the name suggests, development.js stores the configuration params related to my development environment and same applies to the case of test and production. Now if you wish you can have some more configuration setting such as 'staging' etc.
project-name/config/config.js
var path = require("path");
var extend = require("util")._extend;
var development = require("./env/development");
var test = require("./env/test");
var production = require("./env/production");
var defaults = {
root: path.normalize(__dirname + '/..')
};
module.exports = {
development: extend(development,defaults),
test: extend(test,defaults),
production: extend(production,defaults)
}[process.env.NODE_ENV || "development"]
project-name/config/env/test.js
module.exports = {
db: 'mongodb://localhost/mongoExpress_test'
};
Now you can make it even more descriptive by breaking the URL's into, username, password, port, database, hostname.
For For more details have a look at my repo, where you can find this implementation, in fact now in all of my projects i use the same configuration.
If you are more interested then have a look at Mean.js and Mean.io, they have some better ways to manage all such things. If you are beginner i would recommend to keep it simple and get things going, once you are comfortable, you can perform magic on your own. Cheers
I recommend the 12-factor app style http://12factor.net which keeps all of this in env vars. You never should have this kind of information hard-coded or in the app source-code / repo, so you can reuse it in different environments or even share it publicly without breaking security.
However, since there are lots of environment vars, I tend to keep them together in a single env.js like the previous responder wrote - although it is not in the source code repo - and then source it with https://www.npmjs.org/package/dotenv
An alternative is to do it manually and keep it in, e.g. ./env/dev.json and just require() the file.
Any of these works, the important point is to keep all configuration information separate from code.
I agree with the commenter, put it in a config file. There is no ultimate way, but nconf is also one of my favourites.
The important best practise is that you keep the config separate if you have a semi-public project, so your config file will not overwrite other developers.
config-sample.json (has to be renamed and is tracked with for example git)
config.json (not tracked / ignored by git)
tl:dr;
I want to provide the database object to my models and controllers in ExpressJS. How should I do this?
Longer explanation:
My background is in working with Codeigniter and the active-record implementation it has. I have seen other example Node implementations (the mean-stack for instance), however, I was looking to get a site something simple, low-level and that I understood from the ground-up.
The problems is that I don't know express well enough to understand how I should be passing objects around. So I have rounting, db connections and pages rendering all well. However, I am unsure about DB connections being provided to the actual controllers or models.
So, the setup I presently have is:
App.js:
...
//Start the database
var Db = require('mysql-activerecord');
var db = new Db.Adapter({
server: 'localhost',
username: 'root',
password: '********',
database: 'test'
});
// }}}
...
require('./config/routes')(app);
And for config/routes.js
2 /*
3 Exporting variable:
4 #param app The express App
5 */
6
7
8 module.exports = function(app) {
9
10 //Home route
11 var index = require('../server/controllers/index');
12 app.get('/', index.render);
13
14 }
15
So...
The question is perhaps more stylistic than technical. My questions are:
Am I thinking about this the right way?
How would you recommend going about connecting this? Should I use 'require(../..)' in the controllers or is there a more elegant solution?
You can pass the db object to your routes.js (or any other required file you make) file as well:
require('./config/routes')({ app: app, db: db });