in lib/util.js [170:228]
exports.formatCookie = function(name, val, options = {}) {
if (val && typeof val === 'object') val = JSON.stringify(val);
if (options.expires && typeof options.expires !== 'object') {
options.expires = Number(options.expires);
if (isNaN(options.expires)) delete options.expires;
options.expires = new Date(options.expires);
}
const opt = {
path:'/',
secure:true,
httpOnly:false,
...options
}
const regex = /[\;\,\s]/;
const msg = 'cannot contain semicolons, colons, or spaces'
const value = encodeURIComponent(val);
if (regex.test(name) || regex.test(value)) {
throw new Error('Cookie strings ' + msg);
}
name += '=' + value;
if (opt.domain) {
if (!regex.test(opt.domain)) {
name += '; Domain=' + opt.domain;
} else { console.error(`Domain "${opt.domain}" ${msg}`) }
}
if (opt.path) {
if (!regex.test(opt.path)) {
name += '; Path=' + opt.path;
} else {console.error(`Path ${opt.path} ${msg}`)}
}
let exp = formatDate(opt.expires || opt.maxAge, name);
if (exp) {
const time = exp.getTime();
if (time <= Date.now()) {
console.error(`Cookie ${name} is expired`);
}
if (opt.maxAge) {
name += '; Max-Age=' + Math.floor(time/1000);
} else {
name += '; Expires=' + exp.toUTCString();
}
}
if (opt.sameSite) {
const ss = opt.sameSite;
name += '; SameSite=';
const sameSite = /(strict|lax|none)/i.test(ss) ?
(ss.substring(0,1).toUpperCase() + ss.substring(1).toLowerCase()) :
opt.sameSite ? 'Strict' : 'Lax';
name += sameSite;
}
if (opt.httpOnly) name += '; HttpOnly';
if (opt.secure) name += '; Secure';
return name;
}