Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

sessions

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sessions - npm Package Compare versions

Comparing version 0.0.1 to 0.0.2-1

.travis.yml

12

examples/server.js
var http = require("http"),
sessions = require("../lib/sessions"),
handler = new sessions(); // defaults to memory store
handler = new sessions();
http.createServer(function (req, res) {
var session = handler.httpRequest(req, res);
handler.httpRequest(req, res, function (err, session) {
if (err) {
return res.end("session error");
}
console.log("[%s] > %s", session.uid(), req.url);
console.log("[%s] > %s", session.uid(), req.url);
res.end(req.url);
res.end(req.url);
});

@@ -12,0 +16,0 @@ }).listen(1337, function () {

@@ -19,13 +19,23 @@ /**

var sessions = require("../lib/sessions"),
Sessions = new sessions(sessions.stores.memory, { expires: 5 });
var session1 = Sessions.create("session1"),
session2 = Sessions.create("session2"),
session3 = Sessions.create(/* name automatically generated */).refresh(8),
Sessions = new sessions(sessions.stores.memory, { expires: 5 }),
intervalId = null;
console.log("* created session '%s'", session1.uid());
console.log("* created session '%s'", session2.uid());
console.log("* created session '%s'", session3.uid());
Sessions.create("session1", function (_, session1) {
console.log("* created session '%s'", session1.uid());
intervalId = setInterval(function () {
session1.refresh();
}, 1000);
Sessions.create("session2", function (_, session2) {
console.log("* created session '%s'", session2.uid());
Sessions.create(/* name automatically generated */ function (_, session3) {
console.log("* created session '%s'", session3.uid());
session3.refresh(8);
});
});
});
Sessions.on("expired", function (uid) {

@@ -40,6 +50,2 @@ console.log("! session expired:", uid);

console.log("* checking session expiration..");
});
intervalId = setInterval(function () {
session1.refresh();
}, 1000);
});

@@ -12,3 +12,3 @@ var util = require("util"),

this.opts = opts || {};
this.sessions = {};
this._currentSessions = 0;

@@ -30,9 +30,15 @@ this._checkTimeoutId = null;

