开发者

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

开发者 https://www.devze.com 2023-01-29 19:51 出处:网络
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

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 Work开发者_运维技巧er 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].


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


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,

0

精彩评论

暂无评论...
验证码 换一张
取 消