kleinigkeiten
This commit is contained in:
+265
@@ -0,0 +1,265 @@
|
||||
/**
|
||||
* Parse options.
|
||||
*/
|
||||
interface CookieParseOptions {
|
||||
/**
|
||||
* Specifies a function that will be used to decode a [cookie-value](https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1).
|
||||
* Since the value of a cookie has a limited character set (and must be a simple string), this function can be used to decode
|
||||
* a previously-encoded cookie value into a JavaScript string.
|
||||
*
|
||||
* The default function is the global `decodeURIComponent`, wrapped in a `try..catch`. If an error
|
||||
* is thrown it will return the cookie's original value. If you provide your own encode/decode
|
||||
* scheme you must ensure errors are appropriately handled.
|
||||
*
|
||||
* @default decode
|
||||
*/
|
||||
decode?: (str: string) => string | undefined;
|
||||
/**
|
||||
* Custom function to filter parsing specific keys.
|
||||
*/
|
||||
filter?(key: string): boolean;
|
||||
/**
|
||||
* When enabled, duplicate cookie names will return an array of values
|
||||
* instead of only the first value.
|
||||
*/
|
||||
allowMultiple?: boolean;
|
||||
}
|
||||
/**
|
||||
* Cookies object.
|
||||
*/
|
||||
type Cookies = Record<string, string | undefined>;
|
||||
/**
|
||||
* Cookies object when `allowMultiple` is enabled.
|
||||
*/
|
||||
type MultiCookies = Record<string, string | string[] | undefined>;
|
||||
/**
|
||||
* Stringify options.
|
||||
*/
|
||||
interface CookieStringifyOptions {
|
||||
/**
|
||||
* Specifies a function that will be used to encode a [cookie-value](https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1).
|
||||
* Since value of a cookie has a limited character set (and must be a simple string), this function can be used to encode
|
||||
* a value into a string suited for a cookie's value, and should mirror `decode` when parsing.
|
||||
*
|
||||
* @default encodeURIComponent
|
||||
*/
|
||||
encode?: (str: string) => string;
|
||||
/**
|
||||
* Specifies a function that will be used to coerce non-string values to a string.
|
||||
*
|
||||
* @default JSON.stringify
|
||||
*/
|
||||
stringify?: (value: unknown) => string;
|
||||
}
|
||||
/**
|
||||
* Set-Cookie object.
|
||||
*/
|
||||
interface SetCookie {
|
||||
/**
|
||||
* Specifies the name of the cookie.
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* Specifies the string to be the value for the cookie.
|
||||
*/
|
||||
value: string | undefined;
|
||||
/**
|
||||
* Specifies the `number` (in seconds) to be the value for the [`Max-Age` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.2).
|
||||
*
|
||||
* The [cookie storage model specification](https://tools.ietf.org/html/rfc6265#section-5.3) states that if both `expires` and
|
||||
* `maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this,
|
||||
* so if both are set, they should point to the same date and time.
|
||||
*/
|
||||
maxAge?: number;
|
||||
/**
|
||||
* Specifies the `Date` object to be the value for the [`Expires` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.1).
|
||||
* When no expiration is set, clients consider this a "non-persistent cookie" and delete it when the current session is over.
|
||||
*
|
||||
* The [cookie storage model specification](https://tools.ietf.org/html/rfc6265#section-5.3) states that if both `expires` and
|
||||
* `maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this,
|
||||
* so if both are set, they should point to the same date and time.
|
||||
*/
|
||||
expires?: Date;
|
||||
/**
|
||||
* Specifies the value for the [`Domain` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.3).
|
||||
* When no domain is set, clients consider the cookie to apply to the current domain only.
|
||||
*/
|
||||
domain?: string;
|
||||
/**
|
||||
* Specifies the value for the [`Path` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.4).
|
||||
* When no path is set, the path is considered the ["default path"](https://tools.ietf.org/html/rfc6265#section-5.1.4).
|
||||
*/
|
||||
path?: string;
|
||||
/**
|
||||
* Enables the [`HttpOnly` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.6).
|
||||
* When enabled, clients will not allow client-side JavaScript to see the cookie in `document.cookie`.
|
||||
*/
|
||||
httpOnly?: boolean;
|
||||
/**
|
||||
* Enables the [`Secure` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.5).
|
||||
* When enabled, clients will only send the cookie back if the browser has an HTTPS connection.
|
||||
*/
|
||||
secure?: boolean;
|
||||
/**
|
||||
* Enables the [`Partitioned` `Set-Cookie` attribute](https://tools.ietf.org/html/draft-cutler-httpbis-partitioned-cookies/).
|
||||
* When enabled, clients will only send the cookie back when the current domain _and_ top-level domain matches.
|
||||
*
|
||||
* This is an attribute that has not yet been fully standardized, and may change in the future.
|
||||
* This also means clients may ignore this attribute until they understand it. More information
|
||||
* about can be found in [the proposal](https://github.com/privacycg/CHIPS).
|
||||
*/
|
||||
partitioned?: boolean;
|
||||
/**
|
||||
* Specifies the value for the [`Priority` `Set-Cookie` attribute](https://tools.ietf.org/html/draft-west-cookie-priority-00#section-4.1).
|
||||
*
|
||||
* - `'low'` will set the `Priority` attribute to `Low`.
|
||||
* - `'medium'` will set the `Priority` attribute to `Medium`, the default priority when not set.
|
||||
* - `'high'` will set the `Priority` attribute to `High`.
|
||||
*
|
||||
* More information about priority levels can be found in [the specification](https://tools.ietf.org/html/draft-west-cookie-priority-00#section-4.1).
|
||||
*/
|
||||
priority?: "low" | "medium" | "high";
|
||||
/**
|
||||
* Specifies the value for the [`SameSite` `Set-Cookie` attribute](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-09#section-5.4.7).
|
||||
*
|
||||
* - `true` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
|
||||
* - `'lax'` will set the `SameSite` attribute to `Lax` for lax same site enforcement.
|
||||
* - `'none'` will set the `SameSite` attribute to `None` for an explicit cross-site cookie.
|
||||
* - `'strict'` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
|
||||
*
|
||||
* More information about enforcement levels can be found in [the specification](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-09#section-5.4.7).
|
||||
*/
|
||||
sameSite?: boolean | "lax" | "strict" | "none";
|
||||
}
|
||||
/**
|
||||
* Backward compatibility serialize options.
|
||||
*/
|
||||
type CookieSerializeOptions = CookieStringifyOptions & Omit<SetCookie, "name" | "value">;
|
||||
/**
|
||||
* Parse a `Cookie` header string into an object.
|
||||
*
|
||||
* The object has cookie names as keys and decoded values as values.
|
||||
* First occurrence wins for duplicate names unless `allowMultiple` is set.
|
||||
*
|
||||
* @param str - The `Cookie` header string to parse.
|
||||
* @param options - Parsing options (`decode`, `filter`, `allowMultiple`).
|
||||
* @returns A prototype-less object of cookie name-value pairs.
|
||||
*/
|
||||
declare function parse(str: string, options: CookieParseOptions & {
|
||||
allowMultiple: true;
|
||||
}): MultiCookies;
|
||||
declare function parse(str: string, options?: CookieParseOptions): Cookies;
|
||||
/**
|
||||
* Stringify a cookies object into an HTTP `Cookie` header string.
|
||||
*
|
||||
* @param cookie - An object of cookie name-value pairs.
|
||||
* @param options - Stringify options (`encode`).
|
||||
* @returns A `Cookie` header string (e.g. `"foo=bar; baz=qux"`).
|
||||
*/
|
||||
declare function stringifyCookie(cookie: Cookies, options?: CookieStringifyOptions): string;
|
||||
/**
|
||||
* Serialize a cookie into a `Set-Cookie` header string.
|
||||
*
|
||||
* Accepts either a name-value pair with options or a `SetCookie` object.
|
||||
* Non-string values are coerced to strings. Validates name, value, domain,
|
||||
* and path against RFC 6265bis.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* serialize("foo", "bar", { httpOnly: true });
|
||||
* // => "foo=bar; HttpOnly"
|
||||
*
|
||||
* serialize({ name: "foo", value: "bar", secure: true });
|
||||
* // => "foo=bar; Secure"
|
||||
* ```
|
||||
*/
|
||||
declare function serialize(cookie: SetCookie, options?: CookieStringifyOptions): string;
|
||||
declare function serialize(name: string, val: unknown, options?: CookieSerializeOptions): string;
|
||||
interface SetCookieParseOptions {
|
||||
/**
|
||||
* Custom decode function to use on cookie values.
|
||||
*
|
||||
* By default, `decodeURIComponent` is used.
|
||||
*
|
||||
* **Note:** If decoding fails, the original (undecoded) value will be used
|
||||
*/
|
||||
decode?: false | ((value: string) => string);
|
||||
}
|
||||
interface SetCookie$1 {
|
||||
/**
|
||||
* Cookie name
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* Cookie value
|
||||
*/
|
||||
value: string;
|
||||
/**
|
||||
* Cookie path
|
||||
*/
|
||||
path?: string | undefined;
|
||||
/**
|
||||
* Absolute expiration date for the cookie
|
||||
*/
|
||||
expires?: Date | undefined;
|
||||
/**
|
||||
* Relative max age of the cookie in seconds from when the client receives it (integer or undefined)
|
||||
*
|
||||
* Note: when using with express's res.cookie() method, multiply maxAge by 1000 to convert to milliseconds
|
||||
*/
|
||||
maxAge?: number | undefined;
|
||||
/**
|
||||
* Domain for the cookie,
|
||||
* May begin with "." to indicate the named domain or any subdomain of it
|
||||
*/
|
||||
domain?: string | undefined;
|
||||
/**
|
||||
* Indicates that this cookie should only be sent over HTTPs
|
||||
*/
|
||||
secure?: boolean | undefined;
|
||||
/**
|
||||
* Indicates that this cookie should not be accessible to client-side JavaScript
|
||||
*/
|
||||
httpOnly?: boolean | undefined;
|
||||
/**
|
||||
* Indicates a cookie ought not to be sent along with cross-site requests
|
||||
*/
|
||||
sameSite?: true | false | "lax" | "strict" | "none" | undefined;
|
||||
/**
|
||||
* Indicates that the cookie should be stored using partitioned storage
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/Privacy/Privacy_sandbox/Partitioned_cookies
|
||||
*/
|
||||
partitioned?: boolean | undefined;
|
||||
/**
|
||||
* Indicates the priority of the cookie
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#prioritylow_medium_high
|
||||
*/
|
||||
priority?: "low" | "medium" | "high" | undefined;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
/**
|
||||
* Parse a [`Set-Cookie`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie) header string into an object.
|
||||
*
|
||||
* Returns `undefined` for cookies with forbidden names (prototype pollution protection)
|
||||
* or when both name and value are empty (RFC 6265bis sec 5.7).
|
||||
*
|
||||
* @param str - The `Set-Cookie` header string to parse.
|
||||
* @param options - Parsing options (`decode`).
|
||||
* @returns A `SetCookie` object with all parsed attributes, or `undefined`.
|
||||
*/
|
||||
declare function parseSetCookie(str: string, options?: SetCookieParseOptions): SetCookie$1 | undefined;
|
||||
/**
|
||||
* Split comma-joined `Set-Cookie` header strings into individual cookie strings.
|
||||
*
|
||||
* Correctly handles commas within cookie attributes like `Expires` dates
|
||||
* by checking for `=` after a comma to determine if it's a cookie separator.
|
||||
*
|
||||
* @param cookiesString - A comma-joined `Set-Cookie` string or array of strings.
|
||||
* @returns An array of individual `Set-Cookie` strings.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc2616#section-4.2
|
||||
*/
|
||||
declare function splitSetCookieString(cookiesString: string | string[]): string[];
|
||||
export { type CookieParseOptions, type CookieSerializeOptions, type CookieStringifyOptions, type Cookies, type MultiCookies, type SetCookie, type SetCookieParseOptions, parse, parse as parseCookie, parseSetCookie, serialize, serialize as serializeCookie, splitSetCookieString, stringifyCookie };
|
||||
+311
@@ -0,0 +1,311 @@
|
||||
const COOKIE_MAX_AGE_LIMIT = 3456e4;
|
||||
function endIndex(str, min, len) {
|
||||
const index = str.indexOf(";", min);
|
||||
return index === -1 ? len : index;
|
||||
}
|
||||
function eqIndex(str, min, max) {
|
||||
const index = str.indexOf("=", min);
|
||||
return index < max ? index : -1;
|
||||
}
|
||||
function valueSlice(str, min, max) {
|
||||
if (min === max) return "";
|
||||
let start = min;
|
||||
let end = max;
|
||||
do {
|
||||
const code = str.charCodeAt(start);
|
||||
if (code !== 32 && code !== 9) break;
|
||||
} while (++start < end);
|
||||
while (end > start) {
|
||||
const code = str.charCodeAt(end - 1);
|
||||
if (code !== 32 && code !== 9) break;
|
||||
end--;
|
||||
}
|
||||
return str.slice(start, end);
|
||||
}
|
||||
const NullObject = /* @__PURE__ */ (() => {
|
||||
const C = function() {};
|
||||
C.prototype = Object.create(null);
|
||||
return C;
|
||||
})();
|
||||
function parse(str, options) {
|
||||
const obj = new NullObject();
|
||||
const len = str.length;
|
||||
if (len < 2) return obj;
|
||||
const dec = options?.decode || decode;
|
||||
const allowMultiple = options?.allowMultiple || false;
|
||||
let index = 0;
|
||||
do {
|
||||
const eqIdx = eqIndex(str, index, len);
|
||||
if (eqIdx === -1) break;
|
||||
const endIdx = endIndex(str, index, len);
|
||||
if (eqIdx > endIdx) {
|
||||
index = str.lastIndexOf(";", eqIdx - 1) + 1;
|
||||
continue;
|
||||
}
|
||||
const key = valueSlice(str, index, eqIdx);
|
||||
if (options?.filter && !options.filter(key)) {
|
||||
index = endIdx + 1;
|
||||
continue;
|
||||
}
|
||||
const val = dec(valueSlice(str, eqIdx + 1, endIdx));
|
||||
if (allowMultiple) {
|
||||
const existing = obj[key];
|
||||
if (existing === void 0) obj[key] = val;
|
||||
else if (Array.isArray(existing)) existing.push(val);
|
||||
else obj[key] = [existing, val];
|
||||
} else if (obj[key] === void 0) obj[key] = val;
|
||||
index = endIdx + 1;
|
||||
} while (index < len);
|
||||
return obj;
|
||||
}
|
||||
function decode(str) {
|
||||
if (!str.includes("%")) return str;
|
||||
try {
|
||||
return decodeURIComponent(str);
|
||||
} catch {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
const cookieNameRegExp = /^[\u0021-\u003A\u003C\u003E-\u007E]+$/;
|
||||
const cookieValueRegExp = /^[\u0021-\u003A\u003C-\u007E]*$/;
|
||||
const domainValueRegExp = /^([.]?[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)([.][a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$/i;
|
||||
const pathValueRegExp = /^[\u0020-\u003A\u003C-\u007E]*$/;
|
||||
const __toString = Object.prototype.toString;
|
||||
function stringifyCookie(cookie, options) {
|
||||
const enc = options?.encode || encodeURIComponent;
|
||||
const keys = Object.keys(cookie);
|
||||
let str = "";
|
||||
for (const [i, name] of keys.entries()) {
|
||||
const val = cookie[name];
|
||||
if (val === void 0) continue;
|
||||
if (!cookieNameRegExp.test(name)) throw new TypeError(`cookie name is invalid: ${name}`);
|
||||
const value = enc(val);
|
||||
if (!cookieValueRegExp.test(value)) throw new TypeError(`cookie val is invalid: ${val}`);
|
||||
if (i > 0) str += "; ";
|
||||
str += name + "=" + value;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
function serialize(_a0, _a1, _a2) {
|
||||
const isObj = typeof _a0 === "object" && _a0 !== null;
|
||||
const options = isObj ? _a1 : _a2;
|
||||
const stringify = options?.stringify || JSON.stringify;
|
||||
const cookie = isObj ? _a0 : {
|
||||
..._a2,
|
||||
name: _a0,
|
||||
value: _a1 == void 0 ? "" : typeof _a1 === "string" ? _a1 : stringify(_a1)
|
||||
};
|
||||
const enc = options?.encode || encodeURIComponent;
|
||||
if (!cookieNameRegExp.test(cookie.name)) throw new TypeError(`argument name is invalid: ${cookie.name}`);
|
||||
const value = cookie.value ? enc(cookie.value) : "";
|
||||
if (!cookieValueRegExp.test(value)) throw new TypeError(`argument val is invalid: ${cookie.value}`);
|
||||
if (!cookie.secure) {
|
||||
if (cookie.partitioned) throw new TypeError(`Partitioned cookies must have the Secure attribute`);
|
||||
if (cookie.sameSite && String(cookie.sameSite).toLowerCase() === "none") throw new TypeError(`SameSite=None cookies must have the Secure attribute`);
|
||||
if (cookie.name.length > 9 && cookie.name.charCodeAt(0) === 95 && cookie.name.charCodeAt(1) === 95) {
|
||||
const nameLower = cookie.name.toLowerCase();
|
||||
if (nameLower.startsWith("__secure-") || nameLower.startsWith("__host-")) throw new TypeError(`${cookie.name} cookies must have the Secure attribute`);
|
||||
}
|
||||
}
|
||||
if (cookie.name.length > 7 && cookie.name.charCodeAt(0) === 95 && cookie.name.charCodeAt(1) === 95 && cookie.name.toLowerCase().startsWith("__host-")) {
|
||||
if (cookie.path !== "/") throw new TypeError(`__Host- cookies must have Path=/`);
|
||||
if (cookie.domain) throw new TypeError(`__Host- cookies must not have a Domain attribute`);
|
||||
}
|
||||
let str = cookie.name + "=" + value;
|
||||
if (cookie.maxAge !== void 0) {
|
||||
if (!Number.isInteger(cookie.maxAge)) throw new TypeError(`option maxAge is invalid: ${cookie.maxAge}`);
|
||||
str += "; Max-Age=" + Math.max(0, Math.min(cookie.maxAge, COOKIE_MAX_AGE_LIMIT));
|
||||
}
|
||||
if (cookie.domain) {
|
||||
if (!domainValueRegExp.test(cookie.domain)) throw new TypeError(`option domain is invalid: ${cookie.domain}`);
|
||||
str += "; Domain=" + cookie.domain;
|
||||
}
|
||||
if (cookie.path) {
|
||||
if (!pathValueRegExp.test(cookie.path)) throw new TypeError(`option path is invalid: ${cookie.path}`);
|
||||
str += "; Path=" + cookie.path;
|
||||
}
|
||||
if (cookie.expires) {
|
||||
if (!isDate(cookie.expires) || !Number.isFinite(cookie.expires.valueOf())) throw new TypeError(`option expires is invalid: ${cookie.expires}`);
|
||||
str += "; Expires=" + cookie.expires.toUTCString();
|
||||
}
|
||||
if (cookie.httpOnly) str += "; HttpOnly";
|
||||
if (cookie.secure) str += "; Secure";
|
||||
if (cookie.partitioned) str += "; Partitioned";
|
||||
if (cookie.priority) switch (typeof cookie.priority === "string" ? cookie.priority.toLowerCase() : void 0) {
|
||||
case "low":
|
||||
str += "; Priority=Low";
|
||||
break;
|
||||
case "medium":
|
||||
str += "; Priority=Medium";
|
||||
break;
|
||||
case "high":
|
||||
str += "; Priority=High";
|
||||
break;
|
||||
default: throw new TypeError(`option priority is invalid: ${cookie.priority}`);
|
||||
}
|
||||
if (cookie.sameSite) switch (typeof cookie.sameSite === "string" ? cookie.sameSite.toLowerCase() : cookie.sameSite) {
|
||||
case true:
|
||||
case "strict":
|
||||
str += "; SameSite=Strict";
|
||||
break;
|
||||
case "lax":
|
||||
str += "; SameSite=Lax";
|
||||
break;
|
||||
case "none":
|
||||
str += "; SameSite=None";
|
||||
break;
|
||||
default: throw new TypeError(`option sameSite is invalid: ${cookie.sameSite}`);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
function isDate(val) {
|
||||
return __toString.call(val) === "[object Date]";
|
||||
}
|
||||
const maxAgeRegExp = /^-?\d+$/;
|
||||
const _nullProto = /* @__PURE__ */ Object.getPrototypeOf({});
|
||||
function parseSetCookie(str, options) {
|
||||
const len = str.length;
|
||||
let _endIdx = len;
|
||||
let eqIdx = -1;
|
||||
for (let i = 0; i < len; i++) {
|
||||
const c = str.charCodeAt(i);
|
||||
if (c === 59) {
|
||||
_endIdx = i;
|
||||
break;
|
||||
}
|
||||
if (c === 61 && eqIdx === -1) eqIdx = i;
|
||||
}
|
||||
if (eqIdx >= _endIdx) eqIdx = -1;
|
||||
const name = eqIdx === -1 ? "" : _trim(str, 0, eqIdx);
|
||||
if (name && name in _nullProto) return void 0;
|
||||
let value = eqIdx === -1 ? _trim(str, 0, _endIdx) : _trim(str, eqIdx + 1, _endIdx);
|
||||
if (!name && !value) return void 0;
|
||||
if (name.length + value.length > 4096) return void 0;
|
||||
if (options?.decode !== false) value = _decode(value, options?.decode);
|
||||
const setCookie = {
|
||||
name,
|
||||
value
|
||||
};
|
||||
let index = _endIdx + 1;
|
||||
while (index < len) {
|
||||
let endIdx = len;
|
||||
let attrEqIdx = -1;
|
||||
for (let i = index; i < len; i++) {
|
||||
const c = str.charCodeAt(i);
|
||||
if (c === 59) {
|
||||
endIdx = i;
|
||||
break;
|
||||
}
|
||||
if (c === 61 && attrEqIdx === -1) attrEqIdx = i;
|
||||
}
|
||||
if (attrEqIdx >= endIdx) attrEqIdx = -1;
|
||||
const attr = attrEqIdx === -1 ? _trim(str, index, endIdx) : _trim(str, index, attrEqIdx);
|
||||
const val = attrEqIdx === -1 ? void 0 : _trim(str, attrEqIdx + 1, endIdx);
|
||||
if (val === void 0 || val.length <= 1024) switch (attr.toLowerCase()) {
|
||||
case "httponly":
|
||||
setCookie.httpOnly = true;
|
||||
break;
|
||||
case "secure":
|
||||
setCookie.secure = true;
|
||||
break;
|
||||
case "partitioned":
|
||||
setCookie.partitioned = true;
|
||||
break;
|
||||
case "domain":
|
||||
if (val) setCookie.domain = (val.charCodeAt(0) === 46 ? val.slice(1) : val).toLowerCase();
|
||||
break;
|
||||
case "path":
|
||||
setCookie.path = val;
|
||||
break;
|
||||
case "max-age":
|
||||
if (val && maxAgeRegExp.test(val)) setCookie.maxAge = Math.min(Number(val), COOKIE_MAX_AGE_LIMIT);
|
||||
break;
|
||||
case "expires": {
|
||||
if (!val) break;
|
||||
const date = new Date(val);
|
||||
if (Number.isFinite(date.valueOf())) {
|
||||
const maxDate = new Date(Date.now() + COOKIE_MAX_AGE_LIMIT * 1e3);
|
||||
setCookie.expires = date > maxDate ? maxDate : date;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "priority": {
|
||||
if (!val) break;
|
||||
const priority = val.toLowerCase();
|
||||
if (priority === "low" || priority === "medium" || priority === "high") setCookie.priority = priority;
|
||||
break;
|
||||
}
|
||||
case "samesite": {
|
||||
if (!val) break;
|
||||
const sameSite = val.toLowerCase();
|
||||
if (sameSite === "lax" || sameSite === "strict" || sameSite === "none") setCookie.sameSite = sameSite;
|
||||
else setCookie.sameSite = "lax";
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
const attrLower = attr.toLowerCase();
|
||||
if (attrLower && !(attrLower in _nullProto)) setCookie[attrLower] = val;
|
||||
}
|
||||
}
|
||||
index = endIdx + 1;
|
||||
}
|
||||
return setCookie;
|
||||
}
|
||||
function _trim(str, start, end) {
|
||||
if (start === end) return "";
|
||||
let s = start;
|
||||
let e = end;
|
||||
while (s < e && (str.charCodeAt(s) === 32 || str.charCodeAt(s) === 9)) s++;
|
||||
while (e > s && (str.charCodeAt(e - 1) === 32 || str.charCodeAt(e - 1) === 9)) e--;
|
||||
return str.slice(s, e);
|
||||
}
|
||||
function _decode(value, decode) {
|
||||
if (!decode && !value.includes("%")) return value;
|
||||
try {
|
||||
return (decode || decodeURIComponent)(value);
|
||||
} catch {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
function splitSetCookieString(cookiesString) {
|
||||
if (Array.isArray(cookiesString)) return cookiesString.flatMap((c) => splitSetCookieString(c));
|
||||
if (typeof cookiesString !== "string") return [];
|
||||
const cookiesStrings = [];
|
||||
let pos = 0;
|
||||
let start;
|
||||
let ch;
|
||||
let lastComma;
|
||||
let nextStart;
|
||||
let cookiesSeparatorFound;
|
||||
const skipWhitespace = () => {
|
||||
while (pos < cookiesString.length && /\s/.test(cookiesString.charAt(pos))) pos += 1;
|
||||
return pos < cookiesString.length;
|
||||
};
|
||||
const notSpecialChar = () => {
|
||||
ch = cookiesString.charAt(pos);
|
||||
return ch !== "=" && ch !== ";" && ch !== ",";
|
||||
};
|
||||
while (pos < cookiesString.length) {
|
||||
start = pos;
|
||||
cookiesSeparatorFound = false;
|
||||
while (skipWhitespace()) {
|
||||
ch = cookiesString.charAt(pos);
|
||||
if (ch === ",") {
|
||||
lastComma = pos;
|
||||
pos += 1;
|
||||
skipWhitespace();
|
||||
nextStart = pos;
|
||||
while (pos < cookiesString.length && notSpecialChar()) pos += 1;
|
||||
if (pos < cookiesString.length && cookiesString.charAt(pos) === "=") {
|
||||
cookiesSeparatorFound = true;
|
||||
pos = nextStart;
|
||||
cookiesStrings.push(cookiesString.slice(start, lastComma));
|
||||
start = pos;
|
||||
} else pos = lastComma + 1;
|
||||
} else pos += 1;
|
||||
}
|
||||
if (!cookiesSeparatorFound || pos >= cookiesString.length) cookiesStrings.push(cookiesString.slice(start));
|
||||
}
|
||||
return cookiesStrings;
|
||||
}
|
||||
export { parse, parse as parseCookie, parseSetCookie, serialize, serialize as serializeCookie, splitSetCookieString, stringifyCookie };
|
||||
Reference in New Issue
Block a user