如何通过 service worker 区分常规请求和 iframe 请求?
How to differ regular and iframe requests through a service worker?
- 有一个带有 iframe (
http://localhost:8080
) 的页面和连接的 service worker,它监视来自页面和 iframe 的所有 fetch
请求。
- 有一些内部页面请求(加载 favicon、内部脚本等)和 iframe 请求(为 iframe 中的页面加载静态资源)。
- 当 iframe 资源(如 css)具有绝对链接时 - 没问题,很容易区分本地请求(以
http://localhost:8080
开头)和 iframe 请求(以外部 netloc 开头)。
- 当 iframe 资源具有非绝对链接时,例如
images/smth.jpg
- 我无法区分内部和外部请求,因为它们都以 http://localhost:8080
开头。
所以,问题是:如何区分这些请求?也许,有一种方法可以查看请求的源元素 (iframe)?
目前,我实施的唯一解决方案是将所有本地资源移动到某个 hard-unique-named
文件夹,如果请求不是以它开头 - 它可以算作 iframe 请求。不过,我希望有更好的解决方案:)
事实证明,解决方案非常简单。首先,您需要在 Service Worker 和 iframe 激活后向其发送消息(从 iframe 发送):
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
navigator.serviceWorker.register('iframe_worker.js').then(function (registration) {
// Registration was successful
console.log('Iframe Service Worker registration successful with scope: ', registration.scope);
// -> SEND MESSAGE TO GET CLIENT ID
registration.active.postMessage({code: "get-client-id"});
}, function (err) {
// registration failed :(
console.log('Service Worker registration failed: ', err);
});
});
}
然后,您需要处理消息并遍历 clientId
s,因此您可以将主要 window 和 iframe ID 保存为变量以用于过滤。
let windowClientId = '';
let iframeClientId = '';
addEventListener('message', (event) => {
if (event.data.code === 'get-client-id') {
self.clients.matchAll().then(function (clients) {
clients.forEach(function (client) {
if (client.frameType === "top-level") {
windowClientId = client.id
} else if (client.frameType === "nested") {
iframeClientId = client.id
}
});
});
}
});
之后,您可以根据需要过滤和处理请求:
self.addEventListener('fetch', function (event) {
// Don't process any requests if worker/iframe are not activated fully
if (!windowClientId || !iframeClientId) {
return;
}
// Don't process main window resources
if (event.clientId === windowClientId) {
return;
}
// do smth
})
- 有一个带有 iframe (
http://localhost:8080
) 的页面和连接的 service worker,它监视来自页面和 iframe 的所有fetch
请求。 - 有一些内部页面请求(加载 favicon、内部脚本等)和 iframe 请求(为 iframe 中的页面加载静态资源)。
- 当 iframe 资源(如 css)具有绝对链接时 - 没问题,很容易区分本地请求(以
http://localhost:8080
开头)和 iframe 请求(以外部 netloc 开头)。 - 当 iframe 资源具有非绝对链接时,例如
images/smth.jpg
- 我无法区分内部和外部请求,因为它们都以http://localhost:8080
开头。
所以,问题是:如何区分这些请求?也许,有一种方法可以查看请求的源元素 (iframe)?
目前,我实施的唯一解决方案是将所有本地资源移动到某个 hard-unique-named
文件夹,如果请求不是以它开头 - 它可以算作 iframe 请求。不过,我希望有更好的解决方案:)
事实证明,解决方案非常简单。首先,您需要在 Service Worker 和 iframe 激活后向其发送消息(从 iframe 发送):
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
navigator.serviceWorker.register('iframe_worker.js').then(function (registration) {
// Registration was successful
console.log('Iframe Service Worker registration successful with scope: ', registration.scope);
// -> SEND MESSAGE TO GET CLIENT ID
registration.active.postMessage({code: "get-client-id"});
}, function (err) {
// registration failed :(
console.log('Service Worker registration failed: ', err);
});
});
}
然后,您需要处理消息并遍历 clientId
s,因此您可以将主要 window 和 iframe ID 保存为变量以用于过滤。
let windowClientId = '';
let iframeClientId = '';
addEventListener('message', (event) => {
if (event.data.code === 'get-client-id') {
self.clients.matchAll().then(function (clients) {
clients.forEach(function (client) {
if (client.frameType === "top-level") {
windowClientId = client.id
} else if (client.frameType === "nested") {
iframeClientId = client.id
}
});
});
}
});
之后,您可以根据需要过滤和处理请求:
self.addEventListener('fetch', function (event) {
// Don't process any requests if worker/iframe are not activated fully
if (!windowClientId || !iframeClientId) {
return;
}
// Don't process main window resources
if (event.clientId === windowClientId) {
return;
}
// do smth
})