diff --git a/index.js b/index.js index 464c709..c9044bd 100644 --- a/index.js +++ b/index.js @@ -45,6 +45,14 @@ module.exports = function(opts, app){ throw new TypeError('app instance required: `session(opts, app)`'); } + // setup encoding/decoding + if (!(typeof opts.encode === 'function')) { + opts.encode = encode + } + if (!(typeof opts.decode === 'function')) { + opts.decode = decode + } + // to pass to Session() app.context.sessionKey = opts.key; @@ -63,7 +71,7 @@ module.exports = function(opts, app){ try { // make sure sessionOptions exists initSessionOptions(this, opts); - var obj = decode(json); + var obj = opts.decode(json); if (typeof opts.valid === 'function' && !opts.valid(this, obj)) { // valid session value fail, ignore this session sess = new Session(this); @@ -72,7 +80,7 @@ module.exports = function(opts, app){ } else { sess = new Session(this, obj); // make prev a different object from sess - json = decode(json); + json = opts.decode(json); } } catch (err) { // backwards compatibility: @@ -278,9 +286,14 @@ Session.prototype.save = function(){ json._expire = maxAge + Date.now(); json._maxAge = maxAge; - json = encode(json); - debug('save %s', json); - ctx.cookies.set(key, json, opts); + try { + json = opts.encode(json); + debug('save %s', json); + ctx.cookies.set(key, json, opts); + } catch (e) { + debug('encode %j error: %s', json, err); + ctx.cookies.set(key, '', opts); + } }; /** diff --git a/test/test.js b/test/test.js index e7d4900..4290409 100644 --- a/test/test.js +++ b/test/test.js @@ -527,6 +527,55 @@ describe('Koa Session', function(){ }); }) }) + + describe('when options.encode and options.decode are functions', function () { + describe('they are used to encode/decode stored cookie values', function () { + it('should work', function (done) { + var encodeCallCount = 0 + var decodeCallCount = 0 + + function encode(data) { + ++encodeCallCount + return JSON.stringify({enveloped: data}) + } + function decode(data) { + ++decodeCallCount + return JSON.parse(data).enveloped + } + + var app = koa(); + app.keys = ['a', 'b']; + app.use(session({ + encode: encode, + decode: decode + }, app)); + + app.use(function * () { + this.session.counter = (this.session.counter || 0) + 1 + this.body = this.session + return + }) + + request(app.callback()) + .get('/') + .expect(function () { encodeCallCount.should.above(0, 'encode was not called'); }) + .expect(200, function (err, res) { + should.not.exist(err) + res.body.counter.should.equal(1, 'expected body to be equal to session.counter') + var cookies = res.headers['set-cookie'].join(';'); + request(app.callback()) + .get('/') + .set('Cookie', cookies) + .expect(function () { decodeCallCount.should.be.above(1, 'decode was not called'); }) + .expect(200, function (err, res) { + should.not.exist(err); + res.body.counter.should.equal(2); + done(); + }) + }) + }) + }) + }) }) function App(options) {