importScripts(
"https://cdn.jsdelivr.net/npm/[email protected]/dist/localforage.min.js",
);
const ENDPOINT = "https://your-domain/post-request";
const bin2Hex = (buffer) => {
let digest = "";
const dataView = new DataView(buffer);
for (let i = 0, len = dataView.byteLength; i < len; i += 4) {
const value = dataView.getUint32(i);
const hex = value.toString(16);
const padding = "00000000";
const paddedValue = (padding + hex).slice(-padding.length);
digest += paddedValue;
}
return digest;
};
const postRequestFetchListener = (fetchEvent) => {
const requestUrl = fetchEvent.request.url;
const method = fetchEvent.request.method.toUpperCase();
if (!(method === "POST" && requestUrl === ENDPOINT)) {
return;
}
fetchEvent.respondWith(
fetchEvent.request
.clone()
.arrayBuffer()
.then((buffer) => {
const requestBody = String.fromCharCode.apply(
null,
new Uint8Array(buffer),
);
if (requestBody.includes("cache=1")) {
return crypto.subtle.digest("SHA-1", buffer);
}
return Promise.reject();
})
.then((sha1Buffer) => {
const sha1Hash = bin2Hex(sha1Buffer);
console.log("SHA1 Hash => ", sha1Hash);
return localforage.getItem(sha1Hash).then((cachedResponse) => {
if (cachedResponse) {
console.log("Cached repsonse => ", cachedResponse);
return new Response(cachedResponse, {
status: 200,
statusText: "OK",
headers: {
"Content-Length": cachedResponse.length,
"Content-Type": "application/json",
"X-SW-Cache-Hit": 1,
"X-SW-Cache-Type": "POST",
},
});
}
return fetch(fetchEvent.request).then((response) => {
console.log("Fetching response => ", response.clone());
if (200 <= response.status && response.status < 400) {
response
.clone()
.text()
.then((textResponse) => {
console.log("Caching response => ", textResponse);
return localforage.setItem(sha1Hash, textResponse);
});
}
return response;
});
});
})
.catch(() => fetch(fetchEvent.request)),
);
};
self.addEventListener("fetch", postRequestFetchListener);