Skip to content

Commit

Permalink
remove all cookies from cookie jar at once (#115)
Browse files Browse the repository at this point in the history
* remove all cookies from jar
* fix typo in readme
* delete cookies one-by-one for old store implementations
  • Loading branch information
YevhenLukomskyi authored and stash committed Nov 26, 2018
1 parent 8783d46 commit 62802ef
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 1 deletion.
14 changes: 13 additions & 1 deletion README.md
Expand Up @@ -198,7 +198,7 @@ compute the TTL relative to `now` (milliseconds). The same precedence rules as

The "number" `Infinity` is returned for cookies without an explicit expiry and `0` is returned if the cookie is expired. Otherwise a time-to-live in milliseconds is returned.

### `.canonicalizedDoman()`
### `.canonicalizedDomain()`

### `.cdomain()`

Expand Down Expand Up @@ -354,6 +354,14 @@ The `store` argument is optional, but must be a _synchronous_ `Store` instance i

The _source_ and _destination_ must both be synchronous `Store`s. If one or both stores are asynchronous, use `.clone` instead. Recall that `MemoryCookieStore` supports both synchronous and asynchronous API calls.

### `.removeAllCookies(cb(err))`

Removes all cookies from the jar.

### `.removeAllCookiesSync()`

Sync version of `.removeAllCookies()`

## Store

Base class for CookieJar stores. Available as `tough.Store`.
Expand Down Expand Up @@ -418,6 +426,10 @@ Removes matching cookies from the store. The `path` parameter is optional, and

Pass an error ONLY if removing any existing cookies failed.

### `.removeAllCookies(cb(err))`

Removes all cookies from the store.

### `store.getAllCookies(cb(err, cookies))`

Produces an `Array` of all cookies during `jar.serialize()`. The items in the array can be true `Cookie` objects or generic `Object`s with the [Serialization Format] data structure.
Expand Down
37 changes: 37 additions & 0 deletions lib/cookie.js
Expand Up @@ -1385,6 +1385,43 @@ CookieJar.prototype.clone = function(newStore, cb) {
});
};

CAN_BE_SYNC.push('removeAllCookies');
CookieJar.prototype.removeAllCookies = function(cb) {
var store = this.store;
if (store.removeAllCookies instanceof Function) {
store.removeAllCookies(cb);
} else {
store.getAllCookies(function(err, cookies) {
if (err) {
return cb(err);
}

if (cookies.length === 0) {
return cb(null);
}

var completedCount = 0;
var removeErrors = [];

function removeCookieCb(removeErr) {
if (removeErr) {
removeErrors.push(removeErr);
}

completedCount++;

if (completedCount === cookies.length) {
return removeErrors.length > 0 ? cb(removeErrors[0]) : cb(null);
}
}

cookies.forEach(function(cookie) {
store.removeCookie(cookie.domain, cookie.path, cookie.key, removeCookieCb);
});
});
}
};

CookieJar.prototype._cloneSync = syncWrap('clone');
CookieJar.prototype.cloneSync = function(newStore) {
if (!newStore.synchronous) {
Expand Down
5 changes: 5 additions & 0 deletions lib/memstore.js
Expand Up @@ -149,6 +149,11 @@ MemoryCookieStore.prototype.removeCookies = function(domain, path, cb) {
return cb(null);
};

MemoryCookieStore.prototype.removeAllCookies = function(cb) {
this.idx = {};
return cb(null);
}

MemoryCookieStore.prototype.getAllCookies = function(cb) {
var cookies = [];
var idx = this.idx;
Expand Down
4 changes: 4 additions & 0 deletions lib/store.js
Expand Up @@ -66,6 +66,10 @@ Store.prototype.removeCookies = function(domain, path, cb) {
throw new Error('removeCookies is not implemented');
};

Store.prototype.removeAllCookies = function(cb) {
throw new Error('removeAllCookies is not implemented');
}

Store.prototype.getAllCookies = function(cb) {
throw new Error('getAllCookies is not implemented (therefore jar cannot be serialized)');
};
38 changes: 38 additions & 0 deletions test/api_test.js
Expand Up @@ -252,6 +252,7 @@ vows
assert.instanceOf(cookie, Cookie);
}
},

"getCookiesSync": {
topic: function () {
var jar = new CookieJar();
Expand Down Expand Up @@ -300,6 +301,27 @@ vows
assert.typeOf(header, 'string');
});
}
},

