connect-memcached 1.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Readme.md CHANGED
@@ -4,10 +4,16 @@ Memcached session store, using [node-memcached](http://github.com/3rd-Eden/node-
4
4
 
5
5
  ## Installation
6
6
 
7
- via npm:
7
+ npm:
8
8
 
9
- ```bash
10
- $ npm install connect-memcached
9
+ ```shell
10
+ npm install connect-memcached express-session
11
+ ```
12
+
13
+ yarn:
14
+
15
+ ```shell
16
+ yarn add connect-memcached express-session
11
17
  ```
12
18
 
13
19
  ## Example
@@ -15,12 +21,9 @@ $ npm install connect-memcached
15
21
  ```javascript
16
22
  var express = require("express"),
17
23
  session = require("express-session"),
18
- cookieParser = require("cookie-parser"),
19
- http = require("http"),
20
24
  app = express(),
21
25
  MemcachedStore = require("connect-memcached")(session);
22
26
 
23
- app.use(cookieParser());
24
27
  app.use(
25
28
  session({
26
29
  secret: "CatOnKeyboard",
@@ -30,7 +33,7 @@ app.use(
30
33
  saveUninitialized: false,
31
34
  store: new MemcachedStore({
32
35
  hosts: ["127.0.0.1:11211"],
33
- secret: "123, easy as ABC. ABC, easy as 123" // Optionally use transparent encryption for memcache session data
36
+ secret: "Xj8$kLp2@Qa9#Zt5!" // Optionally use transparent encryption for memcached session data (must meet complexity requirements)
34
37
  })
35
38
  })
36
39
  );
@@ -44,21 +47,53 @@ app.get("/", function(req, res) {
44
47
  res.send("Viewed <strong>" + req.session.views + "</strong> times.");
45
48
  });
46
49
 
47
- http.createServer(app).listen(9341, function() {
50
+ app.listen(9341, function() {
48
51
  console.log("Listening on %d", this.address().port);
49
52
  });
50
53
  ```
51
54
 
52
55
  ## Options
53
56
 
54
- - `hosts` Memcached servers locations, can be string, array, hash.
55
- - `prefix` An optional prefix for each memcache key, in case you are sharing your memcached servers with something generating its own keys.
56
- - `ttl` An optional parameter used for setting the default TTL (in seconds)
57
- - `secret` An optional secret can be used to encrypt/decrypt session contents.
58
- - `algorithm` An optional algorithm parameter may be used, but must be valid based on returned `crypto.getCiphers()`. The current default is `aes-256-ctr` and was chosen based on the following [information](http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html)
59
- - ... Rest of given option will be passed directly to the node-memcached constructor.
57
+ - `hosts` (Optional) Memcached servers locations, can be string, array or hash. Default is `127.0.0.1:11211`.
58
+ - `prefix` (Optional) Prefix for each memcached key, in case you are sharing your memcached servers with something generating its own keys.
59
+ - `ttl` (Optional) Default TTL parameter for the session data (in seconds).
60
+ - `secret` (Optional) Secret used to encrypt/decrypt session contents. Setting it enables data encryption, which is handled by [kruptein](https://github.com/jas-/kruptein) module.
61
+ - `algorithm` (Optional) Cipher algorithm from `crypto.getCiphers()`. Default is `aes-256-gcm`.
62
+ - `hashing` (Optional) Hash algorithm from `crypto.getHashes()`. Default is `sha512`.
63
+ - ... Rest of given options will be passed directly to the [node-memcached](http://github.com/3rd-Eden/node-memcached) and [kruptein](https://github.com/jas-/kruptein) constructors, see their appropriate docs for extra configurability.
64
+
65
+ ## Upgrading to v3.x.x
66
+
67
+ v3.0.0 introduces two breaking changes:
68
+
69
+ ### 1. Node.js version requirement
70
+
71
+ **Breaking change:** v3.0.0 requires Node.js >= 14.0.0. Support for Node.js versions 4-12 has been dropped.
72
+
73
+ If you're running an older Node.js version, please upgrade to Node.js 14 or later before upgrading to v3.x.x.
74
+
75
+ ### 2. Stronger secret requirements for encryption
76
+
77
+ **Breaking change:** The `kruptein` dependency has been updated to enforce stricter password complexity requirements for the `secret` option. If you use encryption (set the `secret` option), your secret must now meet these requirements:
78
+
79
+ - Minimum length: 8 characters
80
+ - Minimum 2 uppercase letters
81
+ - Minimum 2 lowercase letters
82
+ - Minimum 2 numbers
83
+ - Minimum 2 special characters (`!@#$%^&*()_+-=[]{};':"\\|,.<>/?`)
84
+
85
+ **IMPORTANT:** Check if your current secret meets these requirements:
86
+
87
+ - **If your secret already meets the requirements:** You can upgrade safely with no additional action needed.
88
+ - **If your secret does NOT meet the requirements:** You MUST flush all encrypted session data from memcached before upgrading AND update your secret to meet the new requirements. All existing encrypted session data will become inaccessible with the new secret.
89
+
90
+ Sessions without encryption (no `secret` option) are not affected.
91
+
92
+ ## Upgrading to v2.x.x
93
+
94
+ When upgrading from pre v2 and using data encryption please flush all the session entries from memcached before rolling the update.
60
95
 
61
- For details see [node-memcached](http://github.com/3rd-Eden/node-memcached).
96
+ Sessions without data encryption are not affected.
62
97
 
63
98
  ## Upgrading from v0.x.x -> v1.x.x
64
99
 
@@ -0,0 +1,104 @@
1
+ services:
2
+ memcached:
3
+ image: memcached:1.6-alpine
4
+ ports:
5
+ - "11211:11211"
6
+ command: memcached -m 64
7
+
8
+ test-node-14:
9
+ image: node:14-alpine
10
+ depends_on:
11
+ - memcached
12
+ working_dir: /app
13
+ volumes:
14
+ - .:/app
15
+ environment:
16
+ - NODE_ENV=test
17
+ - MEMCACHED_HOST=memcached:11211
18
+ - NPM_CONFIG_FUND=false
19
+ - NPM_CONFIG_UPDATE_NOTIFIER=false
20
+ command: sh -c "npm install && npm test"
21
+
22
+ test-node-16:
23
+ image: node:16-alpine
24
+ depends_on:
25
+ - memcached
26
+ working_dir: /app
27
+ volumes:
28
+ - .:/app
29
+ environment:
30
+ - NODE_ENV=test
31
+ - MEMCACHED_HOST=memcached:11211
32
+ - NPM_CONFIG_FUND=false
33
+ - NPM_CONFIG_UPDATE_NOTIFIER=false
34
+ command: sh -c "npm install && npm test"
35
+
36
+ test-node-18:
37
+ image: node:18-alpine
38
+ depends_on:
39
+ - memcached
40
+ working_dir: /app
41
+ volumes:
42
+ - .:/app
43
+ environment:
44
+ - NODE_ENV=test
45
+ - MEMCACHED_HOST=memcached:11211
46
+ - NPM_CONFIG_FUND=false
47
+ - NPM_CONFIG_UPDATE_NOTIFIER=false
48
+ command: sh -c "npm install && npm test"
49
+
50
+ test-node-20:
51
+ image: node:20-alpine
52
+ depends_on:
53
+ - memcached
54
+ working_dir: /app
55
+ volumes:
56
+ - .:/app
57
+ environment:
58
+ - NODE_ENV=test
59
+ - MEMCACHED_HOST=memcached:11211
60
+ - NPM_CONFIG_FUND=false
61
+ - NPM_CONFIG_UPDATE_NOTIFIER=false
62
+ command: sh -c "npm install && npm test"
63
+
64
+ test-node-22:
65
+ image: node:22-alpine
66
+ depends_on:
67
+ - memcached
68
+ working_dir: /app
69
+ volumes:
70
+ - .:/app
71
+ environment:
72
+ - NODE_ENV=test
73
+ - MEMCACHED_HOST=memcached:11211
74
+ - NPM_CONFIG_FUND=false
75
+ - NPM_CONFIG_UPDATE_NOTIFIER=false
76
+ command: sh -c "npm install && npm test"
77
+
78
+ test-node-24:
79
+ image: node:24-alpine
80
+ depends_on:
81
+ - memcached
82
+ working_dir: /app
83
+ volumes:
84
+ - .:/app
85
+ environment:
86
+ - NODE_ENV=test
87
+ - MEMCACHED_HOST=memcached:11211
88
+ - NPM_CONFIG_FUND=false
89
+ - NPM_CONFIG_UPDATE_NOTIFIER=false
90
+ command: sh -c "npm install && npm test"
91
+
92
+ test-node-25:
93
+ image: node:25-alpine
94
+ depends_on:
95
+ - memcached
96
+ working_dir: /app
97
+ volumes:
98
+ - .:/app
99
+ environment:
100
+ - NODE_ENV=test
101
+ - MEMCACHED_HOST=memcached:11211
102
+ - NPM_CONFIG_FUND=false
103
+ - NPM_CONFIG_UPDATE_NOTIFIER=false
104
+ command: sh -c "npm install && npm test"
package/flake.lock ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "nodes": {
3
+ "flake-utils": {
4
+ "inputs": {
5
+ "systems": "systems"
6
+ },
7
+ "locked": {
8
+ "lastModified": 1731533236,
9
+ "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
10
+ "owner": "numtide",
11
+ "repo": "flake-utils",
12
+ "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
13
+ "type": "github"
14
+ },
15
+ "original": {
16
+ "owner": "numtide",
17
+ "repo": "flake-utils",
18
+ "type": "github"
19
+ }
20
+ },
21
+ "nixpkgs": {
22
+ "locked": {
23
+ "lastModified": 1765779637,
24
+ "narHash": "sha256-KJ2wa/BLSrTqDjbfyNx70ov/HdgNBCBBSQP3BIzKnv4=",
25
+ "owner": "NixOS",
26
+ "repo": "nixpkgs",
27
+ "rev": "1306659b587dc277866c7b69eb97e5f07864d8c4",
28
+ "type": "github"
29
+ },
30
+ "original": {
31
+ "owner": "NixOS",
32
+ "ref": "nixos-unstable",
33
+ "repo": "nixpkgs",
34
+ "type": "github"
35
+ }
36
+ },
37
+ "root": {
38
+ "inputs": {
39
+ "flake-utils": "flake-utils",
40
+ "nixpkgs": "nixpkgs"
41
+ }
42
+ },
43
+ "systems": {
44
+ "locked": {
45
+ "lastModified": 1681028828,
46
+ "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
47
+ "owner": "nix-systems",
48
+ "repo": "default",
49
+ "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
50
+ "type": "github"
51
+ },
52
+ "original": {
53
+ "owner": "nix-systems",
54
+ "repo": "default",
55
+ "type": "github"
56
+ }
57
+ }
58
+ },
59
+ "root": "root",
60
+ "version": 7
61
+ }
package/flake.nix ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ description = "Memcached session store for Connect";
3
+
4
+ inputs = {
5
+ nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
6
+ flake-utils.url = "github:numtide/flake-utils";
7
+ };
8
+
9
+ outputs = { self, nixpkgs, flake-utils }:
10
+ flake-utils.lib.eachDefaultSystem (system:
11
+ let
12
+ pkgs = nixpkgs.legacyPackages.${system};
13
+ in
14
+ {
15
+ devShells.default = pkgs.mkShell {
16
+ packages = with pkgs; [
17
+ nodejs
18
+ nodePackages.npm
19
+ memcached
20
+ ];
21
+
22
+ shellHook = ''
23
+ echo "connect-memcached development environment"
24
+ echo "Node: $(node --version)"
25
+ echo "npm: $(npm --version)"
26
+ echo ""
27
+
28
+ # Install dependencies if node_modules doesn't exist
29
+ if [ ! -d "node_modules" ]; then
30
+ echo "Installing npm dependencies..."
31
+ npm install
32
+ fi
33
+
34
+ echo "Ready! Run 'npm test' to run tests"
35
+ '';
36
+ };
37
+ }
38
+ );
39
+ }
package/index.js CHANGED
@@ -1,2 +1 @@
1
-
2
- module.exports = require('./lib/connect-memcached');
1
+ module.exports = require('./lib/connect-memcached');
@@ -2,8 +2,6 @@
2
2
  * connect-memcached
3
3
  * MIT Licensed
4
4
  */
5
- const bufferFrom = require('buffer-from');
6
-
7
5
  var Memcached = require("memcached");
8
6
  var oneDay = 86400;
9
7
 
@@ -39,16 +37,17 @@ module.exports = function(session) {
39
37
  if (!options.hosts) {
40
38
  options.hosts = "127.0.0.1:11211";
41
39
  }
42
- if (options.secret) {
43
- (this.crypto = require("crypto")), (this.secret = options.secret);
44
- }
45
- if (options.algorithm) {
46
- this.algorithm = options.algorithm;
47
- }
48
40
 
49
41
  options.client = new Memcached(options.hosts, options);
50
42
  }
51
43
 
44
+ if (options.secret) {
45
+ options.algorithm = options.algorithm || 'aes-256-gcm';
46
+ options.hashing = options.hashing || 'sha512';
47
+ this.kruptein = require("kruptein")(options);
48
+ this.secret = options.secret;
49
+ }
50
+
52
51
  this.client = options.client;
53
52
  }
54
53
 
@@ -72,7 +71,8 @@ module.exports = function(session) {
72
71
  * @api public
73
72
  */
74
73
  MemcachedStore.prototype.get = function(sid, fn) {
75
- (secret = this.secret), (self = this), (sid = this.getKey(sid));
74
+ var self = this, sid = this.getKey(sid),
75
+ parseable_string;
76
76
 
77
77
  this.client.get(sid, function(err, data) {
78
78
  if (err) {
@@ -82,13 +82,20 @@ module.exports = function(session) {
82
82
  if (!data) {
83
83
  return fn();
84
84
  }
85
- if (secret) {
86
- parseable_string = decryptData.call(self, data.toString());
85
+
86
+ if (self.secret) {
87
+ self.kruptein.get(self.secret, data, function(err, ct) {
88
+ if (err) {
89
+ return fn(err, {});
90
+ }
91
+
92
+ parseable_string = JSON.parse(ct);
93
+ });
87
94
  } else {
88
- parseable_string = data.toString();
95
+ parseable_string = data;
89
96
  }
90
97
 
91
- fn(null, JSON.parse(parseable_string));
98
+ fn(null, parseable_string);
92
99
  } catch (e) {
93
100
  fn(e);
94
101
  }
@@ -110,16 +117,16 @@ module.exports = function(session) {
110
117
  var maxAge = sess.cookie.maxAge;
111
118
  var ttl =
112
119
  this.ttl || ("number" == typeof maxAge ? (maxAge / 1000) | 0 : oneDay);
113
- var sess = JSON.stringify(
114
- this.secret
115
- ? encryptData.call(
116
- this,
117
- JSON.stringify(sess),
118
- this.secret,
119
- this.algorithm
120
- )
121
- : sess
122
- );
120
+
121
+ if (this.secret) {
122
+ this.kruptein.set(this.secret, sess, function(err, ct) {
123
+ if (err) {
124
+ return fn(err);
125
+ }
126
+
127
+ sess = ct;
128
+ });
129
+ }
123
130
 
124
131
  this.client.set(sid, sess, ttl, ensureCallback(fn));
125
132
  } catch (err) {
@@ -172,70 +179,5 @@ module.exports = function(session) {
172
179
  this.set(sid, sess, fn);
173
180
  };
174
181
 
175
- function encryptData(plaintext) {
176
- var pt = encrypt.call(this, this.secret, plaintext, this.algo),
177
- hmac = digest.call(this, this.secret, pt);
178
-
179
- return {
180
- ct: pt,
181
- mac: hmac
182
- };
183
- }
184
-
185
- function decryptData(ciphertext) {
186
- ciphertext = JSON.parse(ciphertext);
187
-
188
- var hmac = digest.call(this, this.secret, ciphertext.ct);
189
-
190
- if (hmac != ciphertext.mac) {
191
- throw "Encrypted session was tampered with!";
192
- }
193
-
194
- return decrypt.call(this, this.secret, ciphertext.ct, this.algo);
195
- }
196
-
197
- function digest(key, obj) {
198
- var hmac = this.crypto.createHmac("sha512", key);
199
- hmac.setEncoding("hex");
200
- hmac.write(obj);
201
- hmac.end();
202
- return hmac.read();
203
- }
204
-
205
- function encrypt(key, pt, algo) {
206
- algo = algo || "aes-256-ctr";
207
- pt = Buffer.isBuffer(pt) ? pt : new bufferFrom(pt);
208
- var iv = this.crypto.randomBytes(16);
209
- var hashedKey = this.crypto
210
- .createHash("sha256")
211
- .update(key)
212
- .digest();
213
- var cipher = this.crypto.createCipheriv(algo, hashedKey, iv),
214
- ct = [];
215
- ct.push(iv.toString("hex"));
216
- ct.push(cipher.update(pt, "buffer", "hex"));
217
- ct.push(cipher.final("hex"));
218
-
219
- return ct.join("");
220
- }
221
-
222
- function decrypt(key, ct, algo) {
223
- algo = algo || "aes-256-ctr";
224
- var dataBuffer = bufferFrom(ct, "hex");
225
- var iv = dataBuffer.slice(0, 16);
226
- var hashedKey = this.crypto
227
- .createHash("sha256")
228
- .update(key)
229
- .digest();
230
-
231
- var cipher = this.crypto.createDecipheriv(algo, hashedKey, iv),
232
- pt = [];
233
-
234
- pt.push(cipher.update(dataBuffer.slice(16), "hex", "utf8"));
235
- pt.push(cipher.final("utf8"));
236
-
237
- return pt.join("");
238
- }
239
-
240
182
  return MemcachedStore;
241
183
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "connect-memcached",
3
- "version": "1.0.0",
3
+ "version": "3.0.0",
4
4
  "description": "Memcached session store for Connect",
5
5
  "keywords": [
6
6
  "memcached",
@@ -15,11 +15,26 @@
15
15
  "url": "https://github.com/balor/connect-memcached"
16
16
  },
17
17
  "dependencies": {
18
- "buffer-from": "1.1.0",
18
+ "kruptein": "3.1.x",
19
19
  "memcached": "2.2.x"
20
20
  },
21
+ "devDependencies": {
22
+ "express": "^4.17.3",
23
+ "express-session": "^1.17.2",
24
+ "jest": "^27.5.1",
25
+ "supertest": "^6.2.2"
26
+ },
27
+ "scripts": {
28
+ "test": "NODE_ENV=test jest --testTimeout=10000"
29
+ },
30
+ "jest": {
31
+ "testEnvironment": "node",
32
+ "coveragePathIgnorePatterns": [
33
+ "/node_modules/"
34
+ ]
35
+ },
21
36
  "engines": {
22
- "node": ">= 0.10.0"
37
+ "node": ">= 14.0.0"
23
38
  },
24
39
  "license": "MIT",
25
40
  "directories": {
@@ -0,0 +1,40 @@
1
+ const express = require("express"),
2
+ session = require("express-session"),
3
+ app = express(),
4
+ MemcachedStore = require("../../lib/connect-memcached")(session);
5
+
6
+ const memcachedStore = new MemcachedStore({
7
+ hosts: [process.env.MEMCACHED_HOST || "127.0.0.1:11211"],
8
+ prefix: "testapp_",
9
+ });
10
+
11
+ app.use(
12
+ session({
13
+ secret: "TestSecret",
14
+ key: "test",
15
+ proxy: "true",
16
+ resave: false,
17
+ saveUninitialized: false,
18
+ store: memcachedStore,
19
+ })
20
+ );
21
+
22
+ app.get("/", function (req, res) {
23
+ if (req.session.views) {
24
+ ++req.session.views;
25
+ } else {
26
+ req.session.views = 1;
27
+ }
28
+ res.json({ pageviews: req.session.views });
29
+ });
30
+
31
+ if (process.env.NODE_ENV !== "test") {
32
+ app.listen(9341, function () {
33
+ console.log("Listening on %d", this.address().port);
34
+ });
35
+ }
36
+
37
+ module.exports = {
38
+ app: app,
39
+ memcachedStore: memcachedStore,
40
+ };
@@ -0,0 +1,41 @@
1
+ const express = require("express"),
2
+ session = require("express-session"),
3
+ app = express(),
4
+ MemcachedStore = require("../../lib/connect-memcached")(session);
5
+
6
+ const memcachedStore = new MemcachedStore({
7
+ hosts: [process.env.MEMCACHED_HOST || "127.0.0.1:11211"],
8
+ secret: "Hello There Stranger2025!?",
9
+ prefix: "testapp_encrypt_",
10
+ });
11
+
12
+ app.use(
13
+ session({
14
+ secret: "TestEncryptSecret",
15
+ key: "test_encrypt",
16
+ proxy: "true",
17
+ resave: false,
18
+ saveUninitialized: false,
19
+ store: memcachedStore,
20
+ })
21
+ );
22
+
23
+ app.get("/", function (req, res) {
24
+ if (req.session.views) {
25
+ ++req.session.views;
26
+ } else {
27
+ req.session.views = 1;
28
+ }
29
+ res.json({ pageviews: req.session.views });
30
+ });
31
+
32
+ if (process.env.NODE_ENV !== "test") {
33
+ app.listen(9341, function () {
34
+ console.log("Listening on %d", this.address().port);
35
+ });
36
+ }
37
+
38
+ module.exports = {
39
+ app: app,
40
+ memcachedStore: memcachedStore,
41
+ };
@@ -0,0 +1,44 @@
1
+ const express = require("express"),
2
+ session = require("express-session"),
3
+ app = express(),
4
+ Memcached = require("memcached"),
5
+ MemcachedStore = require("../../lib/connect-memcached")(session);
6
+
7
+ const memcachedClient = new Memcached(process.env.MEMCACHED_HOST || "127.0.0.1:11211");
8
+
9
+ const memcachedStore = new MemcachedStore({
10
+ client: memcachedClient,
11
+ prefix: "testapp_encrypt_",
12
+ secret: "Hello There Stranger2025!?",
13
+ });
14
+
15
+ app.use(
16
+ session({
17
+ secret: "TestEncryptSecret",
18
+ key: "test_encrypt",
19
+ proxy: "true",
20
+ resave: false,
21
+ saveUninitialized: false,
22
+ store: memcachedStore,
23
+ })
24
+ );
25
+
26
+ app.get("/", function (req, res) {
27
+ if (req.session.views) {
28
+ ++req.session.views;
29
+ } else {
30
+ req.session.views = 1;
31
+ }
32
+ res.json({ pageviews: req.session.views });
33
+ });
34
+
35
+ if (process.env.NODE_ENV !== "test") {
36
+ app.listen(9341, function () {
37
+ console.log("Listening on %d", this.address().port);
38
+ });
39
+ }
40
+
41
+ module.exports = {
42
+ app: app,
43
+ memcachedStore: memcachedStore,
44
+ };
package/test/test.js ADDED
@@ -0,0 +1,63 @@
1
+ const supertest = require("supertest");
2
+
3
+
4
+ describe("Plain memcached session store", () => {
5
+ const { app, memcachedStore } = require("./services/memcached_basic.js");
6
+ const serverAgent = supertest.agent(app);
7
+
8
+ it("GET / should increment views value at each request", async () => {
9
+ let lastPageView = 0;
10
+ for (var i = 1; i < 50; i++) {
11
+ const res = await serverAgent.get("/");
12
+ expect(res.status).toEqual(200);
13
+ expect(res.type).toEqual(expect.stringContaining("json"));
14
+ expect(res.body.pageviews).toBeGreaterThan(lastPageView);
15
+ lastPageView = res.body.pageviews;
16
+ }
17
+ });
18
+
19
+ afterAll(() => {
20
+ memcachedStore.client.end();
21
+ });
22
+ });
23
+
24
+ describe("Encrypted memcached session store", () => {
25
+ const { app, memcachedStore } = require("./services/memcached_crypt.js");
26
+ const serverAgent = supertest.agent(app);
27
+
28
+ it("GET / should increment views value at each request", async () => {
29
+ let lastPageView = 0;
30
+ for (var i = 1; i < 50; i++) {
31
+ const res = await serverAgent.get("/");
32
+ expect(res.status).toEqual(200);
33
+ expect(res.type).toEqual(expect.stringContaining("json"));
34
+ expect(res.body.pageviews).toBeGreaterThan(lastPageView);
35
+ lastPageView = res.body.pageviews;
36
+ }
37
+ });
38
+
39
+ afterAll(() => {
40
+ memcachedStore.client.end();
41
+ });
42
+ });
43
+
44
+ describe("Encrypted session store using preexising memcached client", () => {
45
+ const { app, memcachedStore } = require("./services/memcached_preexisting_crypt_connection.js");
46
+ const serverAgent = supertest.agent(app);
47
+
48
+ it("GET / should increment views value at each request", async () => {
49
+ let lastPageView = 0;
50
+ for (var i = 1; i < 50; i++) {
51
+ const res = await serverAgent.get("/");
52
+ expect(res.status).toEqual(200);
53
+ expect(res.type).toEqual(expect.stringContaining("json"));
54
+ expect(res.body.pageviews).toBeGreaterThan(lastPageView);
55
+ expect(memcachedStore.kruptein.crypto).toBe(require("crypto"));
56
+ lastPageView = res.body.pageviews;
57
+ }
58
+ });
59
+
60
+ afterAll(() => {
61
+ memcachedStore.client.end();
62
+ });
63
+ });
package/test-all.sh ADDED
@@ -0,0 +1,39 @@
1
+ #!/bin/bash
2
+
3
+ set -e
4
+
5
+ echo "Starting memcached..."
6
+ docker-compose up -d memcached
7
+ sleep 2
8
+
9
+ NODE_VERSIONS=(14 16 18 20 22 24 25)
10
+ FAILED=()
11
+
12
+ for version in "${NODE_VERSIONS[@]}"; do
13
+ echo ""
14
+ echo "========================================="
15
+ echo "Testing with Node $version"
16
+ echo "========================================="
17
+
18
+ if docker-compose run --rm test-node-$version; then
19
+ echo "✓ Node $version: PASSED"
20
+ else
21
+ echo "✗ Node $version: FAILED"
22
+ FAILED+=($version)
23
+ fi
24
+ done
25
+
26
+ echo ""
27
+ echo "========================================="
28
+ echo "Test Summary"
29
+ echo "========================================="
30
+
31
+ if [ ${#FAILED[@]} -eq 0 ]; then
32
+ echo "✓ All Node versions passed!"
33
+ docker-compose down
34
+ exit 0
35
+ else
36
+ echo "✗ Failed Node versions: ${FAILED[*]}"
37
+ docker-compose down
38
+ exit 1
39
+ fi
package/.npmignore DELETED
@@ -1,2 +0,0 @@
1
- .idea
2
- node_modules
package/tests/test.js DELETED
@@ -1,34 +0,0 @@
1
- var express = require("express"),
2
- session = require("express-session"),
3
- cookieParser = require("cookie-parser"),
4
- http = require("http"),
5
- app = express(),
6
- MemcachedStore = require("../lib/connect-memcached")(session);
7
-
8
- app.use(cookieParser());
9
- app.use(
10
- session({
11
- secret: "TestSecret",
12
- key: "test",
13
- proxy: "true",
14
- resave: false,
15
- saveUninitialized: false,
16
- store: new MemcachedStore({
17
- hosts: ["127.0.0.1:11211"],
18
- prefix: "testapp_"
19
- })
20
- })
21
- );
22
-
23
- app.get("/", function(req, res) {
24
- if (req.session.views) {
25
- ++req.session.views;
26
- } else {
27
- req.session.views = 1;
28
- }
29
- res.send("Viewed <strong>" + req.session.views + "</strong> times.");
30
- });
31
-
32
- http.createServer(app).listen(9341, function() {
33
- console.log("Listening on %d", this.address().port);
34
- });
@@ -1,35 +0,0 @@
1
- var express = require("express"),
2
- session = require("express-session"),
3
- cookieParser = require("cookie-parser"),
4
- http = require("http"),
5
- app = express(),
6
- MemcachedStore = require("../lib/connect-memcached")(session);
7
-
8
- app.use(cookieParser());
9
- app.use(
10
- session({
11
- secret: "TestEncryptSecret",
12
- key: "test_encrypt",
13
- proxy: "true",
14
- resave: false,
15
- saveUninitialized: false,
16
- store: new MemcachedStore({
17
- hosts: ["127.0.0.1:11211"],
18
- secret: "Hello there stranger!",
19
- prefix: "testapp_encrypt_"
20
- })
21
- })
22
- );
23
-
24
- app.get("/", function(req, res) {
25
- if (req.session.views) {
26
- ++req.session.views;
27
- } else {
28
- req.session.views = 1;
29
- }
30
- res.send("Viewed <strong>" + req.session.views + "</strong> times.");
31
- });
32
-
33
- http.createServer(app).listen(9341, function() {
34
- console.log("Listening on %d", this.address().port);
35
- });