UNPKG

@tencentcloud/chat-cs-uniapp

Version:

TCCC uniapp UIKit

353 lines (312 loc) 9.36 kB
/** * Cookie基础库 * @example * getCookie('cookie1') * setCookie({ cookie1: 'xxx' }) * removeCookie('cookie2') * * @author WecTeam */ /** * 设置 cookie * 功能点: * 1. 支持设置单个,也支持设置多个 * 2. 可以设置有效期(maxAge 或 expires) * 3. 支持直接传值value,也支持传对象Object,里面包含{ value, expires } * 4. 需要进行编码(JS内置的URI编码即可) * * @example * setCookie({ * cookie1: 12345, * cookie2: '12345' * }) * * setCookie({ * cookie1: { * value: 12345, * maxAge: 3600 * 24 // 自定义有效期(这里示例是24小时) * }, * cookie2: { * value: '12345', * expires: 'Wed, 21 Oct 2015 07:28:00 GMT' // 标准GMT格式 * } * }) * * @param {Object} cookies 需要设置的cookie项 * @return void */ export function setCookie(cookies) { if (!isType(cookies, 'Object')) return console.error('输入不合法@setCookie'); const oldCookies = getFullCookiesObj(); const newCookies = {}; // 由入参转化后的标准格式的cookies Object.keys(cookies).forEach((name) => { if (isType(cookies[name], 'Object')) { const { value, expires, maxAge } = cookies[name]; newCookies[name] = getStandardCookieItem({ name, value, expires, maxAge, }); } else { newCookies[name] = getStandardCookieItem({ name, value: cookies[name], }); } }); saveCookiesToStorage(Object.assign({}, oldCookies, newCookies)); } /** * 将 cookies 保存到本地Storage * * @param {Object} cookies 完整到cookies对象 * @return void */ // @ts-ignore function saveCookiesToStorage(cookies) { try { wx.setStorageSync('cookies', cookies); } catch (e) { console.error('saveCookiesToStorage失败:', e); } } /** * 生成标准的 cookie 项 * * @param {Object} obj * .name cookie名 * .value cookie值 * .expires cookie过期时间 * .maxAge cookie有效期 * @return {CookieItem} { name: 'cookie1', value: 'xxx', expires: xxx } */ function getStandardCookieItem({ name, value, expires, maxAge, }) { if (name === undefined || value === undefined) { console.error('输入不合法@getStandardCookieItem'); return {}; } const cookieItem = { name, value, expires: expires || transferMaxAgeToExpires(maxAge), // 默认1年 }; return cookieItem; } /** * 将Max-Age格式的时间,转换为Expires格式的时间 * * @param {Number} maxAge 有效期,单位为“秒” * @return {String} expires 标准的Expires时间 */ function transferMaxAgeToExpires(maxAge) { // 目前的默认cookie是保存1年,注意【秒 ==> 毫秒】 const t = 1000 * (maxAge || 3600 * 24 * 365); // @ts-ignore return new Date(new Date().getTime() + t).toGMTString(); } /** * 获取指定 cookie 字段的值 * * @param {String} name cookie 名称name * @return {String} cookie 值value */ export function getCookie(name = '') { const cookies = getFullCookiesObj(); const cookieItem = cookies[name]; let result = ''; if (cookieItem) { result = decodeURIComponent(cookieItem.value); } else { console.warn('该cookie项不存在,或者已过期:', name); result = ''; } return result; } /** * 获取完整的 cookies 对象 * * @return {Record<string, Cookie>} cookie 对象 * @example * { * cookie1: { name: 'cookie1', value: 'xxx', expires: xxx }, * cookie2: { name: 'cookie2', value: 'xxx', expires: xxx }, * } */ function getFullCookiesObj() { let cookies; try { cookies = wx.getStorageSync('cookies'); } catch (e) { console.error('cookies初始化失败:', e); } if (!isType(cookies, 'Object')) cookies = {}; checkExpires(cookies); // 如果过期会自动删除,并同步本地Storage return cookies; } /** * 获取简化的 cookies 对象(已解码) * * @return {Object} cookie 对象 * @example * { * cookie1: 'xxx', * cookie2: 'xxx', * } */ export function getCookiesObj() { const cookies = getFullCookiesObj(); const newCookies = {}; Object.keys(cookies).forEach((name) => { // @ts-ignore newCookies[name] = decodeURIComponent(cookies[name].value); }); return cookies; } /** * 获取简化的 cookies 字符串(无解码) * * @return {String} cookie 字符串 * @example 'cookie1=xxx;cookie2=xxx' */ export function getCookiesStr() { // @ts-ignore const result = []; const cookies = getFullCookiesObj(); Object.keys(cookies).forEach((name) => { result.push(`${name}=${cookies[name].value}`); }); // @ts-ignore return result.join(';'); } /** * 删除某个cookie * * @param {String} cookieName 待删除的cookie名 * @return void */ export function removeCookie(cookieName) { const cookies = getFullCookiesObj(); delete cookies[cookieName]; saveCookiesToStorage(Object.assign({}, cookies)); } /** * 处理【响应头】的set-cookie字段 * * 可能的值: * "sessionId=38afes7a8", * "id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT", * "id=a3fWa; Max-Age=2592000", * "BAIDUID=xxxxx:FG=1; max-age=31536000; expires=Tue, 22-Dec-20 02:38:57 GMT; * domain=.baidu.com; path=/; version=1; comment=bd,H_WISE_SIDS=43_1374871; * path=/; expires=Tue, 22-Dec-20 02:38:57 GMT; * domain=.baidu.com,bd_traffictrace=231038; * expires=Thu, 08-Jan-1970 00:00:00 GMT,BDSVRTM=144; path=/" * * 注意点: * 1. 最基本的格式:Set-Cookie: <cookie-name>=<cookie-value> * 2. 可能同时包含多个cookie字段,以,分割(但需要排除时间值里的,) * 3. 时间格式:Max-Age/Expires (不区分大小写) * * @param {String} setCookieStr 响应header的 Set-Cookie 值 * @return void */ export function setCookieFromHeader(setCookieStr) { if (!setCookieStr) return; let setCookieArr = []; const resultSetCookieParam = {}; // 拆解cookie项:1. 替换 Expires 里的逗号; 2. 根据逗号分离多个 cookie 项; 3. 还原 Expires 里的逗号 setCookieArr = setCookieStr .replace(/(Expires=[A-Za-z]{3}),/gi, '$1_') .split(',') .map((item) => item.replace(/(Expires=[A-Za-z]{3})_/gi, '$1,')); if (setCookieArr.length === 0) return; // 单独对每一项处理 setCookieArr.forEach((item) => { const cookieItem = parseCookieItem(item); // @ts-ignore if (!cookieItem) return; if (!(cookieItem).name) return; // @ts-ignore resultSetCookieParam[cookieItem.name] = cookieItem; }); setCookie(resultSetCookieParam); } /** * 解析出标准格式的cookie项 * @example parseCookieItem('id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT') * 返回: { * name: 'id', * value: 'a3fWa', * expires: 'Wed, 21 Oct 2015 07:28:00 GMT' * } * * @param {Object} cookieStr set-cookie项 * @return {Object} cookieItem 标准格式的cookie项 */ // @ts-ignore function parseCookieItem(cookieStr) { const params = cookieStr.split(';'); const cookieItem = {}; // 兼容cookie里存在'='的情况 const firstParamItem = params.shift(); const firstParamArrIndex = firstParamItem.indexOf('='); if (firstParamArrIndex === -1) return console.error('cookie value error ', cookieStr); const firstParamArr = [firstParamItem.slice(0, firstParamArrIndex), firstParamItem.slice(firstParamArrIndex + 1)]; // 这里兼容下奇葩cookie值,实际应该 ===2 比较合适 if (firstParamArr.length < 2) return console.error('cookie value error ', cookieStr); // @ts-ignore [cookieItem.name, cookieItem.value] = firstParamArr; // @ts-ignore params.forEach((item) => { // @ts-ignore if (item.match(/^\s*Expires=/i)) { // @ts-ignore cookieItem.expires = new Date(item.split('=')[1]).toGMTString(); } // @ts-ignore if (item.match(/^\s*Max-age=/i)) cookieItem.maxAge = +item.split('=')[1]; }); return cookieItem; } /** * 校验 cookies 中各个字段的有效期(过期则删除) * 注:非纯函数,会直接修改传入的cookies * * @param {Object} cookies cookies对象 * @return void */ // @ts-ignore function checkExpires(cookies) { const newCookies = cookies; let hasExpired = false; const now = new Date(); Object.keys(newCookies).forEach((name) => { const expires = new Date(newCookies[name].expires); if (expires <= now) { hasExpired = true; delete newCookies[name]; // 删除 } }); // 同步到本地Storage if (hasExpired) saveCookiesToStorage(Object.assign({}, newCookies)); } /** * 一般的类型检查函数 * * @param ele {any} 代检查元素 * @param type {String} 目标类型,例如'String'/'Array'/'Function' * @return {Boolean} 是否目标类型 */ function isType(ele, type) { return Object.prototype.toString.call(ele) === `[object ${type}]`; }