index.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
  4. /** !
  5. * koa-redis - index.js
  6. * Copyright(c) 2015
  7. * MIT Licensed
  8. *
  9. * Authors:
  10. * dead_horse <dead_horse@qq.com> (http://deadhorse.me)
  11. */
  12. /**
  13. * Module dependencies.
  14. */
  15. var util = require('util');
  16. var _require = require('events'),
  17. EventEmitter = _require.EventEmitter;
  18. var debug = require('debug')('koa-redis');
  19. var Redis = require('ioredis');
  20. var wrap = require('co-wrap-all');
  21. /**
  22. * Initialize redis session middleware with `opts` (see the README for more info):
  23. *
  24. * @param {Object} options
  25. * - {Boolean} isRedisCluster redis is cluster
  26. * - {Object} client redis client (overides all other options except db and duplicate)
  27. * - {String} socket redis connect socket (DEPRECATED: use 'path' instead)
  28. * - {String} db redis db
  29. * - {Boolean} duplicate if own client object, will use node redis's duplicate function and pass other options
  30. * - {String} password redis password
  31. * - {Any} [any] all other options including above are passed to ioredis
  32. * @returns {Object} Redis instance
  33. */
  34. function RedisStore(options) {
  35. var _this = this;
  36. if (!(this instanceof RedisStore)) {
  37. return new RedisStore(options);
  38. }
  39. EventEmitter.call(this);
  40. options = options || {};
  41. var client;
  42. options.password = options.password || options.auth_pass || options.pass || null; // For backwards compatibility
  43. options.path = options.path || options.socket || null; // For backwards compatibility
  44. if (!options.client) {
  45. //
  46. // TODO: we should probably omit custom options we have
  47. // in this lib from `options` passed to instances below
  48. //
  49. var redisUrl = options.url && options.url.toString();
  50. delete options.url;
  51. if (options.isRedisCluster) {
  52. debug('Initializing Redis Cluster');
  53. delete options.isRedisCluster;
  54. client = new Redis.Cluster(options.nodes, options.clusterOptions);
  55. } else {
  56. debug('Initializing Redis');
  57. delete options.isRedisCluster;
  58. delete options.nodes;
  59. delete options.clusterOptions;
  60. client = redisUrl ? new Redis(redisUrl, options) : new Redis(options);
  61. }
  62. } else if (options.duplicate) {
  63. // Duplicate client and update with options provided
  64. debug('Duplicating provided client with new options (if provided)');
  65. var dupClient = options.client;
  66. delete options.client;
  67. delete options.duplicate;
  68. client = dupClient.duplicate(options); // Useful if you want to use the DB option without adjusting the client DB outside koa-redis
  69. } else {
  70. debug('Using provided client');
  71. client = options.client;
  72. }
  73. if (options.db) {
  74. debug('selecting db %s', options.db);
  75. client.select(options.db);
  76. client.on('connect', function () {
  77. client.send_anyways = true;
  78. client.select(options.db);
  79. client.send_anyways = false;
  80. });
  81. }
  82. ['connect', 'ready', 'error', 'close', 'reconnecting', 'end'].forEach(function (name) {
  83. _this.on(name, function () {
  84. return debug(`redis ${name}`);
  85. });
  86. client.on(name, _this.emit.bind(_this, name));
  87. }); // For backwards compatibility
  88. client.on('end', this.emit.bind(this, 'disconnect'));
  89. this.client = client;
  90. Object.defineProperty(this, 'status', {
  91. get() {
  92. return this.client.status;
  93. }
  94. });
  95. Object.defineProperty(this, 'connected', {
  96. get() {
  97. return ['connect', 'ready'].includes(this.status);
  98. }
  99. }); // Support optional serialize and unserialize
  100. this.serialize = typeof options.serialize === 'function' && options.serialize || JSON.stringify;
  101. this.unserialize = typeof options.unserialize === 'function' && options.unserialize || JSON.parse;
  102. }
  103. util.inherits(RedisStore, EventEmitter);
  104. RedisStore.prototype.get =
  105. /*#__PURE__*/
  106. _regenerator.default.mark(function _callee(sid) {
  107. var data;
  108. return _regenerator.default.wrap(function _callee$(_context) {
  109. while (1) {
  110. switch (_context.prev = _context.next) {
  111. case 0:
  112. _context.next = 2;
  113. return this.client.get(sid);
  114. case 2:
  115. data = _context.sent;
  116. debug('get session: %s', data || 'none');
  117. if (data) {
  118. _context.next = 6;
  119. break;
  120. }
  121. return _context.abrupt("return", null);
  122. case 6:
  123. _context.prev = 6;
  124. return _context.abrupt("return", this.unserialize(data.toString()));
  125. case 10:
  126. _context.prev = 10;
  127. _context.t0 = _context["catch"](6);
  128. // ignore err
  129. debug('parse session error: %s', _context.t0.message);
  130. case 13:
  131. case "end":
  132. return _context.stop();
  133. }
  134. }
  135. }, _callee, this, [[6, 10]]);
  136. });
  137. RedisStore.prototype.set =
  138. /*#__PURE__*/
  139. _regenerator.default.mark(function _callee2(sid, sess, ttl) {
  140. return _regenerator.default.wrap(function _callee2$(_context2) {
  141. while (1) {
  142. switch (_context2.prev = _context2.next) {
  143. case 0:
  144. if (typeof ttl === 'number') {
  145. ttl = Math.ceil(ttl / 1000);
  146. }
  147. sess = this.serialize(sess);
  148. if (!ttl) {
  149. _context2.next = 8;
  150. break;
  151. }
  152. debug('SETEX %s %s %s', sid, ttl, sess);
  153. _context2.next = 6;
  154. return this.client.setex(sid, ttl, sess);
  155. case 6:
  156. _context2.next = 11;
  157. break;
  158. case 8:
  159. debug('SET %s %s', sid, sess);
  160. _context2.next = 11;
  161. return this.client.set(sid, sess);
  162. case 11:
  163. debug('SET %s complete', sid);
  164. case 12:
  165. case "end":
  166. return _context2.stop();
  167. }
  168. }
  169. }, _callee2, this);
  170. });
  171. RedisStore.prototype.destroy =
  172. /*#__PURE__*/
  173. _regenerator.default.mark(function _callee3(sid) {
  174. return _regenerator.default.wrap(function _callee3$(_context3) {
  175. while (1) {
  176. switch (_context3.prev = _context3.next) {
  177. case 0:
  178. debug('DEL %s', sid);
  179. _context3.next = 3;
  180. return this.client.del(sid);
  181. case 3:
  182. debug('DEL %s complete', sid);
  183. case 4:
  184. case "end":
  185. return _context3.stop();
  186. }
  187. }
  188. }, _callee3, this);
  189. });
  190. RedisStore.prototype.quit =
  191. /*#__PURE__*/
  192. _regenerator.default.mark(function _callee4() {
  193. return _regenerator.default.wrap(function _callee4$(_context4) {
  194. while (1) {
  195. switch (_context4.prev = _context4.next) {
  196. case 0:
  197. // End connection SAFELY
  198. debug('quitting redis client');
  199. _context4.next = 3;
  200. return this.client.quit();
  201. case 3:
  202. case "end":
  203. return _context4.stop();
  204. }
  205. }
  206. }, _callee4, this);
  207. });
  208. wrap(RedisStore.prototype);
  209. RedisStore.prototype.end = RedisStore.prototype.quit; // End connection SAFELY. The real end() command should never be used, as it cuts off to queue.
  210. module.exports = RedisStore;