如何获取服务工作者的’fetch’事件所服务的页面的完整URL?
“self.location”属性似乎只引用站点的根URL.例如,如果页面https://example.com/folder/pagename.html正在执行服务工作者正在拦截的提取,则服务工作者的“self.location”属性返回“https://example.com”.
event.currentTarget.location和event.explicitOriginalTarget.location,event.originalTarget和event.target都返回服务工作者.js文件的URL.
如何获取触发fetch事件的页面的完整URL?
解决方法:
您有两种常规方法,具体取决于您希望获得的方式:
使用“Referer”标题信息
如果请求是针对子资源并包含Referer标头,那么该标头的值很可能是发出请求的页面的URL. (有一些警告;请阅读this background info以深入研究.)
在获取处理程序中,您可以使用以下内容读取该标头的值:
self.addEventListener('fetch', event => {
const clientUrl = event.request.referrer;
if (clientUrl) {
// Do something...
}
});
使用clientId值
另一种方法是使用(可能)在FetchEvent上公开的clientId值,然后使用clients.get(id)或循环遍历clients.matchAll()的输出以查找匹配的WindowClient.然后,您可以读取该WindowClient的url属性.
这种方法的一个警告是,查找WindowClient的方法都是异步的,并返回promise,所以如果你以某种方式使用客户端窗口的URL来确定是否要调用event.respondWith(),你运气不好(当首次调用FetchEvent处理程序时,需要同步做出决定).
为了使这种方法起作用,需要支持不同的东西组合,我不确定哪些浏览器目前支持我提到的所有内容.我知道Chrome 67确实存在(因为我刚刚在那里测试过),但是如果这个功能对你很重要,你应该在其他浏览器中查看.
self.addEventListener('fetch', async event => {
const clientId = event.clientId;
if (clientId) {
if ('get' in clients) {
const client = await clients.get(clientId);
const clientUrl = client.url;
// Do something...
} else {
const allClients = await clients.matchAll({type: 'window'});
const filtered = allClients.filter(client => client.id === clientId);
if (filtered.length > 0) {
const clientUrl = filtered[0].url;
// Do something...
}
}
}
});