235 lines
10 KiB
JavaScript
235 lines
10 KiB
JavaScript
|
"use strict";
|
||
|
var __rest = (this && this.__rest) || function (s, e) {
|
||
|
var t = {};
|
||
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
||
|
t[p] = s[p];
|
||
|
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
||
|
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
||
|
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
||
|
t[p[i]] = s[p[i]];
|
||
|
}
|
||
|
return t;
|
||
|
};
|
||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||
|
};
|
||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||
|
const tough_cookie_1 = require("tough-cookie");
|
||
|
const cookie_limit_1 = __importDefault(require("./cookie-limit"));
|
||
|
const lodash_1 = require("lodash");
|
||
|
const url_1 = require("../utils/url");
|
||
|
const json_1 = require("../utils/json");
|
||
|
const url_2 = require("url");
|
||
|
const cookie_1 = require("../utils/cookie");
|
||
|
const LOCALHOST_DOMAIN = 'localhost';
|
||
|
const LOCALHOST_IP = '127.0.0.1';
|
||
|
class Cookies {
|
||
|
constructor() {
|
||
|
this._cookieJar = new tough_cookie_1.CookieJar();
|
||
|
this._findCookieSync = this._syncWrap('findCookie');
|
||
|
this._findCookiesSync = this._syncWrap('findCookies');
|
||
|
this._getAllCookiesSync = this._syncWrap('getAllCookies');
|
||
|
this._putCookieSync = this._syncWrap('putCookie');
|
||
|
this._removeCookieSync = this._syncWrap('removeCookie');
|
||
|
this._removeAllCookiesSync = this._syncWrap('removeAllCookies');
|
||
|
this._pendingSyncCookies = [];
|
||
|
}
|
||
|
_syncWrap(method) {
|
||
|
return (...args) => {
|
||
|
let syncErr;
|
||
|
let syncResult;
|
||
|
this._cookieJar.store[method](...args, (err, result) => {
|
||
|
syncErr = err;
|
||
|
syncResult = result;
|
||
|
});
|
||
|
if (syncErr)
|
||
|
throw syncErr;
|
||
|
return syncResult;
|
||
|
};
|
||
|
}
|
||
|
static _hasLocalhostDomain(cookie) {
|
||
|
if (cookie)
|
||
|
return this._isLocalHostDomain(cookie.domain);
|
||
|
return false;
|
||
|
}
|
||
|
_set(url, cookies, isClient) {
|
||
|
cookies = (0, lodash_1.castArray)(cookies);
|
||
|
return cookies.reduce((resultCookies, cookieStr) => {
|
||
|
let cookie;
|
||
|
if (!isClient) {
|
||
|
if (cookieStr.length > cookie_limit_1.default)
|
||
|
return resultCookies;
|
||
|
cookie = tough_cookie_1.Cookie.parse(cookieStr, { loose: true });
|
||
|
if (!cookie)
|
||
|
return resultCookies;
|
||
|
}
|
||
|
else
|
||
|
cookie = cookieStr;
|
||
|
// NOTE: If cookie.domain and url hostname are equal to localhost/127.0.0.1,
|
||
|
// we should remove 'Domain=...' form cookieStr (GH-1491)
|
||
|
if (Cookies._hasLocalhostDomain(cookie) && (isClient || (0, url_1.parseUrl)(url).hostname === cookie.domain))
|
||
|
cookie.domain = '';
|
||
|
const parsedCookie = this._cookieJar.setCookieSync(cookie, url, {
|
||
|
http: !isClient,
|
||
|
ignoreError: true,
|
||
|
loose: true,
|
||
|
});
|
||
|
if (parsedCookie)
|
||
|
resultCookies.push(parsedCookie);
|
||
|
return resultCookies;
|
||
|
}, []);
|
||
|
}
|
||
|
serializeJar() {
|
||
|
return (0, json_1.stringify)(this._cookieJar.serializeSync());
|
||
|
}
|
||
|
setJar(serializedJar) {
|
||
|
this._cookieJar = serializedJar
|
||
|
? tough_cookie_1.CookieJar.deserializeSync((0, json_1.parse)(serializedJar))
|
||
|
: new tough_cookie_1.CookieJar();
|
||
|
}
|
||
|
_convertToExternalCookies(internalCookies) {
|
||
|
return internalCookies.map(cookie => {
|
||
|
const { key, value, domain, path, expires, maxAge, secure, httpOnly, sameSite, } = cookie;
|
||
|
return {
|
||
|
name: key,
|
||
|
domain: domain || void 0,
|
||
|
path: path || void 0,
|
||
|
expires: expires === 'Infinity' ? void 0 : expires,
|
||
|
maxAge: maxAge || void 0,
|
||
|
value, secure, httpOnly, sameSite,
|
||
|
};
|
||
|
});
|
||
|
}
|
||
|
_convertToCookieProperties(externalCookie) {
|
||
|
return externalCookie.map(cookie => {
|
||
|
const { name } = cookie, rest = __rest(cookie, ["name"]);
|
||
|
return name ? Object.assign({ key: name }, rest) : rest;
|
||
|
});
|
||
|
}
|
||
|
_findCookiesByApi(urls, key) {
|
||
|
return urls.map(({ domain, path }) => {
|
||
|
const cookies = key
|
||
|
? this._findCookieSync(domain, path, key)
|
||
|
: this._findCookiesSync(domain, path);
|
||
|
return cookies || [];
|
||
|
});
|
||
|
}
|
||
|
_filterCookies(cookies, filters) {
|
||
|
const filterKeys = Object.keys(filters);
|
||
|
return cookies.filter(cookie => filterKeys.every(key => cookie[key] === filters[key]));
|
||
|
}
|
||
|
_getCookiesByApi(cookie, urls, strict = false) {
|
||
|
const { key, domain, path } = cookie, filters = __rest(cookie, ["key", "domain", "path"]);
|
||
|
const currentUrls = domain && path ? [{ domain, path }] : urls;
|
||
|
let receivedCookies;
|
||
|
if ((currentUrls === null || currentUrls === void 0 ? void 0 : currentUrls[0]) && (!strict || key))
|
||
|
receivedCookies = (0, lodash_1.flattenDeep)(this._findCookiesByApi(currentUrls, key));
|
||
|
else {
|
||
|
receivedCookies = (0, lodash_1.flattenDeep)(this._getAllCookiesSync());
|
||
|
Object.assign(filters, cookie);
|
||
|
}
|
||
|
return Object.keys(filters).length ? this._filterCookies(receivedCookies, filters) : receivedCookies;
|
||
|
}
|
||
|
getCookies(externalCookies, urls = []) {
|
||
|
let resultCookies = [];
|
||
|
if (!externalCookies || !externalCookies.length)
|
||
|
resultCookies = this._getAllCookiesSync();
|
||
|
else {
|
||
|
const parsedUrls = urls.map(url => {
|
||
|
const { hostname, pathname } = new url_2.URL(url);
|
||
|
return { domain: hostname, path: pathname };
|
||
|
});
|
||
|
const cookies = this._convertToCookieProperties(externalCookies);
|
||
|
for (const cookie of cookies) {
|
||
|
const receivedCookies = this._getCookiesByApi(cookie, parsedUrls);
|
||
|
resultCookies.push(...receivedCookies);
|
||
|
}
|
||
|
}
|
||
|
return this._convertToExternalCookies(resultCookies);
|
||
|
}
|
||
|
setCookies(externalCookies, url) {
|
||
|
const cookies = this._convertToCookieProperties(externalCookies);
|
||
|
const { hostname = '', pathname = '/' } = url ? new url_2.URL(url) : {};
|
||
|
for (const cookie of cookies) {
|
||
|
if (!cookie.domain && !cookie.path)
|
||
|
Object.assign(cookie, { domain: hostname, path: pathname });
|
||
|
const cookieToSet = new tough_cookie_1.Cookie(cookie);
|
||
|
const cookieStr = cookieToSet.toString();
|
||
|
if (cookieStr.length > cookie_limit_1.default)
|
||
|
break;
|
||
|
this._putCookieSync(cookieToSet);
|
||
|
this._pendingSyncCookies.push(cookieToSet);
|
||
|
}
|
||
|
}
|
||
|
deleteCookies(externalCookies, urls = []) {
|
||
|
if (!externalCookies || !externalCookies.length) {
|
||
|
const deletedCookies = this._getAllCookiesSync();
|
||
|
this._pendingSyncCookies.push(...deletedCookies);
|
||
|
return this._removeAllCookiesSync();
|
||
|
}
|
||
|
const parsedUrls = urls.map(url => {
|
||
|
const { hostname, pathname } = new url_2.URL(url);
|
||
|
return { domain: hostname, path: pathname };
|
||
|
});
|
||
|
const cookies = this._convertToCookieProperties(externalCookies);
|
||
|
for (const cookie of cookies) {
|
||
|
const deletedCookies = this._getCookiesByApi(cookie, parsedUrls, true);
|
||
|
for (const deletedCookie of deletedCookies) {
|
||
|
if (deletedCookie.domain && deletedCookie.path && deletedCookie.key) {
|
||
|
this._removeCookieSync(deletedCookie.domain, deletedCookie.path, deletedCookie.key);
|
||
|
deletedCookie.expires = new Date(0);
|
||
|
this._pendingSyncCookies.push(deletedCookie);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
takePendingSyncCookies() {
|
||
|
const cookies = this._pendingSyncCookies;
|
||
|
this._pendingSyncCookies = [];
|
||
|
return cookies;
|
||
|
}
|
||
|
setByServer(url, cookies) {
|
||
|
return this._set(url, cookies, false);
|
||
|
}
|
||
|
setByClient(syncCookies) {
|
||
|
for (const syncCookie of syncCookies) {
|
||
|
const cookie = new tough_cookie_1.Cookie(syncCookie);
|
||
|
const url = { hostname: syncCookie.domain, pathname: syncCookie.path };
|
||
|
this._set(url, cookie, true);
|
||
|
}
|
||
|
}
|
||
|
copySyncCookies(syncCookie, toUrl) {
|
||
|
let hostname;
|
||
|
let pathname;
|
||
|
try {
|
||
|
({ hostname, pathname } = new url_2.URL(toUrl));
|
||
|
}
|
||
|
catch (e) {
|
||
|
return;
|
||
|
}
|
||
|
const { actual: cookies } = (0, cookie_1.parseClientSyncCookieStr)(syncCookie);
|
||
|
for (const cookie of cookies) {
|
||
|
const { domain, path, key } = cookie;
|
||
|
const originCookie = this._findCookieSync(domain, path, key);
|
||
|
const newCookie = new tough_cookie_1.Cookie(Object.assign({}, originCookie, { domain: hostname, path: pathname }));
|
||
|
this._putCookieSync(newCookie);
|
||
|
this._pendingSyncCookies.push(newCookie);
|
||
|
}
|
||
|
}
|
||
|
getClientString(url) {
|
||
|
return this._cookieJar.getCookieStringSync(url, { http: false });
|
||
|
}
|
||
|
getHeader({ url, hostname }) {
|
||
|
// NOTE: https://github.com/DevExpress/testcafe-hammerhead/issues/2715
|
||
|
// Cookies with the secure attribute should be passed to the localhost server(without ssl) or any other server(with ssl).
|
||
|
// CookieJar only checks the protocol, but not a hostname. That is why we should to add secure attribute in case of localhost.
|
||
|
const cookieJarOpts = Cookies._isLocalHostDomain(hostname) ?
|
||
|
{ http: true, secure: true } :
|
||
|
{ http: true };
|
||
|
return this._cookieJar.getCookieStringSync(url, cookieJarOpts) || null;
|
||
|
}
|
||
|
}
|
||
|
exports.default = Cookies;
|
||
|
Cookies._isLocalHostDomain = (domain) => domain === LOCALHOST_DOMAIN || domain === LOCALHOST_IP;module.exports = exports.default;
|
||
|
|