Sessions.prototype.total = function () {
return Object.keys(this.sessions).length;
return this._currentSessions;
};
Sessions.prototype.get = function (uid) {
if (this.sessions.hasOwnProperty(uid)) {
return this.sessions[uid];
}
return null;
Sessions.prototype.get = function (uid, cb) {
var sessions = this;
this.store.get(uid, function (err, meta, data) {
if (err) {
return cb(err);
}
return cb(null, buildSessionUtils(uid, meta, data, sessions.store, sessions.opts.expires, sessions), sessions);
});
return this;
};

@@ -42,3 +48,5 @@ Sessions.prototype.create = function () {

uid = null,
data = {};
data = {},
meta = { expires: Date.now() + (this.opts.expires * 1000) },
cb = null;

@@ -53,2 +61,5 @@ for (var i = 0; i < arguments.length; i++) {

break;
case "function":
cb = arguments[i];
break;
}

@@ -61,61 +72,15 @@ }

if (this.store.add(uid, {
data: data,
expires: Date.now() + (this.opts.expires * 1000)
}) === false) {
return null;
}
this.store.add(uid, meta, data, function (err, data) {
if (err) {
return cb(err);
}
this.sessions[uid] = {
get: function (key) {
if (typeof key == "undefined") {
return sessions.store.get(uid).data;
}
return sessions.store.get(uid).data[key] || null;
},
set: function (key, value) {
if (typeof key == "object") {
sessions.store.set(uid, key);
} else {
var o = {};
o[key] = value;
sessions.store.set(uid, o);
}
return this;
},
refresh: function (expires) {
sessions.store.set(uid, {
expires: Date.now() + ((expires || sessions.opts.expires) * 1000)
});
return this;
},
expire: function () {
sessions.store.remove(uid);
delete sessions.sessions[uid];
sessions.emit("expired", uid, true);
return this;
},
uid: function () {
return uid;
},
expires: function () {
var sess = sessions.store.get(uid);
return (sess ? sess.expires : null);
if (sessions._checkTimeoutId === null) {
sessions._checkTimeoutId = setTimeout(function () {
sessions.checkExpiration();
}, (sessions.opts.expires + 1) * 1000);
}
};
if (this._checkTimeoutId === null) {
this._checkTimeoutId = setTimeout((function (me) {
return function () {
me.checkExpiration();
};
})(this), (this.opts.expires + 1) * 1000);
}
return this.sessions[uid];
return cb(null, buildSessionUtils(uid, meta, data, sessions.store, sessions.opts.expires, sessions), sessions);
});
};

@@ -125,62 +90,64 @@ Sessions.prototype.uid = function () {

};
Sessions.prototype.httpRequest = function (req, res) {
var cookies = {}, session;
Sessions.prototype.httpRequest = function (req, res, cb) {
var cookies = parseCookies(req),
sessions = this;
req.headers.cookie && req.headers.cookie.split(";").forEach(function (param) {
var part = param.split("=", 2);
cookies[part[0].toLowerCase()] = part[1] || true;
});
if (!cookies.hasOwnProperty("uid")) {
session = this.create();
return this.create(function (err, session) {
if (err) {
return cb(err);
}
setHttpCookie(res, "uid", session.uid(), session.expires(), this.opts.path, this.opts.domain);
setHttpCookie(res, "uid", session.uid(), session.expires(), sessions.opts.path, sessions.opts.domain);
return session;
return cb(null, session, sessions);
});
}
session = this.get(cookies.uid);
if (session === null) {
session = this.create();
console.log("creating new session..");
this.get(cookies.uid, function (err, session) {
if (err) {
return sessions.create(function (err, session) {
if (err) {
return cb(err);
}
setHttpCookie(res, "uid", session.uid(), session.expires(), this.opts.path, this.opts.domain);
}
setHttpCookie(res, "uid", session.uid(), session.expires(), sessions.opts.path, sessions.opts.domain);
return session;
return cb(null, session);
});
} else {
return cb(null, session, sessions);
}
});
return this;
};
Sessions.prototype.checkExpiration = function () {
var uids = this.store.uids(), sess,
i = 0, l = uids.length, dt = Date.now(),
next_expires = null;
var sessions = this,
conf = { dt: Date.now(), next: null };
this.emit("expirecheck");
this.store.uids(function (err, uids) {
if (err) {
return;
}
for (; i < l; i++) {
sess = this.store.get(uids[i]);
var sess, i = 0, l = uids.length, missing = l;
if (sess.expires <= dt) {
this.emit("expired", uids[i], false);
this.store.remove(uids[i]);
continue;
}
if (next_expires === null) {
next_expires = sess.expires;
continue;
}
if (sess.expires < next_expires) {
next_expires = sess.expires;
}
}
sessions.emit("expirecheck");
if (next_expires !== null) {
i = (next_expires - Date.now()) / 1000;
for (; i < l; i++) {
checkSessionExpiration(sessions, uids[i], conf, function () {
missing -= 1;
if (missing == 0) {
if (conf.next !== null) {
i = (conf.next - Date.now()) / 1000;
this._checkTimeoutId = setTimeout((function (me) {
return function () {
me.checkExpiration();
};
})(this), (i > 0 ? (i + 1) : 10) * 1000);
}
sessions._checkTimeoutId = setTimeout(function () {
sessions.checkExpiration();
}, (i > 0 ? (i + 1) : 10) * 1000);
}
}
});
}
});
};

@@ -192,2 +159,3 @@

module.exports.stores = sessionStores;
module.exports.parseCookies = parseCookies;

@@ -208,8 +176,45 @@ function initStores() {

function parseCookies(req) {
var cookies = {};
req.headers.cookie && req.headers.cookie.split(";").forEach(function (param) {
var part = param.split("=", 2);
cookies[part[0].toLowerCase()] = part[1] || true;
});
return cookies;
}
function checkSessionExpiration(sessions, uid, conf, cb) {
sessions.store.get(uid, function (err, sess) {
if (err) return cb();
if (sess.expires <= conf.dt) {
sessions.emit("expired", uid, false);
sessions.store.remove(uid);
return cb();
}
if (conf.next === null) {
conf.next = sess.expires;
return cb();
}
if (sess.expires < conf.next) {
conf.next = sess.expires;
}
return cb();
});
}
function setHttpCookie(res, key, value, expires, path, domain) {
var cookie = [], dt;
cookie.push(key + "=" + value);
if (domain !== null) {
cookie.push("domain=" + domain);
}
if (path !== null) {
cookie.push("path=" + path);
}

@@ -229,1 +234,42 @@ if (expires !== null) {

}
function buildSessionUtils(uid, meta, data, store, expires, sessions) {
return {
get: function (key) {
if (typeof key == "undefined") {
return data;
}
return data[key] || null;
},
set: function (key, value, cb) {
if (typeof key == "object") {
store.set(uid, key, cb);
} else {
var o = {};
o[key] = value;
store.set(uid, o, cb);
}
return this;
},
refresh: function (expire) {
meta.expires = Date.now() + ((expire || expires) * 1000);
store.set(uid, meta, {});
return this;
},
expire: function () {
store.remove(uid);
sessions.emit("expired", uid, true);
return this;
},
uid: function () {
return uid;
},
expires: function () {
return meta.expires;
}
};
}
function MemoryStore() {
this.store = {};
}
MemoryStore.prototype.add = function (uid, data) {
if (this.store.hasOwnProperty(uid)) {
return false;
MemoryStore.prototype.add = function (uid) {
var meta = null, data = {}, cb = null, success = false;
for (var i = 1; i < arguments.length; i++) {
switch (typeof arguments[i]) {
case "function":
cb = arguments[i];
break;
case "object":
if (meta === null) {
meta = arguments[i];
} else {
data = arguments[i];
}
break;
}
}
this.store[uid] = data || {};
if (meta === null) {
meta = {};
}
return true;
if (!this.store.hasOwnProperty(uid)) {
this.store[uid] = { meta: meta, data: data };
success = true;
}
if (cb !== null) {
if (success) {
cb(null, meta, data);
} else {
cb(new Error("could not add uid"));
}
}
return this;
};
MemoryStore.prototype.uids = function () {
return Object.keys(this.store);
MemoryStore.prototype.uids = function (cb) {
cb(null, Object.keys(this.store));
return this;
};
MemoryStore.prototype.set = function (uid, data) {
MemoryStore.prototype.set = function (uid, meta, data, cb) {
if (!this.store.hasOwnProperty(uid)) {
return false;
typeof cb == "function" && cb(new Error("uid not found"));
return this;
}
for (k in meta) {
this.store[uid].meta[k] = meta[k];
}
for (k in data) {
this.store[uid][k] = data[k];
this.store[uid].data[k] = data[k];
}
return true;
typeof cb == "function" && cb(null);
return this;
};
MemoryStore.prototype.get = function (uid, key) {
MemoryStore.prototype.get = function (uid) {
var key = null, cb = null;
for (var i = 1; i < arguments.length; i++) {
switch (typeof arguments[i]) {
case "string":
key = arguments[i];
break;
case "function":
cb = arguments[i];
break;
}
}
if (cb === null) {
throw new Error("missing callback");
}
if (this.store.hasOwnProperty(uid)) {
if (typeof key == "undefined") {
return this.store[uid];
if (key === null) {
cb(null, this.store[uid].meta, this.store[uid].data);
} else {
cb(null, this.store[uid].data.hasOwnProperty(key) ? this.store[uid].data[key] : null);
}
return this.store[uid].hasOwnProperty(key) ? this.store[uid][key] : null;
} else {
cb(new Error("uid not found"));
}
return null;
return this;
};
MemoryStore.prototype.remove = function () {
var items = Array.prototype.slice.apply(arguments),
uid = items.shift();
uid = items.shift(), cb = items.pop();
if (!this.store.hasOwnProperty(uid)) {
return false;
typeof cb == "function" && cb(new Error("uid not found"));
return this;
}
if (items.length == 0) {

@@ -50,5 +111,8 @@ delete this.store[uid];

}
return true;
typeof cb == "function" && cb(null);
return this;
};
module.exports = MemoryStore;
{
"name" : "sessions",
"version" : "0.0.1",
"version" : "0.0.2-1",
"description" : "NodeJS session management",

@@ -29,2 +29,2 @@ "keywords" : [ "session", "cookie" ],

}
}
}
var vows = require("vows"),
assert = require("assert"),
memoryStore = require("../lib/sessions").stores.memory,
memoryStore = require("../lib/store/memory"),
store = new memoryStore(),
testMeta = { meta: "test" },
dup_id = "dupid";
vows.describe("memory store").addBatch({
"a clean memory store": {
topic: new memoryStore(),
"should have no uids initially": function (topic) {
assert.isArray(topic.uids());
assert.equal(topic.uids().length, 0);
"getting initial uids": {
topic: function () {
store.uids(this.callback);
},
"add duplicated uids should not be possible": function (topic) {
assert.isTrue(topic.add(dup_id, { dup: false }));
assert.isFalse(topic.add(dup_id, { dup: true }));
"should come empty": function (uids) {
assert.isArray(uids);
assert.equal(uids.length, 0);
}
}
}).addBatch({
"adding an uid": {
topic: function () {
store.add(dup_id, testMeta, { dup: false }, this.callback);
},
"changing current uid data is possible": function (topic) {
assert.isTrue(topic.set(dup_id, { dup: true }));
"should be ok": function (err, meta, data) {
assert.isNull(err);
assert.deepEqual(meta, testMeta);
assert.deepEqual(data, { dup: false });
}
}
}).addBatch({
"but adding again": {
topic: function () {
store.add(dup_id, testMeta, { dup: true }, this.callback);
},
"changing unknown uid data is impossible": function (topic) {
assert.isFalse(topic.set(dup_id + "-unknown", { dup: true }));
"should not be ok": function (err, data) {
assert.isNotNull(err);
}
}
}).addBatch({
"changing current uid data": {
topic: function () {
store.set(dup_id, {}, { dup: true }, this.callback);
},
"previous uid data should be ok": function (topic) {
assert.isTrue(topic.get(dup_id, "dup"));
assert.deepEqual(topic.get(dup_id), { dup: true });
"should be ok": function (err, _) {
assert.isNull(err);
}
}
}).addBatch({
"changing unknown uid data": {
topic: function () {
store.set(dup_id + "-unknown", {}, { dup: true }, this.callback);
},
"previous uid unknown data should return null": function (topic) {
assert.isNull(topic.get(dup_id, "unknown key"));
"should not be ok": function (err, _) {
assert.isNotNull(err);
}
}
}).addBatch({
"previous uid data": {
topic: function () {
store.get(dup_id, this.callback);
},
"only one uid should be present now": function (topic) {
assert.isArray(topic.uids());
assert.equal(topic.uids().length, 1);
"should be ok": function (err, meta, data) {
assert.isNull(err);
assert.deepEqual(meta, testMeta);
assert.deepEqual(data, { dup: true });
}
}
}).addBatch({
"previous uid unknown data": {
topic: function () {
store.get(dup_id + "-unknown", this.callback);
},
"removing a property should be ok": function (topic) {
assert.isTrue(topic.remove(dup_id, "dup"));
assert.isNull(topic.get(dup_id, "dup"));
assert.isEmpty(topic.get(dup_id));
"should return error": function (err, _) {
assert.isNotNull(err);
}
}
}).addBatch({
"the total uids saved": {
topic: function () {
store.uids(this.callback);
},
"removing an uid should be ok": function (topic) {
assert.isTrue(topic.remove(dup_id));
assert.isNull(topic.get(dup_id, "dup"));
assert.isNull(topic.get(dup_id));
"should now be one": function (uids) {
assert.isArray(uids);
assert.equal(uids.length, 1);
}
}
}).addBatch({
"removing a property": {
topic: function () {
store.remove(dup_id, "dup", this.callback);
},
"no uids should be in store now": function (topic) {
assert.isArray(topic.uids());
assert.equal(topic.uids().length, 0);
"should be ok": function (err, _) {
assert.isNull(err);
}
}
}).addBatch({
"removing an uid": {
topic: function () {
store.remove(dup_id, this.callback);
},
"should be ok": function (err, _) {
assert.isNull(err);
}
}
}).addBatch({
"the total uids saved": {
topic: function () {
store.uids(this.callback);
},
"should now be zero": function (uids) {
assert.isArray(uids);
assert.equal(uids.length, 0);
}
}
}).export(module);

@@ -8,3 +8,3 @@ var vows = require("vows"),

vows.describe("sessions").addBatch({
"a clean session handler": {
"a session handler": {
topic: new sessions(),

@@ -14,19 +14,19 @@ "should have no sessions initially": function (topic) {

},
"should be able to create a new session": function (topic) {
session = topic.create(sessid);
assert.isObject(session);
assert.isNotNull(session);
},
"new session should have no data": function (topic) {
assert.isObject(session.get());
assert.isNull(session.get("undefined"));
},
"new session should have defined uid": function (topic) {
assert.strictEqual(session.uid(), sessid);
},
"expiring session should clean it": function (topic) {
session.expire();
assert.strictEqual(topic.total(), 0);
"creating a new session": {
topic: function (sessions) {
sessions.create(sessid, this.callback);
},
"should be ok": function (err, session) {
assert.isNull(err);
assert.isObject(session);
assert.isFunction(session.get);
assert.isFunction(session.set);
assert.isFunction(session.refresh);
assert.isFunction(session.expire);
assert.isFunction(session.expires);
assert.isFunction(session.uid);
},
"uid should be the same used": function (err, session) {
assert.equal(session.uid(), sessid);
}
}

@@ -33,0 +33,0 @@ },

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc