Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
81146 views
1
/*!
2
* Copyright (c) 2015, Salesforce.com, Inc.
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions are met:
7
*
8
* 1. Redistributions of source code must retain the above copyright notice,
9
* this list of conditions and the following disclaimer.
10
*
11
* 2. Redistributions in binary form must reproduce the above copyright notice,
12
* this list of conditions and the following disclaimer in the documentation
13
* and/or other materials provided with the distribution.
14
*
15
* 3. Neither the name of Salesforce.com nor the names of its contributors may
16
* be used to endorse or promote products derived from this software without
17
* specific prior written permission.
18
*
19
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
* POSSIBILITY OF SUCH DAMAGE.
30
*/
31
'use strict';
32
var vows = require('vows');
33
var assert = require('assert');
34
var async = require('async');
35
var tough = require('../lib/cookie');
36
var Cookie = tough.Cookie;
37
var CookieJar = tough.CookieJar;
38
39
var atNow = Date.now();
40
41
function at(offset) {
42
return {now: new Date(atNow + offset)};
43
}
44
45
vows
46
.describe('CookieJar')
47
.addBatch({
48
"Setting a basic cookie": {
49
topic: function () {
50
var cj = new CookieJar();
51
var c = Cookie.parse("a=b; Domain=example.com; Path=/");
52
assert.strictEqual(c.hostOnly, null);
53
assert.instanceOf(c.creation, Date);
54
assert.strictEqual(c.lastAccessed, null);
55
c.creation = new Date(Date.now() - 10000);
56
cj.setCookie(c, 'http://example.com/index.html', this.callback);
57
},
58
"works": function (c) {
59
assert.instanceOf(c, Cookie)
60
}, // C is for Cookie, good enough for me
61
"gets timestamped": function (c) {
62
assert.ok(c.creation);
63
assert.ok(Date.now() - c.creation.getTime() < 5000); // recently stamped
64
assert.ok(c.lastAccessed);
65
assert.equal(c.creation, c.lastAccessed);
66
assert.equal(c.TTL(), Infinity);
67
assert.ok(!c.isPersistent());
68
}
69
},
70
"Setting a no-path cookie": {
71
topic: function () {
72
var cj = new CookieJar();
73
var c = Cookie.parse("a=b; Domain=example.com");
74
assert.strictEqual(c.hostOnly, null);
75
assert.instanceOf(c.creation, Date);
76
assert.strictEqual(c.lastAccessed, null);
77
c.creation = new Date(Date.now() - 10000);
78
cj.setCookie(c, 'http://example.com/index.html', this.callback);
79
},
80
"domain": function (c) {
81
assert.equal(c.domain, 'example.com')
82
},
83
"path is /": function (c) {
84
assert.equal(c.path, '/')
85
},
86
"path was derived": function (c) {
87
assert.strictEqual(c.pathIsDefault, true)
88
}
89
},
90
"Setting a cookie already marked as host-only": {
91
topic: function () {
92
var cj = new CookieJar();
93
var c = Cookie.parse("a=b; Domain=example.com");
94
assert.strictEqual(c.hostOnly, null);
95
assert.instanceOf(c.creation, Date);
96
assert.strictEqual(c.lastAccessed, null);
97
c.creation = new Date(Date.now() - 10000);
98
c.hostOnly = true;
99
cj.setCookie(c, 'http://example.com/index.html', this.callback);
100
},
101
"domain": function (c) {
102
assert.equal(c.domain, 'example.com')
103
},
104
"still hostOnly": function (c) {
105
assert.strictEqual(c.hostOnly, true)
106
}
107
},
108
"Setting a session cookie": {
109
topic: function () {
110
var cj = new CookieJar();
111
var c = Cookie.parse("a=b");
112
assert.strictEqual(c.path, null);
113
cj.setCookie(c, 'http://www.example.com/dir/index.html', this.callback);
114
},
115
"works": function (c) {
116
assert.instanceOf(c, Cookie)
117
},
118
"gets the domain": function (c) {
119
assert.equal(c.domain, 'www.example.com')
120
},
121
"gets the default path": function (c) {
122
assert.equal(c.path, '/dir')
123
},
124
"is 'hostOnly'": function (c) {
125
assert.ok(c.hostOnly)
126
}
127
},
128
"Setting wrong domain cookie": {
129
topic: function () {
130
var cj = new CookieJar();
131
var c = Cookie.parse("a=b; Domain=fooxample.com; Path=/");
132
cj.setCookie(c, 'http://example.com/index.html', this.callback);
133
},
134
"fails": function (err, c) {
135
assert.ok(err.message.match(/domain/i));
136
assert.ok(!c);
137
}
138
},
139
"Setting sub-domain cookie": {
140
topic: function () {
141
var cj = new CookieJar();
142
var c = Cookie.parse("a=b; Domain=www.example.com; Path=/");
143
cj.setCookie(c, 'http://example.com/index.html', this.callback);
144
},
145
"fails": function (err, c) {
146
assert.ok(err.message.match(/domain/i));
147
assert.ok(!c);
148
}
149
},
150
"Setting super-domain cookie": {
151
topic: function () {
152
var cj = new CookieJar();
153
var c = Cookie.parse("a=b; Domain=example.com; Path=/");
154
cj.setCookie(c, 'http://www.app.example.com/index.html', this.callback);
155
},
156
"success": function (err, c) {
157
assert.ok(!err);
158
assert.equal(c.domain, 'example.com');
159
}
160
},
161
"Setting a sub-path cookie on a super-domain": {
162
topic: function () {
163
var cj = new CookieJar();
164
var c = Cookie.parse("a=b; Domain=example.com; Path=/subpath");
165
assert.strictEqual(c.hostOnly, null);
166
assert.instanceOf(c.creation, Date);
167
assert.strictEqual(c.lastAccessed, null);
168
c.creation = new Date(Date.now() - 10000);
169
cj.setCookie(c, 'http://www.example.com/index.html', this.callback);
170
},
171
"domain is super-domain": function (c) {
172
assert.equal(c.domain, 'example.com')
173
},
174
"path is /subpath": function (c) {
175
assert.equal(c.path, '/subpath')
176
},
177
"path was NOT derived": function (c) {
178
assert.strictEqual(c.pathIsDefault, null)
179
}
180
},
181
"Setting HttpOnly cookie over non-HTTP API": {
182
topic: function () {
183
var cj = new CookieJar();
184
var c = Cookie.parse("a=b; Domain=example.com; Path=/; HttpOnly");
185
cj.setCookie(c, 'http://example.com/index.html', {http: false}, this.callback);
186
},
187
"fails": function (err, c) {
188
assert.match(err.message, /HttpOnly/i);
189
assert.ok(!c);
190
}
191
}
192
})
193
.addBatch({
194
"Store eight cookies": {
195
topic: function () {
196
var cj = new CookieJar();
197
var ex = 'http://example.com/index.html';
198
var tasks = [];
199
tasks.push(function (next) {
200
cj.setCookie('a=1; Domain=example.com; Path=/', ex, at(0), next);
201
});
202
tasks.push(function (next) {
203
cj.setCookie('b=2; Domain=example.com; Path=/; HttpOnly', ex, at(1000), next);
204
});
205
tasks.push(function (next) {
206
cj.setCookie('c=3; Domain=example.com; Path=/; Secure', ex, at(2000), next);
207
});
208
tasks.push(function (next) { // path
209
cj.setCookie('d=4; Domain=example.com; Path=/foo', ex, at(3000), next);
210
});
211
tasks.push(function (next) { // host only
212
cj.setCookie('e=5', ex, at(4000), next);
213
});
214
tasks.push(function (next) { // other domain
215
cj.setCookie('f=6; Domain=nodejs.org; Path=/', 'http://nodejs.org', at(5000), next);
216
});
217
tasks.push(function (next) { // expired
218
cj.setCookie('g=7; Domain=example.com; Path=/; Expires=Tue, 18 Oct 2011 00:00:00 GMT', ex, at(6000), next);
219
});
220
tasks.push(function (next) { // expired via Max-Age
221
cj.setCookie('h=8; Domain=example.com; Path=/; Max-Age=1', ex, next);
222
});
223
var cb = this.callback;
224
async.parallel(tasks, function (err, results) {
225
setTimeout(function () {
226
cb(err, cj, results);
227
}, 2000); // so that 'h=8' expires
228
});
229
},
230
"setup ok": function (err, cj, results) {
231
assert.ok(!err);
232
assert.ok(cj);
233
assert.ok(results);
234
},
235
"then retrieving for http://nodejs.org": {
236
topic: function (cj, oldResults) {
237
assert.ok(oldResults);
238
cj.getCookies('http://nodejs.org', this.callback);
239
},
240
"get a nodejs cookie": function (cookies) {
241
assert.lengthOf(cookies, 1);
242
var cookie = cookies[0];
243
assert.equal(cookie.domain, 'nodejs.org');
244
}
245
},
246
"then retrieving for https://example.com": {
247
topic: function (cj, oldResults) {
248
assert.ok(oldResults);
249
cj.getCookies('https://example.com', {secure: true}, this.callback);
250
},
251
"get a secure example cookie with others": function (cookies) {
252
var names = cookies.map(function (c) {
253
return c.key
254
});
255
assert.deepEqual(names, ['a', 'b', 'c', 'e']);
256
}
257
},
258
"then retrieving for https://example.com (missing options)": {
259
topic: function (cj, oldResults) {
260
assert.ok(oldResults);
261
cj.getCookies('https://example.com', this.callback);
262
},
263
"get a secure example cookie with others": function (cookies) {
264
var names = cookies.map(function (c) {
265
return c.key
266
});
267
assert.deepEqual(names, ['a', 'b', 'c', 'e']);
268
}
269
},
270
"then retrieving for http://example.com": {
271
topic: function (cj, oldResults) {
272
assert.ok(oldResults);
273
cj.getCookies('http://example.com', this.callback);
274
},
275
"get a bunch of cookies": function (cookies) {
276
var names = cookies.map(function (c) {
277
return c.key
278
});
279
assert.deepEqual(names, ['a', 'b', 'e']);
280
}
281
},
282
"then retrieving for http://EXAMPlE.com": {
283
topic: function (cj, oldResults) {
284
assert.ok(oldResults);
285
cj.getCookies('http://EXAMPlE.com', this.callback);
286
},
287
"get a bunch of cookies": function (cookies) {
288
var names = cookies.map(function (c) {
289
return c.key
290
});
291
assert.deepEqual(names, ['a', 'b', 'e']);
292
}
293
},
294
"then retrieving for http://example.com, non-HTTP": {
295
topic: function (cj, oldResults) {
296
assert.ok(oldResults);
297
cj.getCookies('http://example.com', {http: false}, this.callback);
298
},
299
"get a bunch of cookies": function (cookies) {
300
var names = cookies.map(function (c) {
301
return c.key
302
});
303
assert.deepEqual(names, ['a', 'e']);
304
}
305
},
306
"then retrieving for http://example.com/foo/bar": {
307
topic: function (cj, oldResults) {
308
assert.ok(oldResults);
309
cj.getCookies('http://example.com/foo/bar', this.callback);
310
},
311
"get a bunch of cookies": function (cookies) {
312
var names = cookies.map(function (c) {
313
return c.key
314
});
315
assert.deepEqual(names, ['d', 'a', 'b', 'e']);
316
}
317
},
318
"then retrieving for http://example.com as a string": {
319
topic: function (cj, oldResults) {
320
assert.ok(oldResults);
321
cj.getCookieString('http://example.com', this.callback);
322
},
323
"get a single string": function (cookieHeader) {
324
assert.equal(cookieHeader, "a=1; b=2; e=5");
325
}
326
},
327
"then retrieving for http://example.com as a set-cookie header": {
328
topic: function (cj, oldResults) {
329
assert.ok(oldResults);
330
cj.getSetCookieStrings('http://example.com', this.callback);
331
},
332
"get a single string": function (cookieHeaders) {
333
assert.lengthOf(cookieHeaders, 3);
334
assert.equal(cookieHeaders[0], "a=1; Domain=example.com; Path=/");
335
assert.equal(cookieHeaders[1], "b=2; Domain=example.com; Path=/; HttpOnly");
336
assert.equal(cookieHeaders[2], "e=5; Path=/");
337
}
338
},
339
"then retrieving for http://www.example.com/": {
340
topic: function (cj, oldResults) {
341
assert.ok(oldResults);
342
cj.getCookies('http://www.example.com/foo/bar', this.callback);
343
},
344
"get a bunch of cookies": function (cookies) {
345
var names = cookies.map(function (c) {
346
return c.key
347
});
348
assert.deepEqual(names, ['d', 'a', 'b']); // note lack of 'e'
349
}
350
}
351
}
352
})
353
.addBatch({
354
"Repeated names": {
355
topic: function () {
356
var cb = this.callback;
357
var cj = new CookieJar();
358
var ex = 'http://www.example.com/';
359
var sc = cj.setCookie;
360
var tasks = [];
361
var now = Date.now();
362
tasks.push(sc.bind(cj, 'aaaa=xxxx', ex, at(0)));
363
tasks.push(sc.bind(cj, 'aaaa=1111; Domain=www.example.com', ex, at(1000)));
364
tasks.push(sc.bind(cj, 'aaaa=2222; Domain=example.com', ex, at(2000)));
365
tasks.push(sc.bind(cj, 'aaaa=3333; Domain=www.example.com; Path=/pathA', ex, at(3000)));
366
async.series(tasks, function (err, results) {
367
results = results.filter(function (e) {
368
return e !== undefined
369
});
370
cb(err, {cj: cj, cookies: results, now: now});
371
});
372
},
373
"all got set": function (err, t) {
374
assert.lengthOf(t.cookies, 4);
375
},
376
"then getting 'em back": {
377
topic: function (t) {
378
var cj = t.cj;
379
cj.getCookies('http://www.example.com/pathA', this.callback);
380
},
381
"there's just three": function (err, cookies) {
382
var vals = cookies.map(function (c) {
383
return c.value
384
});
385
// may break with sorting; sorting should put 3333 first due to longest path:
386
assert.deepEqual(vals, ['3333', '1111', '2222']);
387
}
388
}
389
}
390
})
391
.addBatch({
392
"CookieJar setCookie errors": {
393
"public-suffix domain": {
394
topic: function () {
395
var cj = new CookieJar();
396
cj.setCookie('i=9; Domain=kyoto.jp; Path=/', 'kyoto.jp', this.callback);
397
},
398
"errors": function (err, cookie) {
399
assert.ok(err);
400
assert.ok(!cookie);
401
assert.match(err.message, /public suffix/i);
402
}
403
},
404
"wrong domain": {
405
topic: function () {
406
var cj = new CookieJar();
407
cj.setCookie('j=10; Domain=google.com; Path=/', 'http://google.ca', this.callback);
408
},
409
"errors": function (err, cookie) {
410
assert.ok(err);
411
assert.ok(!cookie);
412
assert.match(err.message, /not in this host's domain/i);
413
}
414
},
415
"old cookie is HttpOnly": {
416
topic: function () {
417
var cb = this.callback;
418
var next = function (err, c) {
419
c = null;
420
return cb(err, cj);
421
};
422
var cj = new CookieJar();
423
cj.setCookie('k=11; Domain=example.ca; Path=/; HttpOnly', 'http://example.ca', {http: true}, next);
424
},
425
"initial cookie is set": function (err, cj) {
426
assert.ok(!err);
427
assert.ok(cj);
428
},
429
"but when trying to overwrite": {
430
topic: function (cj) {
431
var cb = this.callback;
432
var next = function (err, c) {
433
c = null;
434
cb(null, err);
435
};
436
cj.setCookie('k=12; Domain=example.ca; Path=/', 'http://example.ca', {http: false}, next);
437
},
438
"it's an error": function (err) {
439
assert.ok(err);
440
},
441
"then, checking the original": {
442
topic: function (ignored, cj) {
443
assert.ok(cj instanceof CookieJar);
444
cj.getCookies('http://example.ca', {http: true}, this.callback);
445
},
446
"cookie has original value": function (err, cookies) {
447
assert.equal(err, null);
448
assert.lengthOf(cookies, 1);
449
assert.equal(cookies[0].value, 11);
450
}
451
}
452
}
453
},
454
"similar to public suffix": {
455
topic: function () {
456
var cj = new CookieJar();
457
var url = 'http://www.foonet.net';
458
assert.isTrue(cj.rejectPublicSuffixes);
459
cj.setCookie('l=13; Domain=foonet.net; Path=/', url, this.callback);
460
},
461
"doesn't error": function (err, cookie) {
462
assert.ok(!err);
463
assert.ok(cookie);
464
}
465
}
466
}
467
})
468
.export(module);
469
470