How do I make Worker() work against cross-domain?
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:
- Have a dedicated location for your SharedWorker() such as a CDN or from the file:// protocol.
- Open this location using a new window or an iframe.
- 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,
精彩评论