From 5161205df42fbf031d3d33391020f2366754e26d Mon Sep 17 00:00:00 2001 From: chenlingjie Date: Wed, 20 Dec 2017 11:29:06 +0800 Subject: [PATCH 1/2] xg --- .idea/dbnavigator.xml | 452 ++++++++++++++++++ .idea/inspectionProfiles/Project_Default.xml | 6 + .idea/misc.xml | 6 + .idea/modules.xml | 8 + .idea/session.iml | 12 + .idea/vcs.xml | 6 + .idea/workspace.xml | 454 +++++++++++++++++++ index.js | 172 +++---- lib/context.js | 48 +- lib/session.js | 4 +- "\346\224\266\350\216\267.md" | 13 + 11 files changed, 1077 insertions(+), 104 deletions(-) create mode 100644 .idea/dbnavigator.xml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/session.iml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml create mode 100644 "\346\224\266\350\216\267.md" diff --git a/.idea/dbnavigator.xml b/.idea/dbnavigator.xml new file mode 100644 index 0000000..fb39777 --- /dev/null +++ b/.idea/dbnavigator.xml @@ -0,0 +1,452 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..c6cc8c8 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..28a804d --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..7867bfc --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/session.iml b/.idea/session.iml new file mode 100644 index 0000000..24643cc --- /dev/null +++ b/.idea/session.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..80ded95 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,454 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + debug + uid + Symbol + ContextSession + externalKey + commit + commit|commit + save + ContextSession|ContextSession + sessionOptions + cookie + + + + + + + + + + + + + true + + false + true + + + true + DEFINITION_ORDER + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1513734560993 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/index.js b/index.js index b095060..2c26c51 100644 --- a/index.js +++ b/index.js @@ -20,31 +20,36 @@ const _CONTEXT_SESSION = Symbol('context#_contextSession'); * @param {Application} app, koa application instance * @api public */ - -module.exports = function(opts, app) { - // session(app[, opts]) - if (opts && typeof opts.use === 'function') { - [ app, opts ] = [ opts, app ]; - } - // app required - if (!app || typeof app.use !== 'function') { - throw new TypeError('app instance required: `session(opts, app)`'); - } - - opts = formatOpts(opts); - extendContext(app.context, opts); - - return async function session(ctx, next) { - const sess = ctx[CONTEXT_SESSION]; - if (sess.store) await sess.initFromExternal(); - try { - await next(); - } catch (err) { - throw err; - } finally { - await sess.commit(); +//TODO opts是中间件的config,app是服务器 +module.exports = function (opts, app) { + // session(app[, opts]) + //TODO hook,防止用户参数写反了 + if (opts && typeof opts.use === 'function') { + [app, opts] = [opts, app]; } - }; + // app required + //TODO 报错 + if (!app || typeof app.use !== 'function') { + throw new TypeError('app instance required: `session(opts, app)`'); + } + //TODO 把设置格式化 + opts = formatOpts(opts); + //TODO 获取接口 + extendContext(app.context, opts); + //TODO 返回中间件 + return async function session(ctx, next) { + const sess = ctx[CONTEXT_SESSION]; + //TODO 如果是缓存层的 + if (sess.store) await sess.initFromExternal(); + try { + await next(); + } catch (err) { + throw err; + //TODO 无论什么结果都会执行 + } finally { + await sess.commit(); + } + }; }; /** @@ -56,49 +61,50 @@ module.exports = function(opts, app) { */ function formatOpts(opts) { - opts = opts || {}; - // key - opts.key = opts.key || 'koa:sess'; - - // back-compat maxage - if (!('maxAge' in opts)) opts.maxAge = opts.maxage; + opts = opts || {}; + // key + opts.key = opts.key || 'koa:sess'; - // defaults - if (opts.overwrite == null) opts.overwrite = true; - if (opts.httpOnly == null) opts.httpOnly = true; - if (opts.signed == null) opts.signed = true; + // back-compat maxage + if (!('maxAge' in opts)) opts.maxAge = opts.maxage; - debug('session options %j', opts); + // defaults + if (opts.overwrite == null) opts.overwrite = true; + if (opts.httpOnly == null) opts.httpOnly = true; + if (opts.signed == null) opts.signed = true; - // setup encoding/decoding - if (typeof opts.encode !== 'function') { - opts.encode = util.encode; - } - if (typeof opts.decode !== 'function') { - opts.decode = util.decode; - } + debug('session options %j', opts); - const store = opts.store; - if (store) { - assert(is.function(store.get), 'store.get must be function'); - assert(is.function(store.set), 'store.set must be function'); - assert(is.function(store.destroy), 'store.destroy must be function'); - } + // setup encoding/decoding + //TODO encode和decode的函数 + if (typeof opts.encode !== 'function') { + opts.encode = util.encode; + } + if (typeof opts.decode !== 'function') { + opts.decode = util.decode; + } - const ContextStore = opts.ContextStore; - if (ContextStore) { - assert(is.class(ContextStore), 'ContextStore must be a class'); - assert(is.function(ContextStore.prototype.get), 'ContextStore.prototype.get must be function'); - assert(is.function(ContextStore.prototype.set), 'ContextStore.prototype.set must be function'); - assert(is.function(ContextStore.prototype.destroy), 'ContextStore.prototype.destroy must be function'); - } + const store = opts.store; + if (store) { + assert(is.function(store.get), 'store.get must be function'); + assert(is.function(store.set), 'store.set must be function'); + assert(is.function(store.destroy), 'store.destroy must be function'); + } - if (!opts.genid) { - if (opts.prefix) opts.genid = () => opts.prefix + uid.sync(24); - else opts.genid = () => uid.sync(24); - } + const ContextStore = opts.ContextStore; + if (ContextStore) { + assert(is.class(ContextStore), 'ContextStore must be a class'); + assert(is.function(ContextStore.prototype.get), 'ContextStore.prototype.get must be function'); + assert(is.function(ContextStore.prototype.set), 'ContextStore.prototype.set must be function'); + assert(is.function(ContextStore.prototype.destroy), 'ContextStore.prototype.destroy must be function'); + } + //TODO 生成genid的函数 + if (!opts.genid) { + if (opts.prefix) opts.genid = () => opts.prefix + uid.sync(24); + else opts.genid = () => uid.sync(24); + } - return opts; + return opts; } /** @@ -111,27 +117,27 @@ function formatOpts(opts) { */ function extendContext(context, opts) { - Object.defineProperties(context, { - [CONTEXT_SESSION]: { - get() { - if (this[_CONTEXT_SESSION]) return this[_CONTEXT_SESSION]; - this[_CONTEXT_SESSION] = new ContextSession(this, opts); - return this[_CONTEXT_SESSION]; - }, - }, - session: { - get() { - return this[CONTEXT_SESSION].get(); - }, - set(val) { - this[CONTEXT_SESSION].set(val); - }, - configurable: true, - }, - sessionOptions: { - get() { - return this[CONTEXT_SESSION].opts; - }, - }, - }); + Object.defineProperties(context, { + [CONTEXT_SESSION]: { + get() { + if (this[_CONTEXT_SESSION]) return this[_CONTEXT_SESSION]; + this[_CONTEXT_SESSION] = new ContextSession(this, opts); + return this[_CONTEXT_SESSION]; + }, + }, + session: { + get() { + return this[CONTEXT_SESSION].get(); + }, + set(val) { + this[CONTEXT_SESSION].set(val); + }, + configurable: true, + }, + sessionOptions: { + get() { + return this[CONTEXT_SESSION].opts; + }, + }, + }); } diff --git a/lib/context.js b/lib/context.js index c4622a1..1aa4609 100644 --- a/lib/context.js +++ b/lib/context.js @@ -5,7 +5,7 @@ const Session = require('./session'); const util = require('./util'); const ONE_DAY = 24 * 60 * 60 * 1000; - +//TODO externalKey是指在redis中的key class ContextSession { /** * context session constructor @@ -24,7 +24,7 @@ class ContextSession { * * @api public */ - + //TODO 每个请求进入中间件,就会执行这个,用于得到或创建session get() { const session = this.session; // already retrieved @@ -43,7 +43,7 @@ class ContextSession { * * @api public */ - + //TODO 设置session set(val) { if (val === null) { this.session = false; @@ -63,15 +63,15 @@ class ContextSession { * * @api public */ - + //TODO 创建带缓存层的session async initFromExternal() { debug('init from external'); const ctx = this.ctx; const opts = this.opts; - + //TODO 得到缓存层的key,有缓存层时session就是个key const externalKey = ctx.cookies.get(opts.key, opts); debug('get external key from cookie %s', externalKey); - + //TODO 如果不存在key if (!externalKey) { // create a new `externalKey` this.create(); @@ -79,6 +79,7 @@ class ContextSession { } const json = await this.store.get(externalKey, opts.maxAge, { rolling: opts.rolling }); + //TODO 如果已经过期 if (!this.valid(json)) { // create a new `externalKey` this.create(); @@ -94,13 +95,14 @@ class ContextSession { * init session from cookie * @api private */ - + //TODO 创建没有缓存层的session initFromCookie() { debug('init from cookie'); const ctx = this.ctx; const opts = this.opts; - + //TODO 没有缓存层的session包含了所有数据,opts只是为了signed参数 const cookie = ctx.cookies.get(opts.key, opts); + //TODO 第一次请求没有session那就创建 if (!cookie) { this.create(); return; @@ -109,6 +111,7 @@ class ContextSession { let json; debug('parse %s', cookie); try { + //TODO 解码得到数据 json = opts.decode(cookie); } catch (err) { // backwards compatibility: @@ -118,6 +121,7 @@ class ContextSession { // but `JSON.parse(string)` will crash. debug('decode %j error: %s', cookie, err); if (!(err instanceof SyntaxError)) { + //TODO 删除session // clean this cookie to ensure next request won't throw again ctx.cookies.set(opts.key, '', opts); // ctx.onerror will unset all headers, and set those specified in err @@ -131,12 +135,12 @@ class ContextSession { } debug('parsed %j', json); - + //TODO 验证是否过期 if (!this.valid(json)) { this.create(); return; } - + //TODO 创建带数据的session // support access `ctx.session` before session middleware this.create(json); this.prevHash = util.hash(this.session.toJSON()); @@ -148,15 +152,15 @@ class ContextSession { * @return {Boolean} valid * @api private */ - + //TODO 验证session是否过期 valid(json) { if (!json) return false; - + //TODO 如果session过期 if (json._expire && json._expire < Date.now()) { debug('expired session'); return false; } - + //TODO 用户自己的验证规则 const valid = this.opts.valid; if (typeof valid === 'function' && !valid(this.ctx, json)) { // valid session value fail, ignore this session @@ -173,10 +177,12 @@ class ContextSession { * @param {String} [externalKey] session external key * @api private */ - + //TODO 创建session,没有参数时创建空session create(val, externalKey) { debug('create session with val: %j externalKey: %s', val, externalKey); + //TODO 如果使用缓存层,就添加缓存的key if (this.store) this.externalKey = externalKey || this.opts.genid(); + //TODO 创建session this.session = new Session(this.ctx, val); } @@ -185,7 +191,7 @@ class ContextSession { * * @api public */ - + //TODO save的hook async commit() { const session = this.session; const prevHash = this.prevHash; @@ -223,14 +229,15 @@ class ContextSession { * remove session * @api private */ - + //TODO 移除session async remove() { const opts = this.opts; const ctx = this.ctx; const key = opts.key; const externalKey = this.externalKey; - + //TODO 如果在缓存层当中就把缓存层的删除 if (externalKey) await this.store.destroy(externalKey); + //TODO cookie设置为空 ctx.cookies.set(key, '', opts); } @@ -238,14 +245,16 @@ class ContextSession { * save session * @api private */ - + //TODO 把session返回浏览器 async save(changed) { const opts = this.opts; const key = opts.key; const externalKey = this.externalKey; let json = this.session.toJSON(); // set expire for check + //TODO 设置默认的过期水煎 const maxAge = opts.maxAge ? opts.maxAge : ONE_DAY; + //TODO 过期时间是session那就是maxAge = undefined if (maxAge === 'session') { // do not set _expire in json if maxAge is set to 'session' // also delete maxAge from options @@ -256,6 +265,7 @@ class ContextSession { json._maxAge = maxAge; } + //TODO 有缓存层的话就保存key // save to external store if (externalKey) { debug('save %j to external key %s', json, externalKey); @@ -266,7 +276,7 @@ class ContextSession { this.ctx.cookies.set(key, externalKey, opts); return; } - + //TODO 没有缓存层就保存数据 // save to cookie debug('save %j to cookie', json); json = opts.encode(json); diff --git a/lib/session.js b/lib/session.js index b585f2a..dbb6052 100644 --- a/lib/session.js +++ b/lib/session.js @@ -11,7 +11,7 @@ class Session { * @param {Object} obj * @api private */ - + //TODO obj是数据 constructor(ctx, obj) { this._ctx = ctx; if (!obj) { @@ -94,7 +94,7 @@ class Session { * @param {Number} * @api public */ - + //TODO 会变成修改所有的session配置 set maxAge(val) { this._ctx.sessionOptions.maxAge = val; // maxAge changed, must save to cookie and store diff --git "a/\346\224\266\350\216\267.md" "b/\346\224\266\350\216\267.md" new file mode 100644 index 0000000..808d800 --- /dev/null +++ "b/\346\224\266\350\216\267.md" @@ -0,0 +1,13 @@ +###### Symbol +由于这种特点,Symbol类型适合作为标识符,用于对象的属性名, +保证了属性名之间不会发生冲突。如果一个对象由多个模块构成, +这样就不会出现同名的属性,也就防止了键值被不小心改写或覆盖。 +###### try/catch/finally +finally一定会执行 +###### uid-safe库 +###### crc库 +循环冗余校验 +###### 编码解码 +使用base64和JSON进行 +###### 写库多用get,set +###### 这个库没办法动态设置每个session的过期时间 From b49292b8190d278fa77ba1049e34832489c40c4b Mon Sep 17 00:00:00 2001 From: chenlingjie Date: Tue, 26 Dec 2017 09:55:25 +0800 Subject: [PATCH 2/2] xg --- .idea/workspace.xml | 181 ++++++++++++++++++++++++++-------- "\346\224\266\350\216\267.md" | 6 ++ 2 files changed, 144 insertions(+), 43 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 80ded95..a1c457a 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,13 +2,8 @@ - - - - - - - + + @@ -22,12 +17,12 @@ - + - + @@ -46,7 +41,7 @@ - + @@ -56,8 +51,8 @@ - - + + @@ -67,7 +62,7 @@ - + @@ -76,8 +71,8 @@ - - + + @@ -87,8 +82,8 @@ - - + + @@ -136,7 +131,7 @@ - + @@ -207,7 +202,6 @@ - @@ -250,6 +244,7 @@ + @@ -290,12 +285,13 @@ - @@ -308,9 +304,9 @@ - - - + + + @@ -318,11 +314,11 @@ - - + + @@ -337,6 +333,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -362,7 +457,7 @@ - + @@ -391,25 +486,17 @@ - - - - - - - - - + - + @@ -423,18 +510,26 @@ + + + + + + + + - + - + - - + + @@ -442,8 +537,8 @@ - - + + diff --git "a/\346\224\266\350\216\267.md" "b/\346\224\266\350\216\267.md" index 808d800..074301a 100644 --- "a/\346\224\266\350\216\267.md" +++ "b/\346\224\266\350\216\267.md" @@ -9,5 +9,11 @@ finally一定会执行 循环冗余校验 ###### 编码解码 使用base64和JSON进行 +解码 +const body = new Buffer(string, 'base64').toString('utf8'); +const json = JSON.parse(body); +编码 +const body = JSON.stringify(body); +new Buffer(body).toString('base64'); ###### 写库多用get,set ###### 这个库没办法动态设置每个session的过期时间