2010-12-11 199 views
3

我一直在试图让BeSpin在我的CDN上工作,并且通过转换为使用JSONP来通过XHR跨域请求获得theme.less。我遇到的下一个问题是新的Worker(js_file),其中js_file位于不同的域中。如何使Worker()对抗跨域工作?

如何/我可以为Worker()启用跨域?

我可以直接给工人提供源代码吗? (即构建一个嵌入了另一个文件的超大型JavaScript文件)[这并不理想,但它应该工作]。

回答

2

试试这个:

  • 创建功能与工人的代码
  • 得到函数(的ToString)的字符串表示,除去第一和最后一行。现在你有一个工人的一串代码
  • 创建一个新的BlobBuilder(window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder)
  • 追加工人串吧
  • 调用getBlob()得到一个团块
  • 使用窗口的URL(window.URL || window.webkitURL)使用createObjectURL
  • 使用该网址为职工

这里创建一个对象的URL代码

function getUrlForWorker(workerFunction) { 
    var BlobBuilder = window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder, 
    URL = window.URL || window.webkitURL, 
     mainString = workerFunction.toString(), 
     bodyString  = mainString.substring(mainString.indexOf("{")+1, mainString.lastIndexOf("}")), 
     bb = new BlobBuilder() 

    bb.append(bodyString) 

    return URL.createObjectURL(bb.getBlob()) 
} 
+0

这将在'heap'中创建一个'new Object',而不是使用该文件本身,是否正确?我问,因为我想使用'SharedWorker',它可以在同一个域的多个选项卡上使用,但允许多个域(按照约定)能够将其用作分布式网络中的服务。 – Cody 2013-08-20 05:03:18

+0

丑,但它的作品。但是,“删除第一行和最后一行”应该是“在{'''之间提取函数体”。 – 2016-09-08 07:24:44

0

一种方法是建立我所说的“窗口 - 代理” ......

说你要主办您指向与您new Worker('at.yourCDN.com/worker.js') CDN的一名工人。此工作人员可能是SharedWorker,它允许您在不同的标签在同一个域上维护共享状态。也许你希望这个工作人员可以访问不同领域的所有标签。换句话说,您希望将该工作者用作服务/服务器平台。

问题: 您不能指向位于不同域或使用文件协议的Worker()/ SHaredWorker()。

这是我会在本周的测试:

  1. 有一个专门的位置为您SharedWorker(),如CDN或从file://协议。
  2. 使用新窗口或iframe打开此位置。
  3. 使与该工作者的所有交互通过此窗口或iframe进行交互,然后将该消息转发给工作人员 - 此窗口/ iframe可以简单地是DOM中的脚本标记,它可以拖动工作人员,工人。

详情: 只要有任何窗口/标签这就需要访问此工人运行myWindow.postMessage('my message'),并让myWindow运行port.postMessage(myMsg)给工人。

就像我说的,我还没有测试过,但我希望这有助于。

此外,我正在寻找一个运行无头浏览器,或与CORS“永远服务器”,希望缓解这么多的iframe注入和window.postMessageing。

当我找到解决方案时,我会回复。

************************************ EDIT ************************************

我已经研究了如何使用SharedWorker共享状态,不只是在同一个域多标签,而且还多个域之间共享状态 - 使用SharedWorker为本地托管服务。这不是一个解决方案,但这里演示了如何从FileReader API构建一个工人代码:

// DOM的CODE:

<b>1</b> 
<input id="uploadImage" type="file" name="myPhoto" onchange="onSelect();" autofocus="true" /> 
<script> 
var fReader = new FileReader(); 
fReader.onload = function(e){ 
    var blob = new Blob([e.target.result], {type: 'text/javascript'}); 
    var blobURL = URL.createObjectURL(blob); 
    var w = new SharedWorker(blobURL); 
    w.port.onmessage = function(e){ 
    console.log('%%^', e); 
    }; 
    w.port.start(); 
    w.port.postMessage('Echo'); 
}; 
function onSelect(e){ 
    var file = document.getElementById("uploadImage").files[0]; 
    var dataURL = fReader.readAsText(file); 
} 
</script> 

//在worker文件桌面上的CODE :

var ports = ports || []; 
self.onconnect = function(e){ 
    var port = e.ports[0]; 
    ports.push(port); 

    port.addEventListener('message', function(e){ 
    port = e.target; 
    ports.forEach(function(p){ 
     p.postMessage('gWorker:: ' + e.data); 
    }); 
    }, false); 

    port.start(); 
}; 

可能的解决方案:

至于用CDN的工人去,我们似乎不能用FileReader/BlobBuilder,因为这些将在当地heap中创建我们的“自己的”worker object。看起来我们不能使用CORS作为服务器,CORS启用后可以通过XMLHttpRequest调用工作代码,但是创建new Worker('http://from.mycors.com/enabled/server')失败,因为我们已经看到太多相同的“DOM Exception 18SecurityError

最好的解决方案可能是上面详细描述的“Window-Proxy”方法(iframe.postMessage()到另一个带有自己工作者的服务器上的iframe,window.onmessage转发给worker的消息)。请注意,如果您打算利用http以外的其他Internet协议,则window.postMessage将使用http。

另外,有些公司已经开始运行google-chrome --allow-file-access-from-files - 但这对于生产场景来说显然是有风险的。

另一个途径是为WebRTC架构创建一个交会点,这可能是最强大的。

我希望这可以为您节省大量不必要的研究,并激发出更好的解决方案。

干杯,