"removeAllCookiesSync": {
topic: function () {
var jar = new CookieJar();
var cookie1 = Cookie.parse("a=b; Domain=example.com; Path=/");
var cookie2 = Cookie.parse("a=b; Domain=foo.com; Path=/");
var cookie3 = Cookie.parse("foo=bar; Domain=foo.com; Path=/");
jar.setCookieSync(cookie1, 'http://example.com/index.html');
jar.setCookieSync(cookie2, 'http://foo.com/index.html');
jar.setCookieSync(cookie3, 'http://foo.com/index.html');

jar.removeAllCookiesSync();

jar.store.getAllCookies(this.callback)
},
"no cookies in the jar": function (err, cookies) {
assert(err == null);
assert(cookies != null);
assert(cookies.length === 0, 'cookies were not removed')
}
}
}
})
Expand Down Expand Up @@ -371,6 +393,22 @@ vows
assert.equal(err.message,
'CookieJar store is not synchronous; use async API instead.');
}
},
"removeAllCookies": {
topic: function(store) {
var jar = new CookieJar(store);
try {
jar.removeAllCookiesSync();
return false;
} catch (e) {
return e
}
},
"fails": function(err) {
assert.instanceOf(err, Error);
assert.equal(err.message,
'CookieJar store is not synchronous; use async API instead.');
}
}
}
})
Expand Down
61 changes: 61 additions & 0 deletions test/cookie_jar_test.js
Expand Up @@ -480,4 +480,65 @@ vows
}
}
})
.addBatch({
"Remove all cookies": {
topic: function () {
var jar = new CookieJar();
var cookie1 = Cookie.parse("a=b; Domain=example.com; Path=/");
var cookie2 = Cookie.parse("a=b; Domain=foo.com; Path=/");
var cookie3 = Cookie.parse("foo=bar; Domain=foo.com; Path=/");
jar.setCookie(cookie1, 'http://example.com/index.html', function () {});
jar.setCookie(cookie2, 'http://foo.com/index.html', function () {});
jar.setCookie(cookie3, 'http://foo.com/index.html', function () {});

var cb = this.callback;
jar.removeAllCookies(function (err) {
cb(err, jar);
});
},
"no errors": function (err, jar) {
assert(err == null);
},
"load cookies from the jar": {
topic: function(jar) {
jar.store.getAllCookies(this.callback);
},
"no cookies in the jar": function(err, cookies) {
assert(err == null);
assert(cookies != null);
assert(cookies.length === 0, 'cookies were not removed');
}
}
},
"Remove all cookies (the underlying store does not support removeAllCookies)": {
topic: function () {
var jar = new CookieJar();
jar.store.removeAllCookies = undefined;
var cookie1 = Cookie.parse("a=b; Domain=example.com; Path=/");
var cookie2 = Cookie.parse("a=b; Domain=foo.com; Path=/");
var cookie3 = Cookie.parse("foo=bar; Domain=foo.com; Path=/");
jar.setCookie(cookie1, 'http://example.com/index.html', function () {});
jar.setCookie(cookie2, 'http://foo.com/index.html', function () {});
jar.setCookie(cookie3, 'http://foo.com/index.html', function () {});

var cb = this.callback;
jar.removeAllCookies(function (err) {
cb(err, jar);
});
},
"no errors": function (err, jar) {
assert(err == null);
},
"load cookies from the jar": {
topic: function(jar) {
jar.store.getAllCookies(this.callback);
},
"no cookies in the jar": function(err, cookies) {
assert(err == null);
assert(cookies != null);
assert(cookies.length === 0, 'cookies were not removed');
}
}
}
})
.export(module);

0 comments on commit 62802ef

Please sign in to comment.