UNPKG

@shgysk8zer0/http-server

Version:

A powerful but lightweight node server built using web standards

289 lines (243 loc) 5.41 kB
export class Cookie { #name; #value; #path = '/'; #domain; #expires; #sameSite = 'Lax'; #httpOnly = false; #secure = false; #partitioned = false; /** * * @param {object} options * @param {string} name * @param {string} [value=""] * @param {string} [path="/"] * @param {string} [domain] * @param {number|Date} [expires] * @param {"strict"|"lax"|"none"} [sameSite="lax"] * @param {boolean} [httpOnly=false] * @param {boolean} [secure=false] * @param {boolean} [partitioned=false] */ constructor({ name, value = '', path = '/', domain, expires, sameSite = 'lax', httpOnly = false, secure = false, partitioned = false, }) { this.name = name; this.value = value; if (typeof domain !== 'undefined') { this.domain = domain; } if (typeof expires !== 'undefined') { this.expires = expires; } if (typeof httpOnly !== 'undefined') { this.httpOnly = httpOnly; } if (typeof partitioned !== 'undefined') { this.partitioned = partitioned; } if (typeof path !== 'undefined') { this.path = path; } if (typeof sameSite !== 'undefined') { this.sameSite = sameSite; } if (typeof secure !== 'undefined') { this.secure = secure; } } get name() { return this.#name; } set name(val) { if (typeof val === 'string') { this.#name = val; } else { throw new TypeError('Cookie name must be a string.'); } } get value() { return this.#value; } set value(val) { if (typeof val === 'string') { this.#value = val; } else { switch(typeof val) { case 'undefined': this.#value = ''; break; case 'number': case 'bigint': if (Number.isNaN(val)) { this.#value = ''; } else { this.#value = val.toString(); } break; case 'object': if (val !== null) { this.#value = val.toString(); } else { this.#value = ''; } break; case 'boolean': this.#value = val ? 'true' : 'false'; break; default: this.#value = val.toString(); } } } get domain() { return this.#domain; } set domain(val) { if (val instanceof URL) { this.#domain = val.hostname; } else if (typeof val !== 'string' || val.length === '') { throw new TypeError('Cookie domain must be a non-empty string.'); } else { this.#domain = val; } } get expires() { if (this.#expires instanceof Date) { return this.#expires.getTime(); } else { return undefined; } } set expires(val) { switch (typeof val) { case 'string': this.expires = new Date(val).getTime(); break; case 'number': this.#expires = Number.isNaN(val) ? undefined : val; break; case 'object': if (val === null) { this.#expires = undefined; } else if (! (val instanceof Date)) { throw new TypeError('Invalid expires.'); } else { this.#expires = val.getTime(); } break; case 'boolean': if (val) { this.#expires = new Date(0); } else { this.#expires = undefined; } } } get httpOnly() { return this.#httpOnly; } set httpOnly(val) { if (typeof val !== 'boolean') { throw new TypeError('Cookie httpOnly must be a boolean.'); } else { this.#httpOnly = val; } } get partitioned() { return this.#partitioned; } set partitioned(val) { if (typeof val !== 'boolean') { throw new TypeError('Cookie partitioned must be a boolean.'); } else { this.#partitioned = val; } } get path() { return this.#path; } set path(val) { if (val instanceof URL) { this.#path = val.pathname; } else if (typeof val === 'string' && val.length !== 0) { this.#path = val; } else { throw new TypeError('Cookie path must be a non-empty string.'); } } get sameSite() { return this.#sameSite; } set sameSite(val) { if (typeof val !== 'string') { throw new TypeError('Cookie SameSite must be a string.'); } else if (! ['lax', 'strict', 'none'].includes(val)) { throw new TypeError('Cookie SameSite must be "none", "lax", or "strict".'); } else { this.#sameSite = val; } } get secure() { return this.#secure; } set secure(val) { if (typeof val !== 'boolean') { throw new TypeError('Cookie secure must be a boolean.'); } else { this.#secure = val; } } toString() { const parts = [`${this.#name}=${this.#value}`]; if (typeof this.#expires === 'number') { parts.push(`Expires=${new Date(this.#expires).toUTCString()}`); } if (typeof this.#domain === 'string') { parts.push(`Domain=${this.#domain}`); } if (typeof this.#path === 'string' && this.#path !== '/') { parts.push(`Path=${this.#path}`); } if (typeof this.#sameSite === 'string') { parts.push(`SameSite=${this.sameSite[0].toUpperCase()}${this.#sameSite.substring(1).toLowerCase()}`); } if (this.#httpOnly) { parts.push('HttpOnly'); } if (this.#secure) { parts.push('Secure'); } if (this.#partitioned) { parts.push('Partitioned'); } return parts.join('; '); } toJSON() { return this.toString(); } addToHeaders(headers) { if (! (headers instanceof Headers)) { throw new TypeError('Expected a Headers object.'); } else { headers.append('Set-Cookie', this); } } addToResponse(resp) { if (resp instanceof Response) { this.addToHeaders(resp.headers); } else { throw new TypeError('Not a Response object.'); } } }