How do I make Worker() work against cross-domain?

删除回忆录丶 提交于 2019-12-22 10:27:38

问题


I've been hacking away at BeSpin trying to make it work on my CDN, and I got past the XHR cross domain request for the theme.less by converting to use JSONP. The next problem I've been at is the new Worker(js_file) where js_file is on a different domain.

How do/Can I enable cross-domain for a Worker()?

Can I give the Worker the source code directly? (i.e. build a super large JavaScript file with another file embedded in it) [this is less than ideal, but it should work].


回答1:


try this:

  • create a function with the worker's code
  • get the string representation of the function (.toString), remove the first and last line. Now you have a string with the worker's code
  • create a new BlobBuilder ( window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder)
  • append the worker string to it
  • call getBlob() to get a blob
  • using the window's URL (window.URL || window.webkitURL) create an object url using createObjectURL
  • use that url for the worker

Here's the code

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())
}



回答2:


One way is to create what I call a "Window-Proxy"....

Say you want to host a worker on a cdn which you point to with your new Worker('at.yourCDN.com/worker.js'). This worker might be a SharedWorker which allows your different tabs ON THE SAME DOMAIN to maintain a shared state. Perhaps you want this worker to be accessible to ALL TABS ON DIFFERENT DOMAINS ALSO. In other words, you would like to use the worker as a Service/Server platform.

The Issues: You cannot point to a Worker()/SHaredWorker() that is on a different domain or which uses the file protocol.

This is what I'll be testing this week:

  1. Have a dedicated location for your SharedWorker() such as a CDN or from the file:// protocol.
  2. Open this location using a new window or an iframe.
  3. Make all interactions to this worker interact vicariously through this window or iframe which then forwards the message to the worker -- this window/iframe could simply be a script tag in the DOM which either pulls the worker, or is an inline-worker.

Details: Simply have any window/tab which needs to access this worker run a myWindow.postMessage('my message'), and let myWindow run a port.postMessage(myMsg) to the worker.

Like I said, I haven't tested this yet but I hope this helps.

Also, I'm looking a running a headless browser, or a "Forever Server" with CORS to hopefully mitigate so much iframe-injection and window.postMessageing.

I will post back WHEN I find a solution.

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

I have researched on how to share state using a SharedWorker, not just for multiple-tabs on the same domain, but to also share state between multiple domains - using the SharedWorker as a locally hosted service. This is not a solution, but here's the code to demonstrate how to build a worker from the FileReader API:

//THE 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>

//THE CODE FROM A WORKER FILE ON THE DESKTOP:

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();
};

POSSIBLE SOLUTIONS:

As far as a CDN-Worker goes, it seems that we cannot use FileReader/BlobBuilder as these will create our 'own' worker object in the local heap. It seems we cannot use CORS as a server with CORS enabled can pitch the worker-code via XMLHttpRequest, but creating a new Worker('http://from.mycors.com/enabled/server') fails with the same "DOM Exception 18" SecurityError that we've seen all too much.

The best solution may be the "Window-Proxy" method detailed above (iframe.postMessage() to iframe on another server with its own worker, on window.onmessage forward message to worker). Note that if you plan to leverage another internet-protocol other than http, window.postMessage uses http.

Alternatively, some have resorted to running google-chrome --allow-file-access-from-files -- but this is obviously risky for a production scenario.

Another avenue is to create a rendezvous-point for a WebRTC architecture, which maybe the most robust.

I hope this saves you a lot of unnecessary research, and inspires a better solution.

Cheers,



来源:https://stackoverflow.com/questions/4415382/how-do-i-make-worker-work-against-cross-domain

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!