Greasemonkey づいている連休です。サーバからデータ受信して処理したいのですが、GM_xmlhttpRequest だと 5KB くらいしか取得できないっぽいです。しかもサーバが Range ヘッダを無視してくれるという状況です。
検索したのですが見つからなかった(ちゃんと調べてない奴ほど、こういうことを言う)ので、強引なスクリプトを書いてみました。
- データを取得する側の文書を receiver、取得される HTML 文書を sender とします。
- receiver 上のスクリプトが GM_setValue('req',true) に指定する
- receiver に object 要素を埋め込み、sender の URL を表示させる。
- sender 上のスクリプトは GM_setValue('req',false) であることを確認したら、req を false にして、文書の一部を GM_setValue('buffer', ...) する
- receiver 上のスクリプトが req が false になっていることを確認したら、GM_getValue('buffer') する
- 2~5 を繰り返す。
以下がサンプル。httpget と httpsend がコアの関数です。Unicode のエスケープには、sawatの日記 - Unicodeエスケープ を使っています。長くてすみません。もっと、いいやり方ないかなぁ。
// ==UserScript==
// @name voexample
// @namespace http://localhost/
// @description Emulating HTTP GET via object element
// @include http://example.com/receiver.htm
// @include http://example.com/sender.htm
// ==/UserScript==
(function (){
var receiverurl = 'http://example.com/receiver.htm';
var senderurl = 'http://example.com/sender.htm';
function httpget(url, callback) {
function receive(callback) {
var data = "";
function closure () {
function unescapeUnicode(str) {
return str.replace(/\\u([a-fA-F0-9]{4})/g, function(m0, m1) {
return String.fromCharCode(parseInt(m1, 16));
});
}
if (GM_getValue('req')==false) {
var part = GM_getValue('buffer');
if (part==false) {
document.body.removeChild(document.getElementById('__externaldoc'));
callback(unescapeUnicode(data));
} else {
data += part;
GM_setValue('req', true);
startClosure();
}
} else {
startClosure();
}
}
function startClosure(ms) {
setTimeout(closure, ms ? ms : 10);
}
startClosure(0);
}
function loadDocumentInObject(url) {
var o = document.createElement('object');
o.setAttribute('id', '__externaldoc');
o.data = url;
document.body.appendChild(o);
}
GM_setValue('req', true);
loadDocumentInObject(senderurl);
receive(callback);
}
function httpsend() {
function escapeUnicode(str) {
return str.replace(/[^ -~]|\\/g, function(m0) {
var code = m0.charCodeAt(0);
return '\\u' + ((code < 0x10)? '000' :
(code < 0x100)? '00' :
(code < 0x1000)? '0' : '') + code.toString(16);
});
}
var i = 0;
var data = escapeUnicode(document.body.innerHTML);
var step = 4098;
var closure = function() {
if (GM_getValue('rew')==false) {
setTimeout(closure, 10);
} else {
if (i<data.length) {
GM_setValue('buffer', data.substring(i, i+step));
GM_setValue('req', false);
i += step;
setTimeout(closure, 10);
} else {
GM_setValue('buffer', false);
GM_setValue('req', false);
}
}
}
setTimeout(closure, 10);
}
function callback(text) {
var div = document.createElement('div');
div.innerHTML = text.toUpperCase();
document.body.appendChild(div);
}
if (document.location == receiverurl) {
httpget(senderurl, callback);
} else if (document.location == senderurl) {
httpsend();
}
})();