135 lines
6.4 KiB
JavaScript
135 lines
6.4 KiB
JavaScript
|
"use strict";
|
||
|
// -------------------------------------------------------------
|
||
|
// WARNING: this file is used by both the client and the server.
|
||
|
// Do not use any browser or node-specific API!
|
||
|
// -------------------------------------------------------------
|
||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||
|
};
|
||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||
|
exports.generateDeleteSyncCookieStr = exports.isOutdatedSyncCookie = exports.changeSyncType = exports.parseSyncCookie = exports.formatSyncCookie = exports.prepareSyncCookieProperties = exports.parseClientSyncCookieStr = exports.SYNCHRONIZATION_TYPE = void 0;
|
||
|
const string_trim_1 = __importDefault(require("./string-trim"));
|
||
|
const lodash_1 = require("lodash");
|
||
|
const TIME_RADIX = 36;
|
||
|
const CLEAR_COOKIE_VALUE_STR = '=;path=/;expires=Thu, 01 Jan 1970 00:00:01 GMT';
|
||
|
const CLIENT_COOKIE_SYNC_KEY_FRAGMENT_COUNT = 8;
|
||
|
const KEY_VALUE_REGEX = /(?:^([^=]+)=([\s\S]*))?/;
|
||
|
exports.SYNCHRONIZATION_TYPE = {
|
||
|
server: 's',
|
||
|
client: 'c',
|
||
|
window: 'w',
|
||
|
};
|
||
|
const SYNCHRONIZATION_TYPE_RE = new RegExp(`^[${exports.SYNCHRONIZATION_TYPE.server}${exports.SYNCHRONIZATION_TYPE.client}${exports.SYNCHRONIZATION_TYPE.window}]+`);
|
||
|
function isSameCookies(cookie1, cookie2) {
|
||
|
return cookie1.sid === cookie2.sid &&
|
||
|
cookie1.key === cookie2.key &&
|
||
|
cookie1.domain === cookie2.domain &&
|
||
|
cookie1.path === cookie2.path;
|
||
|
}
|
||
|
function sortByOutdatedAndActual(parsedCookies) {
|
||
|
const outdated = [];
|
||
|
const actual = [];
|
||
|
for (let current = 0; current < parsedCookies.length; current++) {
|
||
|
let other = current + 1;
|
||
|
for (; other < parsedCookies.length; other++) {
|
||
|
if (isSameCookies(parsedCookies[current], parsedCookies[other])) {
|
||
|
if (parsedCookies[current].lastAccessed > parsedCookies[other].lastAccessed) {
|
||
|
const temp = parsedCookies[current];
|
||
|
parsedCookies[current] = parsedCookies[other];
|
||
|
parsedCookies[other] = temp;
|
||
|
}
|
||
|
outdated.push(parsedCookies[current]);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (other === parsedCookies.length)
|
||
|
actual.push(parsedCookies[current]);
|
||
|
}
|
||
|
return { outdated, actual };
|
||
|
}
|
||
|
function stringifySyncType(cookie) {
|
||
|
return (cookie.isServerSync ? exports.SYNCHRONIZATION_TYPE.server : '') +
|
||
|
(cookie.isClientSync ? exports.SYNCHRONIZATION_TYPE.client : '') +
|
||
|
(cookie.isWindowSync ? exports.SYNCHRONIZATION_TYPE.window : '');
|
||
|
}
|
||
|
function formatSyncCookieKey(cookie) {
|
||
|
const syncType = stringifySyncType(cookie);
|
||
|
const key = encodeURIComponent(cookie.key);
|
||
|
const domain = encodeURIComponent(cookie.domain);
|
||
|
const path = encodeURIComponent(cookie.path);
|
||
|
const expires = cookie.expires !== 'Infinity' ? cookie.expires.getTime().toString(TIME_RADIX) : '';
|
||
|
const lastAccessed = cookie.lastAccessed.getTime().toString(TIME_RADIX);
|
||
|
const maxAge = !(0, lodash_1.isNil)(cookie.maxAge) && !isNaN(Number(cookie.maxAge)) && String(cookie.maxAge) !== 'Infinity' ? cookie.maxAge.toString(TIME_RADIX) : '';
|
||
|
return `${syncType}|${cookie.sid}|${key}|${domain}|${path}|${expires}|${lastAccessed}|${maxAge}`;
|
||
|
}
|
||
|
function parseClientSyncCookieStr(cookieStr) {
|
||
|
const cookies = cookieStr ? cookieStr.split(';') : '';
|
||
|
const parsedCookies = [];
|
||
|
for (const cookie of cookies) {
|
||
|
const parsedCookie = parseSyncCookie((0, string_trim_1.default)(cookie));
|
||
|
if (parsedCookie)
|
||
|
parsedCookies.push(parsedCookie);
|
||
|
}
|
||
|
return sortByOutdatedAndActual(parsedCookies);
|
||
|
}
|
||
|
exports.parseClientSyncCookieStr = parseClientSyncCookieStr;
|
||
|
function prepareSyncCookieProperties(cookie) {
|
||
|
cookie.syncKey = cookie.syncKey || formatSyncCookieKey(cookie);
|
||
|
cookie.cookieStr = cookie.cookieStr || `${cookie.syncKey}=${cookie.value}`;
|
||
|
}
|
||
|
exports.prepareSyncCookieProperties = prepareSyncCookieProperties;
|
||
|
function formatSyncCookie(cookie) {
|
||
|
if (cookie.cookieStr)
|
||
|
return `${cookie.cookieStr};path=/`;
|
||
|
return `${formatSyncCookieKey(cookie)}=${cookie.value};path=/`;
|
||
|
}
|
||
|
exports.formatSyncCookie = formatSyncCookie;
|
||
|
function parseSyncCookie(cookieStr) {
|
||
|
const [, key, value] = KEY_VALUE_REGEX.exec(cookieStr) || [];
|
||
|
const parsedKey = key !== void 0 && value !== void 0 && key.split('|');
|
||
|
if (parsedKey && parsedKey.length !== CLIENT_COOKIE_SYNC_KEY_FRAGMENT_COUNT)
|
||
|
return null;
|
||
|
return {
|
||
|
isServerSync: parsedKey[0].indexOf(exports.SYNCHRONIZATION_TYPE.server) > -1,
|
||
|
isClientSync: parsedKey[0].indexOf(exports.SYNCHRONIZATION_TYPE.client) > -1,
|
||
|
isWindowSync: parsedKey[0].indexOf(exports.SYNCHRONIZATION_TYPE.window) > -1,
|
||
|
sid: parsedKey[1],
|
||
|
key: decodeURIComponent(parsedKey[2]),
|
||
|
domain: decodeURIComponent(parsedKey[3]),
|
||
|
path: decodeURIComponent(parsedKey[4]),
|
||
|
expires: parsedKey[5] ? new Date(parseInt(parsedKey[5], TIME_RADIX)) : 'Infinity',
|
||
|
lastAccessed: new Date(parseInt(parsedKey[6], TIME_RADIX)),
|
||
|
maxAge: parsedKey[7] ? parseInt(parsedKey[7], TIME_RADIX) : null,
|
||
|
syncKey: key,
|
||
|
value,
|
||
|
cookieStr,
|
||
|
};
|
||
|
}
|
||
|
exports.parseSyncCookie = parseSyncCookie;
|
||
|
function changeSyncType(parsedCookie, flags) {
|
||
|
var _a, _b;
|
||
|
if ('server' in flags)
|
||
|
parsedCookie.isServerSync = flags.server;
|
||
|
if ('client' in flags)
|
||
|
parsedCookie.isClientSync = flags.client;
|
||
|
if ('window' in flags)
|
||
|
parsedCookie.isWindowSync = flags.window;
|
||
|
const newSyncTypeStr = stringifySyncType(parsedCookie);
|
||
|
parsedCookie.syncKey = (_a = parsedCookie.syncKey) === null || _a === void 0 ? void 0 : _a.replace(SYNCHRONIZATION_TYPE_RE, newSyncTypeStr);
|
||
|
parsedCookie.cookieStr = (_b = parsedCookie.cookieStr) === null || _b === void 0 ? void 0 : _b.replace(SYNCHRONIZATION_TYPE_RE, newSyncTypeStr);
|
||
|
}
|
||
|
exports.changeSyncType = changeSyncType;
|
||
|
function isOutdatedSyncCookie(currentCookie, newCookie) {
|
||
|
return newCookie.isServerSync === currentCookie.isServerSync &&
|
||
|
newCookie.sid === currentCookie.sid &&
|
||
|
newCookie.key === currentCookie.key &&
|
||
|
newCookie.domain === currentCookie.domain &&
|
||
|
newCookie.path === currentCookie.path &&
|
||
|
newCookie.lastAccessed > currentCookie.lastAccessed;
|
||
|
}
|
||
|
exports.isOutdatedSyncCookie = isOutdatedSyncCookie;
|
||
|
function generateDeleteSyncCookieStr(cookie) {
|
||
|
return cookie.syncKey + CLEAR_COOKIE_VALUE_STR;
|
||
|
}
|
||
|
exports.generateDeleteSyncCookieStr = generateDeleteSyncCookieStr;
|