当前由Service Worker'fetch'事件提供服务的页面的URL

Rya*_*ggs 2 javascript url offline service-worker

如何获取服务工作者的“获取”事件正在服务的页面的完整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?

Jef*_*ick 5

根据要获得的参与程度,您有两种通用方法:

使用“推荐人”标题信息

如果请求是针对子资源的,并且包含Referer标头,则该标头的值很可能是发出请求的页面的URL。(有一些警告;请阅读此背景信息以进行深入研究。)

在fetch处理程序中,可以使用以下内容读取该标头的值:

self.addEventListener('fetch', event => {
  const clientUrl = event.request.referrer;
  if (clientUrl) {
    // Do something...
  } 
});
Run Code Online (Sandbox Code Playgroud)

使用clientId值

另一种方法是使用clientId(可能)在上公开的值,FetchEvent然后使用clients.get(id)或循环遍历的输出clients.matchAll()以找到匹配项WindowClient。然后,您可以读取该url属性WindowClient。

使用此方法的一个警告是,查找的方法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...
      }
    }
  }
});
Run Code Online (Sandbox Code Playgroud)