如何检查URL是否与当前页面和/或工作者源相同

时间:2018-12-11 11:51:56

标签: javascript web-worker

这里有一个类似的问题

javascript How to check if a URL is same origin as current page?

不幸的是,它没有指定答案必须同时在页面和工作程序中起作用,因此所有答案都不能在工作程序中起作用。

特别是我正在尝试使用fetch API以尽可能自动的方式来获取图像。提取图像后,我想将模式设置为cors,但前提是URL的来源不同。我需要知道如何在页面上下文和辅助上下文中做到这一点。

伪代码

function loadImageBitmap(url) {
  const options = {};
  if (urlIsNotSameOrigin(url)) {
    options.mode = 'cors'; 
  }
  return fetch(url, options)
  .then((response) => {
    if (!response.ok) {
      throw response;
    }
    return response.blob();
  }).then((blob) => {
    return global.createImageBitmap(blob);
  });
}

function urlIsNotSameOrigin(url) {
  // what do I put here?
}

// examples
async function main() {
  const bitmaps = Promise.all([
    'https://notsamedomain.com/foo.jpg',
    '../relative/image.png',
    '/absolute/thing.jpg',
    '//other/absolute/thing.jpg',
    'https://samedomain.com/bar.gif',
  ].map(loadImageBitmap));
}
    

我看到的大多数解决方案都是制作一个锚点<a>元素,分配src属性,然后读取它。但是工作人员中不存在锚。 URL对象似乎无法像锚一样处理相对资源。

1 个答案:

答案 0 :(得分:2)

URL()构造函数和锚点 元素之间的区别是 URL()构造函数不是Node它也没有附加到特定的 Document 对象,因此没有baseURI可以挂接。

因此,要使 URL()构造函数的行为与锚点 元素相同,您需要传递一个 baseURI 作为second argument of the constructor

这意味着,只要生成的 URI 是有效的,在文档new URL(uri, document.baseURI)中将返回与Object.assign(document.createElement('a'), {href: uri})相同的URL属性。

现在,在Worker中,我们仍然也无法访问 Node baseURI ,并且还不清楚您要挂接哪个对象。

在大多数情况下,您可以简单地使用self.location.href作为基本URI,而如果要获取同源资源,则实际上可能就是您想要的,但是如果您确实从blobURL初始化了Worker, ,您可能必须从主要范围传递它,就像我在StackSnippet®的过度保护的iframe中所做的那样。

// init worker from a blobURI...
const worker_url = getWorkerURL(worker_script);
const worker = new Worker(worker_url);
worker.onmessage = e => console.log(e.data);

worker.postMessage({
  // we pass the base URL
  base: 'https://samedomain.com/foo.html',
  uris: [
    'https://notsamedomain.com/foo.jpg',
    '../relative/image.png',
    '/absolute/thing.jpg',
    '//other/absolute/thing.jpg',
    'https://samedomain.com/bar.gif'
    ]
});

//__MISC__________
// gets our Worker's blobURL based on a Blob made
// from a <script> element textContent
function getWorkerURL(el) {
  const content = el.textContent;
  const blob = new Blob([content], {type: 'application/javascript'});
  return URL.createObjectURL(blob);
}
<script id="worker_script" type="worker_script">
  onmessage = e => {
    const d = e.data;
    
    // if we weren't in a null origined iframe's blobURI we could do
    //const self_url = new URL(location.href)
    // but here we pass the fake base domain
    const self_url = new URL(d.base);
    const sameorigins = d.uris.filter( uri => {
      try { // wrap in a try-catch, invalids throw
        const url = new URL(uri, self_url);
        return url.origin === self_url.origin;
      } catch(e) { return false; }
    })
    postMessage(sameorigins);
  };
</script>