egg-cookies
Advanced tools
Comparing version 1.0.0 to 2.0.0
2.0.0 / 2016-11-22 | ||
================== | ||
* refactor: rewrite keygrip and cookies for egg/koa (#1) | ||
* chore: add zh-CN readme | ||
1.0.0 / 2016-07-15 | ||
@@ -3,0 +9,0 @@ ================== |
'use strict'; | ||
const Cookies = require('cookies'); | ||
const assert = require('assert'); | ||
const utility = require('utility'); | ||
const Keygrip = require('./keygrip'); | ||
const Cookie = require('./cookie'); | ||
const KEYS_ARRAY = Symbol('eggCookies:keysArray'); | ||
const KEYS = Symbol('eggCookies:keys'); | ||
/** | ||
@@ -10,50 +15,125 @@ * cookies for egg | ||
*/ | ||
class EggCookies extends Cookies { | ||
class Cookies { | ||
constructor(ctx, keys) { | ||
super(ctx.req, ctx.res, { | ||
keys, | ||
secure: ctx.secure, | ||
}); | ||
this[KEYS_ARRAY] = keys; | ||
this._keys = keys; | ||
this.ctx = ctx; | ||
this.secure = this.ctx.secure; | ||
} | ||
get keys() { | ||
if (this[KEYS]) return this[KEYS]; | ||
if (!this[KEYS]) { | ||
assert(Array.isArray(this[KEYS_ARRAY]), '.keys required for encrypt/sign cookies'); | ||
this[KEYS] = new Keygrip(this[KEYS_ARRAY]); | ||
} | ||
return this[KEYS]; | ||
} | ||
/** | ||
* get cookie value by name | ||
* @param {String} name - cookie's name | ||
* @param {Object} opts - cookies' options | ||
* - {Boolean} signed - defualt to true | ||
* - {Boolean} encrypt - defualt to false | ||
* @return {String} value - cookie's value | ||
*/ | ||
get(name, opts) { | ||
// 默认不开启 encrypt | ||
const encrypt = opts && opts.encrypt; | ||
opts = encryptOrSigned(opts); | ||
// signed 和 encrypt 不同时开启 | ||
if (encrypt) { | ||
opts.signed = false; | ||
} | ||
const header = this.ctx.get('cookie'); | ||
if (!header) return; | ||
let value = super.get(name, opts); | ||
const match = header.match(getPattern(name)); | ||
if (!match) return; | ||
if (value && encrypt) { | ||
this.assertKeys(); | ||
value = utility.base64decode(value, true, 'buffer'); | ||
const msg = this.keys.decrypt(value); | ||
value = msg ? msg[0].toString('utf8') : undefined; | ||
let value = match[1]; | ||
if (!opts.encrypt && !opts.signed) return value; | ||
// signed | ||
if (opts.signed) { | ||
const sigName = name + '.sig'; | ||
const sigValue = this.get(sigName, { signed: false }); | ||
if (!sigValue) return; | ||
const raw = name + '=' + value; | ||
const index = this.keys.verify(raw, sigValue); | ||
if (index < 0) { | ||
// can not match any key, remove ${name}.sig | ||
this.set(sigName, null, { path: '/', signed: false }); | ||
return; | ||
} | ||
if (index > 0) { | ||
// not signed by the first key, update sigValue | ||
this.set(sigName, this.keys.sign(raw), { signed: false }); | ||
} | ||
return value; | ||
} | ||
return value; | ||
// encrypt | ||
value = utility.base64decode(value, true, 'buffer'); | ||
const res = this.keys.decrypt(value); | ||
return res ? res.value.toString() : undefined; | ||
} | ||
set(name, value, opts) { | ||
const encrypt = opts && opts.encrypt; | ||
opts = encryptOrSigned(opts); | ||
value = value || ''; | ||
if (!this.secure && opts.secure) { | ||
throw new Error('Cannot send secure cookie over unencrypted connection'); | ||
} | ||
if (opts.secure === undefined) opts.secure = this.secure; | ||
// signed 和 encrypt 不需要同时开启 | ||
if (value && encrypt) { | ||
opts.signed = false; | ||
this.assertKeys(); | ||
value = utility.base64encode(this.keys.encrypt(value), true); | ||
let headers = this.ctx.response.get('set-cookie') || []; | ||
// encrypt | ||
if (opts.encrypt) { | ||
value = value && utility.base64encode(this.keys.encrypt(value), true); | ||
} | ||
return super.set(name, value, opts); | ||
} | ||
const cookie = new Cookie(name, value, opts); | ||
headers = pushCookie(headers, cookie); | ||
assertKeys() { | ||
if (!this.keys) { | ||
throw new TypeError('.keys required for encrypt cookies'); | ||
// signed | ||
if (opts.signed) { | ||
cookie.value = value && this.keys.sign(cookie.toString()); | ||
cookie.name += '.sig'; | ||
headers = pushCookie(headers, cookie); | ||
} | ||
this.ctx.set('set-cookie', headers); | ||
return this; | ||
} | ||
} | ||
module.exports = EggCookies; | ||
const cache = new Map(); | ||
function getPattern(name) { | ||
const cachePattern = cache.get(name); | ||
if (cachePattern) return cachePattern; | ||
const reg = new RegExp( | ||
'(?:^|;) *' + | ||
name.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') + | ||
'=([^;]*)' | ||
); | ||
cache.set(name, reg); | ||
return reg; | ||
} | ||
function encryptOrSigned(opts) { | ||
opts = opts || {}; | ||
// encrypt default to false, signed default to true. | ||
// disable singed when encrypt is true. | ||
if (opts.encrypt) opts.signed = false; | ||
if (opts.signed !== false) opts.signed = true; | ||
return opts; | ||
} | ||
function pushCookie(cookies, cookie) { | ||
if (cookie.attrs.overwrite) { | ||
cookies = cookies.filter(c => !c.startsWith(cookie.name + '=')); | ||
} | ||
cookies.push(cookie.toHeader()); | ||
return cookies; | ||
} | ||
module.exports = Cookies; |
{ | ||
"name": "egg-cookies", | ||
"version": "1.0.0", | ||
"description": "cookies module for egg, base on pillarjs/cookies", | ||
"version": "2.0.0", | ||
"description": "cookies module for egg", | ||
"files": [ | ||
@@ -10,11 +10,17 @@ "lib" | ||
"dependencies": { | ||
"cookies": "~0.6.1", | ||
"debug": "^2.2.0", | ||
"scmp": "^1.0.0", | ||
"utility": "^1.8.0" | ||
"debug": "^2.3.3", | ||
"scmp": "^2.0.0", | ||
"utility": "^1.9.0" | ||
}, | ||
"devDependencies": { | ||
"egg-bin": "1", | ||
"eslint": "3", | ||
"eslint-config-egg": "3" | ||
"autod": "^2.7.1", | ||
"beautify-benchmark": "^0.2.4", | ||
"benchmark": "^2.1.2", | ||
"cookies": "^0.6.2", | ||
"egg-bin": "^1.7.0", | ||
"egg-ci": "^1.1.0", | ||
"eslint": "^3.10.2", | ||
"eslint-config-egg": "^3.2.0", | ||
"intelli-espower-loader": "^1.0.1", | ||
"power-assert": "^1.4.2" | ||
}, | ||
@@ -28,6 +34,7 @@ "repository": { | ||
"scripts": { | ||
"test": "npm run lint && npm run test-local", | ||
"test-local": "egg-bin test", | ||
"lint": "eslint --fix lib test", | ||
"ci": "npm run lint && egg-bin cov" | ||
"test": "egg-bin test --require intelli-espower-loader", | ||
"cov": "egg-bin cov --require intelli-espower-loader", | ||
"lint": "eslint index.js test", | ||
"ci": "npm run lint && npm run cov", | ||
"autod": "autod" | ||
}, | ||
@@ -38,4 +45,4 @@ "engines": { | ||
"ci": { | ||
"version": "4, 6" | ||
"version": "4, 6, 7" | ||
} | ||
} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
11017
3
7
239
10
1
+ Addedscmp@2.1.0(transitive)
- Removedcookies@~0.6.1
- Removedcookies@0.6.2(transitive)
- Removeddepd@1.1.2(transitive)
- Removedkeygrip@1.0.3(transitive)
- Removedscmp@1.0.2(transitive)
Updateddebug@^2.3.3
Updatedscmp@^2.0.0
Updatedutility@^1.9.0