是否可以与服务工作者代理iframe子资源?

时间:2016-06-17 20:49:28

标签: javascript iframe service-worker

我有一个依赖第三方资源的iframe。 iframe本身没有src,没有沙盒,通过AJAX填充内容,其子资源(e.x. CSS,图像)存在于不同域的CDN上。

对于我们或我们的客户中断的情况,我希望能够将iframe的CSS切换到我们域中的本地文件。我试图通过我们的服务工作者中的fetch事件来做到这一点:

self.addEventListener('fetch', event => {
  const processEpubRequests = () => fetch(`/epubs/${event.request.url.split('epub-resource/')[1]}`);

  if(event.request.url.startsWith(`https://our_api.com`))
    event.respondWith(
      fetch(event.request)
        .then(response => response.status >= 400 ? processEpubRequests(response) : response)
        .catch(processEpubRequests)
    );
  else
    event.respondWith(
      caches.match(event.request)
        .then(response => response || fetch(event.request))
    );
});

这对于内容的AJAX请求非常有用,但CSS似乎不起作用。它会在网络标签中显示正确的响应,但它就像iframe一样忽略它。

是否可以通过这种方式处理iframe子资源?

谢谢!

修改 我制作了一个Github页面演示来说明我所看到的内容。 页面:https://soluml.github.io/ServiceWorkerIframeExample/ Src:https://github.com/soluml/ServiceWorkerIframeExample/tree/gh-pages

1 个答案:

答案 0 :(得分:2)

原来是Chrome bug out there for this issue。还有several related issues for Firefox

但是,我们可以通过以下方式解决问题:

  1. 将iframe标记设置为相同的原始虚拟src。
  2. <iframe src=".iframe"></iframe>

    1. 在我们的服务工作者中回应虚拟src(如果我们使用一个而不是实际的空白html文件)
    2. &#13;
      &#13;
      if(event.request.url == `${self.location.origin}/.iframe`)
        event.respondWith(
          new Response(`<!doctype html><title>i</title>`, {
            status: 200,
            headers: { "Content-Type": "text/html" }
          })
        );
      &#13;
      &#13;
      &#13;

      1. 使用contentDocument.write()而不是doc.documentElement.innerHTML。这将更改iframe中现有的<html>代码和DOCTYPE。