redis-cookie-store
Advanced tools
+10
| 'use strict'; | ||
| // node core modules | ||
| // 3rd party modules | ||
| // internal modules | ||
| const RedisCookieStore = require('./redis-cookie-store'); | ||
| module.exports = RedisCookieStore; |
+119
-84
| 'use strict'; | ||
| var tough = require('tough-cookie'); | ||
| var Store = tough.Store; | ||
| var permuteDomain = tough.permuteDomain; | ||
| var permutePath = tough.permutePath; | ||
| var util = require('util'); | ||
| var async = require('async'); | ||
| var _ = require('lodash'); | ||
| var Cookie = tough.Cookie; | ||
| // node core modules | ||
| const util = require('util'); | ||
| // 3rd party modules | ||
| const async = require('async'); | ||
| const _ = require('lodash'); | ||
| const { | ||
| Store, permuteDomain, permutePath, Cookie, | ||
| } = require('tough-cookie'); | ||
| // internal modules | ||
| // putting id last to not break existing interface | ||
| function RedisCookieStore(redisClient, id) { | ||
| Store.call(this); | ||
| this.idx = {}; | ||
| this.id = id || 'default'; | ||
| this.client = redisClient; | ||
| this.synchronous = false; | ||
| const self = this; | ||
| Store.call(self); | ||
| self.idx = {}; | ||
| self.id = id || 'default'; | ||
| self.client = redisClient; | ||
| self.synchronous = false; | ||
| } | ||
@@ -22,109 +28,138 @@ util.inherits(RedisCookieStore, Store); | ||
| RedisCookieStore.prototype.getKeyName = function getKeyName(domain, path) { | ||
| const self = this; | ||
| if (path) { | ||
| return "cookie-store:" + this.id + ":cookie:" + domain + ":" + path; | ||
| } else { | ||
| return "cookie-store:" + this.id + ":cookie:" + domain; | ||
| return `cookie-store:${self.id}:cookie:${domain}:${path}`; | ||
| } | ||
| return `cookie-store:${self.id}:cookie:${domain}`; | ||
| }; | ||
| RedisCookieStore.prototype.findCookie = function(domain, path, key, cb) { | ||
| return this.client.hget(this.getKeyName(domain, path), key, cb); | ||
| RedisCookieStore.prototype.findCookie = function findCookie(domain, path, cookieName, cb) { | ||
| const self = this; | ||
| const { client } = self; | ||
| const keyName = self.getKeyName(domain, path); | ||
| client.hget(keyName, cookieName, cb); | ||
| }; | ||
| RedisCookieStore.prototype.findCookies = function(domain, path, cb) { | ||
| const cookiePrefixRegexp = /(.*cookie:[^:]*:)/i; | ||
| const pathMatcher = ({ domainKeys, paths, client }, cb) => { | ||
| const [firstDomainKey] = domainKeys; | ||
| const [, domainPrefix] = firstDomainKey.match(cookiePrefixRegexp); // get domain key prefix e.g. "cookie:www.example.com" | ||
| const prefixedPaths = paths.map(path => domainPrefix + path); | ||
| const keys = _.intersection(domainKeys, prefixedPaths).sort((a, b) => a.length - b.length); | ||
| const jobs = keys.map(key => next => client.hgetall(key, next)); | ||
| async.parallel(jobs, (err, results) => { | ||
| if (err) { | ||
| cb(err); | ||
| return; | ||
| } | ||
| cb(null, _.merge(...results)); | ||
| }); | ||
| }; | ||
| RedisCookieStore.prototype.findCookies = function findCookies(domain, path, cb) { | ||
| const self = this; | ||
| const { client } = self; | ||
| if (!domain) { | ||
| return cb(null, []); | ||
| cb(null, []); | ||
| return; | ||
| } | ||
| var domains = permuteDomain(domain) || [domain]; | ||
| var self = this; | ||
| const permutedDomains = permuteDomain(domain) || [domain]; | ||
| // sort permuted domains (length ascending) | ||
| const sortedPermutedDomains = permutedDomains.sort((a, b) => a.length - b.length); | ||
| var paths = permutePath(path) || [path]; | ||
| var pathMatcher = function matchRFC(domainKeys, cb) { | ||
| const paths = permutePath(path) || [path]; | ||
| var domainPrefix = domainKeys[0].match(/(.*cookie:[^:]*:)/i)[1]; //get domain key prefix e.g. "cookie:www.example.com" | ||
| var prefixedPaths = paths.map(function(path) { | ||
| return domainPrefix + path; | ||
| }); | ||
| // console.log(prefixedPaths); | ||
| var keys = _.intersection(domainKeys, prefixedPaths).sort(function(a, b) { | ||
| return a.length - b.length; | ||
| }); | ||
| // prepare jobs to load cookie data from redis for each permuted domain | ||
| const jobs = sortedPermutedDomains.map(permutedDomain => (next) => { | ||
| const keyName = `${self.getKeyName(permutedDomain)}:*`; | ||
| async.parallel(keys.map(function(key) { | ||
| return function(callback) { | ||
| self.client.hgetall(key, function(err, hash) { | ||
| callback(err, hash); | ||
| }); | ||
| }; | ||
| }), function(err, results) { | ||
| client.keys(keyName, (err, domainKeys) => { | ||
| if (err) { | ||
| return cb(err); | ||
| next(err, null); | ||
| return; | ||
| } | ||
| cb(null, _.merge.apply(_, results)); | ||
| if (!domainKeys || !domainKeys.length) { | ||
| next(null, {}); | ||
| return; | ||
| } | ||
| pathMatcher({ domainKeys, paths, client }, next); | ||
| }); | ||
| }; | ||
| }); | ||
| async.parallel(jobs, (err, results) => { | ||
| if (err) { | ||
| cb(err); | ||
| return; | ||
| } | ||
| cb( | ||
| err, | ||
| _.values(_.merge(...results)).map((cookieString) => { | ||
| const cookie = Cookie.parse(cookieString); | ||
| async.parallel(domains.sort(function(a, b) { | ||
| return a.length - b.length; | ||
| }).map(function(domain) { | ||
| return function(callback) { | ||
| self.client.keys(self.getKeyName(domain) + ":*", function(err, domainKeys) { | ||
| if (err) { | ||
| return callback(err, null); | ||
| if (!cookie.domain) { | ||
| cookie.domain = domain; | ||
| } | ||
| if (!domainKeys || !domainKeys.length) { | ||
| return callback(null, {}); | ||
| } | ||
| pathMatcher(domainKeys, callback); | ||
| }); | ||
| }; | ||
| }), function(err, results) { | ||
| if (err) { | ||
| return cb(err); | ||
| } | ||
| cb(err, _.values(_.merge.apply(_, results)).map(function(cookieString) { | ||
| var cookie = Cookie.parse(cookieString); | ||
| if (!cookie.domain) { | ||
| cookie.domain = domain; | ||
| } | ||
| return cookie; | ||
| })); | ||
| return cookie; | ||
| }) | ||
| ); | ||
| }); | ||
| }; | ||
| RedisCookieStore.prototype.putCookie = function(cookie, cb) { | ||
| this.client.hset(this.getKeyName(cookie.domain, cookie.path), cookie.key, cookie.toString(), cb); | ||
| RedisCookieStore.prototype.putCookie = function putCookie(cookie, cb) { | ||
| const self = this; | ||
| const { client } = self; | ||
| const { key: cookieName, domain, path } = cookie; | ||
| const keyName = self.getKeyName(domain, path); | ||
| const cookieString = cookie.toString(); | ||
| client.hset(keyName, cookieName, cookieString, cb); | ||
| }; | ||
| RedisCookieStore.prototype.updateCookie = function updateCookie(oldCookie, newCookie, cb) { | ||
| const self = this; | ||
| // updateCookie() may avoid updating cookies that are identical. For example, | ||
| // lastAccessed may not be important to some stores and an equality | ||
| // comparison could exclude that field. | ||
| this.putCookie(newCookie, cb); | ||
| self.putCookie(newCookie, cb); | ||
| }; | ||
| RedisCookieStore.prototype.removeCookie = function removeCookie(domain, path, key, cb) { | ||
| this.client.hdel(this.getKeyName(domain, path), key, cb); | ||
| RedisCookieStore.prototype.removeCookie = function removeCookie(domain, path, cookieName, cb) { | ||
| const self = this; | ||
| const { client } = self; | ||
| const keyName = self.getKeyName(domain, path); | ||
| client.hdel(keyName, cookieName, cb); | ||
| }; | ||
| RedisCookieStore.prototype.removeCookies = function removeCookies(domain, path, cb) { | ||
| var self = this; | ||
| const self = this; | ||
| const { client } = self; | ||
| if (path) { | ||
| return self.client.del(self.getKeyName(domain, path), cb); | ||
| } else { | ||
| self.client.keys(self.getKeyName(domain) + ":*", function(err, keys) { | ||
| if (err) { | ||
| return cb(err); | ||
| } | ||
| async.each( | ||
| keys, | ||
| self.client.del, | ||
| cb | ||
| ); | ||
| }); | ||
| const keyName = self.getKeyName(domain, path); | ||
| client.del(keyName, cb); | ||
| return; | ||
| } | ||
| const keyName = `${self.getKeyName(domain)}:*`; | ||
| client.keys(keyName, (err, keys) => { | ||
| if (err) { | ||
| cb(err); | ||
| return; | ||
| } | ||
| async.each(keys, client.del, cb); | ||
| }); | ||
| }; | ||
| module.exports = RedisCookieStore; |
+22
-7
| { | ||
| "name": "redis-cookie-store", | ||
| "version": "0.0.3", | ||
| "version": "1.0.0", | ||
| "description": "Redis cookie store for tough-cookie module", | ||
| "main": "index.js", | ||
| "files": [ | ||
| "lib/" | ||
| ], | ||
| "main": "lib/index.js", | ||
| "scripts": { | ||
| "test": "echo \"Error: no test specified\" && exit 1" | ||
| "format": "prettier-eslint --write \"lib/**/*.js\"", | ||
| "prelint": "npm run format", | ||
| "lint": "eslint --ignore-path .gitignore .", | ||
| "test": "ava --verbose", | ||
| "test:watch": "npm test -- --watch", | ||
| "coverage": "nyc npm test && nyc report --reporter=html" | ||
| }, | ||
@@ -20,3 +28,3 @@ "repository": { | ||
| ], | ||
| "author": "Artem Vovsya <avovsya@gmail.com>", | ||
| "author": "Benjamin Kroeger <benjamin.kroeger@gmail.com>", | ||
| "license": "MIT", | ||
@@ -28,6 +36,13 @@ "bugs": { | ||
| "dependencies": { | ||
| "async": "1.5.0", | ||
| "lodash": "3.10.1", | ||
| "tough-cookie": "2.2.0" | ||
| "async": "^2.6.0", | ||
| "lodash": "^4.17.10", | ||
| "tough-cookie": "^2.3.4" | ||
| }, | ||
| "devDependencies": { | ||
| "ava": "^0.25.0", | ||
| "eslint": "^4.19.1", | ||
| "eslint-config-oniyi": "^5.1.0", | ||
| "nyc": "^11.8.0", | ||
| "prettier-eslint-cli": "^4.7.1" | ||
| } | ||
| } |
+18
-14
| # Redis Cookie Store | ||
| redis-cookie-store is a Redis store for tough-cookie module. See | ||
| [tough-cookie documentation](https://github.com/goinstant/tough-cookie#constructionstore--new-memorycookiestore-rejectpublicsuffixes) for more info. | ||
| a Redis store for tough-cookie module. See [tough-cookie documentation](https://github.com/goinstant/tough-cookie#constructionstore--new-memorycookiestore-rejectpublicsuffixes) for more info. | ||
| ## Installation | ||
| $ npm install redis-cookie-store | ||
| ```sh | ||
| npm install --save redis-cookie-store | ||
| ``` | ||
@@ -13,17 +14,20 @@ ## Options | ||
| * `client` An existing redis client object you normally get from `redis.createClient()` | ||
| * `id` **optional** ID for each redis store so that we can use multiple stores with the same redis database [*default:* "default"] | ||
| * `id` **optional** ID for each redis store so that we can use multiple stores with the same redis database [*default:* 'default'] | ||
| ## Usage | ||
| var redis = require("redis"); | ||
| var client = redis.createClient(); | ||
| var CookieJar = require("tough-cookie").CookieJar; | ||
| var RedisCookieStore = require("redis-cookie-store"); | ||
| ```js | ||
| const redis = require('redis'); | ||
| const { CookieJar } = require('tough-cookie'); | ||
| const RedisCookieStore = require('redis-cookie-store'); | ||
| var defaultJar = new CookieJar(new RedisCookieStore(client)); | ||
| var myJar = new CookieJar(new RedisCookieStore(client, 'my-cookie-store')); | ||
| const client = redis.createClient(); | ||
| # License | ||
| MIT | ||
| const defaultJar = new CookieJar(new RedisCookieStore(client)); | ||
| const myJar = new CookieJar(new RedisCookieStore(client, 'my-cookie-store')); | ||
| ``` | ||
| # License | ||
| MIT |
-1
| module.exports = require('./lib/redis-cookie-store'); |
No tests
QualityPackage does not have any tests. This is a strong signal of a poorly maintained or low quality package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
6492
19.14%136
18.26%0
-100%33
13.79%5
Infinity%+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
Updated
Updated
Updated