Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added auto sub domain feature for cookies #311

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
unreleased
==========

* Methods are no longer enumerable on `req.session` object

1.13.1 / 2016-01-29
===================

* deps: parseurl@~1.3.1
- perf: enable strict mode
* deps: uid-safe@~2.1.0
Expand Down
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -412,90 +412,122 @@ The following modules implement a session store that is compatible with this
module. Please make a PR to add additional modules :)

[![★][cassandra-store-image] cassandra-store][cassandra-store-url] An Apache Cassandra-based session store.

[cassandra-store-url]: https://www.npmjs.com/package/cassandra-store
[cassandra-store-image]: https://img.shields.io/github/stars/webcc/cassandra-store.svg?label=%E2%98%85

[![★][cluster-store-image] cluster-store][cluster-store-url] A wrapper for using in-process / embedded
stores - such as SQLite (via knex), leveldb, files, or memory - with node cluster (desirable for Raspberry Pi 2
and other multi-core embedded devices).

[cluster-store-url]: https://www.npmjs.com/package/cluster-store
[cluster-store-image]: https://img.shields.io/github/stars/coolaj86/cluster-store.svg?label=%E2%98%85

[![★][connect-azuretables-image] connect-azuretables][connect-azuretables-url] An [Azure Table Storage](https://azure.microsoft.com/en-gb/services/storage/tables/)-based session store.

[connect-azuretables-url]: https://www.npmjs.com/package/connect-azuretables
[connect-azuretables-image]: https://img.shields.io/github/stars/mike-goodwin/connect-azuretables.svg?label=%E2%98%85

[![★][connect-couchbase-image] connect-couchbase][connect-couchbase-url] A [couchbase](http://www.couchbase.com/)-based session store.

[connect-couchbase-url]: https://www.npmjs.com/package/connect-couchbase
[connect-couchbase-image]: https://img.shields.io/github/stars/christophermina/connect-couchbase.svg?label=%E2%98%85

[![★][connect-dynamodb-image] connect-dynamodb][connect-dynamodb-url] A DynamoDB-based session store.

[connect-dynamodb-url]: https://github.com/ca98am79/connect-dynamodb
[connect-dynamodb-image]: https://img.shields.io/github/stars/ca98am79/connect-dynamodb.svg?label=%E2%98%85

[![★][connect-mssql-image] connect-mssql][connect-mssql-url] A SQL Server-based session store.

[connect-mssql-url]: https://www.npmjs.com/package/connect-mssql
[connect-mssql-image]: https://img.shields.io/github/stars/patriksimek/connect-mssql.svg?label=%E2%98%85

[![★][connect-monetdb-image] connect-monetdb][connect-monetdb-url] A MonetDB-based session store.

[connect-monetdb-url]: https://www.npmjs.com/package/connect-monetdb
[connect-monetdb-image]: https://img.shields.io/github/stars/MonetDB/npm-connect-monetdb.svg?label=%E2%98%85

[![★][connect-mongo-image] connect-mongo][connect-mongo-url] A MongoDB-based session store.

[connect-mongo-url]: https://www.npmjs.com/package/connect-mongo
[connect-mongo-image]: https://img.shields.io/github/stars/kcbanner/connect-mongo.svg?label=%E2%98%85

[![★][connect-mongodb-session-image] connect-mongodb-session][connect-mongodb-session-url] Lightweight MongoDB-based session store built and maintained by MongoDB.

[connect-mongodb-session-url]: https://www.npmjs.com/package/connect-mongodb-session
[connect-mongodb-session-image]: https://img.shields.io/github/stars/mongodb-js/connect-mongodb-session.svg?label=%E2%98%85

[![★][connect-pg-simple-image] connect-pg-simple][connect-pg-simple-url] A PostgreSQL-based session store.

[connect-pg-simple-url]: https://www.npmjs.com/package/connect-pg-simple
[connect-pg-simple-image]: https://img.shields.io/github/stars/voxpelli/node-connect-pg-simple.svg?label=%E2%98%85

[![★][connect-redis-image] connect-redis][connect-redis-url] A Redis-based session store.

[connect-redis-url]: https://www.npmjs.com/package/connect-redis
[connect-redis-image]: https://img.shields.io/github/stars/tj/connect-redis.svg?label=%E2%98%85

[![★][connect-memcached-image] connect-memcached][connect-memcached-url] A memcached-based session store.

[connect-memcached-url]: https://www.npmjs.com/package/connect-memcached
[connect-memcached-image]: https://img.shields.io/github/stars/balor/connect-memcached.svg?label=%E2%98%85

[![★][connect-session-knex-image] connect-session-knex][connect-session-knex-url] A session store using
[Knex.js](http://knexjs.org/), which is a SQL query builder for PostgreSQL, MySQL, MariaDB, SQLite3, and Oracle.

[connect-session-knex-url]: https://www.npmjs.com/package/connect-session-knex
[connect-session-knex-image]: https://img.shields.io/github/stars/llambda/connect-session-knex.svg?label=%E2%98%85

[![★][connect-session-sequelize-image] connect-session-sequelize][connect-session-sequelize-url] A session store using
[Sequelize.js](http://sequelizejs.com/), which is a Node.js / io.js ORM for PostgreSQL, MySQL, SQLite and MSSQL.

[connect-session-sequelize-url]: https://www.npmjs.com/package/connect-session-sequelize
[connect-session-sequelize-image]: https://img.shields.io/github/stars/mweibel/connect-session-sequelize.svg?label=%E2%98%85

[![★][express-mysql-session-image] express-mysql-session][express-mysql-session-url] A session store using native
[MySQL](https://www.mysql.com/) via the [node-mysql](https://github.com/felixge/node-mysql) module.

[express-mysql-session-url]: https://www.npmjs.com/package/express-mysql-session
[express-mysql-session-image]: https://img.shields.io/github/stars/chill117/express-mysql-session.svg?label=%E2%98%85

[![★][connect-sqlite3-image] connect-sqlite3][connect-sqlite3-url] A [SQLite3](https://github.com/mapbox/node-sqlite3) session store modeled after the TJ's `connect-redis` store.

[connect-sqlite3-url]: https://www.npmjs.com/package/connect-sqlite3
[connect-sqlite3-image]: https://img.shields.io/github/stars/rawberg/connect-sqlite3.svg?label=%E2%98%85

[![★][express-nedb-session-image] express-nedb-session][express-nedb-session-url] A NeDB-based session store.

[express-nedb-session-url]: https://www.npmjs.com/package/express-nedb-session
[express-nedb-session-image]: https://img.shields.io/github/stars/louischatriot/express-nedb-session.svg?label=%E2%98%85

[![★][level-session-store-image] level-session-store][level-session-store-url] A LevelDB-based session store.

[level-session-store-url]: https://www.npmjs.com/package/level-session-store
[level-session-store-image]: https://img.shields.io/github/stars/scriptollc/level-session-store.svg?label=%E2%98%85

[![★][mssql-session-store-image] mssql-session-store][mssql-session-store-url] A SQL Server-based session store.

[mssql-session-store-url]: https://www.npmjs.com/package/mssql-session-store
[mssql-session-store-image]: https://img.shields.io/github/stars/jwathen/mssql-session-store.svg?label=%E2%98%85

[![★][nedb-session-store-image] nedb-session-store][nedb-session-store-url] An alternate NeDB-based (either in-memory or file-persisted) session store.

[nedb-session-store-url]: https://www.npmjs.com/package/nedb-session-store
[nedb-session-store-image]: https://img.shields.io/github/stars/JamesMGreene/nedb-session-store.svg?label=%E2%98%85

[![★][sequelstore-connect-image] sequelstore-connect][sequelstore-connect-url] A session store using [Sequelize.js](http://sequelizejs.com/).

[sequelstore-connect-url]: https://www.npmjs.com/package/sequelstore-connect
[sequelstore-connect-image]: https://img.shields.io/github/stars/MattMcFarland/sequelstore-connect.svg?label=%E2%98%85

[![★][session-file-store-image] session-file-store][session-file-store-url] A file system-based session store.

[session-file-store-url]: https://www.npmjs.com/package/session-file-store
[session-file-store-image]: https://img.shields.io/github/stars/valery-barysok/session-file-store.svg?label=%E2%98%85

[![★][session-rethinkdb-image] session-rethinkdb][session-rethinkdb-url] A [RethinkDB](http://rethinkdb.com/)-based session store.

[session-rethinkdb-url]: https://www.npmjs.com/package/session-rethinkdb
[session-rethinkdb-image]: https://img.shields.io/github/stars/llambda/session-rethinkdb.svg?label=%E2%98%85

Expand Down
8 changes: 8 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ var Session = require('./session/session')
, Cookie = require('./session/cookie')
, Store = require('./session/store')

var parseDomain = require('parse-domain');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you can, please move this up with the other requires (probably right before the parseUrl one).

// environment

var env = process.env.NODE_ENV;
Expand Down Expand Up @@ -146,6 +147,13 @@ function session(options){
if (cookieOptions.secure === 'auto') {
req.session.cookie.secure = issecure(req, trustProxy);
}

if (cookieOptions.autoSubDomain) {
var parsedDomain = parseDomain(req.headers.host);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of only using req.headers.host directly, we need to actually hook into the mechanisms of Express.js such that it uses the settings and parsing that is in there so people who use "trust proxy" and the like can have the correct domain when using a reverse proxy.

if (parsedDomain && parsedDomain.domain) {
req.session.cookie.domain = '.' + parsedDomain.domain + '.' + parsedDomain.tld;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious here: why is the option called autoSubDomain, but yet this just leaves the parsedDomain.subdomain out of the picture? Perhaps I'm just not understanding what you're trying to do here. If you add the documentation for your feature to the README, I can read that and see if I understand :)

}
}
};

var storeImplementsTouch = typeof store.touch === 'function';
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "express-session",
"version": "1.13.0",
"version": "1.13.1",
"description": "Simple session middleware for Express",
"author": "TJ Holowaychuk <tj@vision-media.ca> (http://tjholowaychuk.com)",
"contributors": [
Expand All @@ -18,7 +18,8 @@
"on-headers": "~1.0.1",
"parseurl": "~1.3.1",
"uid-safe": "~2.1.0",
"utils-merge": "1.0.0"
"utils-merge": "1.0.0",
"parse-domain": "^0.2.1"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use an exact version and order this to be alphabetical (otherwise npm operations will reorganize it, creating unnecessary churn).

},
"devDependencies": {
"after": "0.8.1",
Expand Down
39 changes: 28 additions & 11 deletions session/session.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ function Session(req, data) {
* @api public
*/

Session.prototype.touch = function(){
defineMethod(Session.prototype, 'touch', function touch() {
return this.resetMaxAge();
};
});

/**
* Reset `.maxAge` to `.originalMaxAge`.
Expand All @@ -55,10 +55,10 @@ Session.prototype.touch = function(){
* @api public
*/

Session.prototype.resetMaxAge = function(){
defineMethod(Session.prototype, 'resetMaxAge', function resetMaxAge() {
this.cookie.maxAge = this.cookie.originalMaxAge;
return this;
};
});

/**
* Save the session data with optional callback `fn(err)`.
Expand All @@ -68,10 +68,10 @@ Session.prototype.resetMaxAge = function(){
* @api public
*/

Session.prototype.save = function(fn){
defineMethod(Session.prototype, 'save', function save(fn) {
this.req.sessionStore.set(this.id, this, fn || function(){});
return this;
};
});

/**
* Re-loads the session data _without_ altering
Expand All @@ -85,7 +85,7 @@ Session.prototype.save = function(fn){
* @api public
*/

Session.prototype.reload = function(fn){
defineMethod(Session.prototype, 'reload', function reload(fn) {
var req = this.req
, store = this.req.sessionStore;
store.get(this.id, function(err, sess){
Expand All @@ -95,7 +95,7 @@ Session.prototype.reload = function(fn){
fn();
});
return this;
};
});

/**
* Destroy `this` session.
Expand All @@ -105,11 +105,11 @@ Session.prototype.reload = function(fn){
* @api public
*/

Session.prototype.destroy = function(fn){
defineMethod(Session.prototype, 'destroy', function destroy(fn) {
delete this.req.session;
this.req.sessionStore.destroy(this.id, fn);
return this;
};
});

/**
* Regenerate this request's session.
Expand All @@ -119,7 +119,24 @@ Session.prototype.destroy = function(fn){
* @api public
*/

Session.prototype.regenerate = function(fn){
defineMethod(Session.prototype, 'regenerate', function regenerate(fn) {
this.req.sessionStore.regenerate(this.req, fn);
return this;
});

/**
* Helper function for creating a method on a prototype.
*
* @param {Object} obj
* @param {String} name
* @param {Function} fn
* @private
*/
function defineMethod(obj, name, fn) {
Object.defineProperty(obj, name, {
configurable: true,
enumerable: false,
value: fn,
writable: true
});
};
18 changes: 18 additions & 0 deletions test/session.js
Original file line number Diff line number Diff line change
Expand Up @@ -1420,6 +1420,24 @@ describe('session()', function(){
});
})

it('should not have enumerable methods', function (done) {
var app = express()
.use(session({ secret: 'keyboard cat', cookie: { maxAge: min }}))
.use(function(req, res, next) {
req.session.foo = 'foo';
req.session.bar = 'bar';
var keys = [];
for (var key in req.session) {
keys.push(key);
}
res.end(keys.sort().join(','));
});

request(app)
.get('/')
.expect(200, 'bar,cookie,foo', done);
});

describe('.destroy()', function(){
it('should destroy the previous session', function(done){
var app = express()
Expand Down