From 0c2c594ec5d0ca461cd2032226c976ccbc684458 Mon Sep 17 00:00:00 2001 From: "tree.xie" Date: Sat, 8 Jul 2017 09:13:01 +0800 Subject: [PATCH 1/2] feat: support options.externalKey --- Readme.md | 7 +++++ index.js | 7 +++++ lib/context.js | 17 ++++++++--- test/externalKey.test.js | 64 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 test/externalKey.test.js diff --git a/Readme.md b/Readme.md index 6108fb9..6c72ebc 100644 --- a/Readme.md +++ b/Readme.md @@ -114,6 +114,13 @@ console.log('listening on port 3000'); If your session store requires data or utilities from context, `opts.ContextStore` is alse supported. `ContextStore` must be a class which claims three instance methods demonstrated above. `new ContextStore(ctx)` will be executed on every request. +### Custom External Key + + External key is used the cookie by default, but you can use `options.externalKey` to customize your own external key methods. `options.externalKey` with two methods: + + - `get(key, opts, ctx)`: get the external key + - `set(key, value, opts, ctx)`: set the external key + ### Session#isNew Returns __true__ if the session is new. diff --git a/index.js b/index.js index 24a7d9d..24fc5b8 100644 --- a/index.js +++ b/index.js @@ -86,6 +86,13 @@ function formatOpts(opts) { assert(is.function(store.destroy), 'store.destroy must be function'); } + const externalKey = opts.externalKey; + + if (externalKey) { + assert(is.function(externalKey.get), 'externalKey.get must be function'); + assert(is.function(externalKey.set), 'externalKey.set must be function'); + } + const ContextStore = opts.ContextStore; if (ContextStore) { assert(is.class(ContextStore), 'ContextStore must be a class'); diff --git a/lib/context.js b/lib/context.js index f7664bf..bbfcc13 100644 --- a/lib/context.js +++ b/lib/context.js @@ -69,9 +69,14 @@ class ContextSession { debug('init from external'); const ctx = this.ctx; const opts = this.opts; - - const externalKey = ctx.cookies.get(opts.key, opts); - debug('get external key from cookie %s', externalKey); + let externalKey; + if (opts.externalKey) { + externalKey = opts.externalKey.get(opts.key, opts, ctx); + debug('get external key from custom %s', externalKey); + } else { + externalKey = ctx.cookies.get(opts.key, opts); + debug('get external key from cookie %s', externalKey); + } if (!externalKey) { // create a new `externalKey` @@ -264,7 +269,11 @@ class ContextSession { changed, rolling: opts.rolling, }); - this.ctx.cookies.set(key, externalKey, opts); + if (opts.externalKey) { + opts.externalKey.set(key, externalKey, opts, this.ctx); + } else { + this.ctx.cookies.set(key, externalKey, opts); + } return; } diff --git a/test/externalKey.test.js b/test/externalKey.test.js new file mode 100644 index 0000000..ed41b64 --- /dev/null +++ b/test/externalKey.test.js @@ -0,0 +1,64 @@ +'use strict'; + +const Koa = require('koa'); +const request = require('supertest'); +const assert = require('assert'); +const session = require('..'); +const store = require('./store'); +const TOKEN_KEY = 'User-Token'; + +describe('Koa Session External Key', () => { + describe('when the external key set/get is invalid', () => { + it('should throw a error', () => { + try { + new App({ + externalKey: {}, + }); + } catch (err) { + assert.equal(err.code, 'ERR_ASSERTION'); + } + }); + }); + + describe('custom get/set external key', () => { + it('should still work', done => { + const app = App(); + + app.use(async function(ctx) { + if (ctx.method === 'POST') { + ctx.session.string = ';'; + ctx.status = 204; + } else { + ctx.body = ctx.session.string; + } + }); + + const server = app.listen(); + + request(server) + .post('/') + .expect(204, (err, res) => { + if (err) return done(err); + const token = res.get(TOKEN_KEY); + request(server) + .get('/') + .set(TOKEN_KEY, token) + .expect(';', done); + }); + }); + }); +}); + +function App(options) { + const app = new Koa(); + app.keys = [ 'a', 'b' ]; + options = options || {}; + options.store = store; + options.key = TOKEN_KEY; + options.externalKey = options.externalKey || { + get: (key, opts, ctx) => ctx.get(key), + set: (key, value, opts, ctx) => ctx.set(key, value), + }; + app.use(session(options, app)); + return app; +} From 16c12174fb9a21c39cc52afb19f62e3b0de85076 Mon Sep 17 00:00:00 2001 From: "tree.xie" Date: Sat, 8 Jul 2017 09:25:15 +0800 Subject: [PATCH 2/2] Update test for node.js 7 --- test/externalKey.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/externalKey.test.js b/test/externalKey.test.js index ed41b64..c545d05 100644 --- a/test/externalKey.test.js +++ b/test/externalKey.test.js @@ -15,7 +15,7 @@ describe('Koa Session External Key', () => { externalKey: {}, }); } catch (err) { - assert.equal(err.code, 'ERR_ASSERTION'); + assert.equal(err.message, 'externalKey.get must be function'); } }); });