import { CACHE_NAME, DEFAULT_CACHE_TIMEOUT, MSG_CLEAR_CACHES, MSG_GET_HTTPCACHE, MSG_PUT_HTTPCACHE, } from "../config"; import { kissLog } from "./log"; import { isExt } from "./client"; import { isBg } from "./browser"; import { sendBgMsg } from "./msg"; import { blobToBase64 } from "./utils"; /** * 清除缓存数据 */ export const tryClearCaches = async () => { try { if (isExt && !isBg) { await sendBgMsg(MSG_CLEAR_CACHES); } else { await caches.delete(CACHE_NAME); } } catch (err) { kissLog("clean caches", err); } }; /** * 构造缓存 request * @param {*} input * @param {*} init * @returns */ const newCacheReq = async (input, init) => { let request = new Request(input, init); if (request.method !== "GET") { const body = await request.text(); const cacheUrl = new URL(request.url); cacheUrl.pathname += body; request = new Request(cacheUrl.toString(), { method: "GET" }); } return request; }; /** * 查询 caches * @param {*} input * @param {*} init * @returns */ export const getHttpCache = async ({ input, init }) => { try { const request = await newCacheReq(input, init); const cache = await caches.open(CACHE_NAME); const response = await cache.match(request); if (response) { const res = await parseResponse(response); return res; } } catch (err) { kissLog("get cache", err); } return null; }; /** * 插入 caches * @param {*} input * @param {*} init * @param {*} data */ export const putHttpCache = async ({ input, init, data, maxAge = DEFAULT_CACHE_TIMEOUT, // todo: 从设置里面读取最大缓存时间 }) => { try { const req = await newCacheReq(input, init); const cache = await caches.open(CACHE_NAME); const res = new Response(JSON.stringify(data), { status: 200, headers: { "Content-Type": "application/json", "Cache-Control": `max-age=${maxAge}`, }, }); // res.headers.set("Cache-Control", `max-age=${maxAge}`); await cache.put(req, res); } catch (err) { kissLog("put cache", err); } }; /** * 解析 response * @param {*} res * @returns */ export const parseResponse = async (res) => { if (!res) { throw new Error("Response object does not exist"); } if (!res.ok) { const msg = { url: res.url, status: res.status, }; if (res.headers.get("Content-Type")?.includes("json")) { msg.response = await res.json(); } throw new Error(JSON.stringify(msg)); } const contentType = res.headers.get("Content-Type"); if (contentType?.includes("json")) { return res.json(); } else if (contentType?.includes("audio")) { const blob = await res.blob(); return blobToBase64(blob); } return res.text(); }; /** * getHttpCache 兼容性封装 * @param {*} input * @param {*} init * @returns */ export const getHttpCachePolyfill = (input, init) => { // 插件 if (isExt && !isBg()) { return sendBgMsg(MSG_GET_HTTPCACHE, { input, init }); } // 油猴/网页/BackgroundPage return getHttpCache({ input, init }); }; /** * putHttpCache 兼容性封装 * @param {*} input * @param {*} init * @param {*} data * @returns */ export const putHttpCachePolyfill = (input, init, data) => { // 插件 if (isExt && !isBg()) { return sendBgMsg(MSG_PUT_HTTPCACHE, { input, init, data }); } // 油猴/网页/BackgroundPage return putHttpCache({ input, init, data }); };