Полноценный кроссдоменный AJAX для пользовательских скриптов Opera 10.6 на транспорте script

Недавно наткнулся на подобную заметку "Кросс-доменные запросы в Opera UserJS" — метод основан на window.name транспорте. Но в комментариях было замечание, что данная техника не работает в Opera 10.64, хотя работает в 10.10. Я детально не вчитывался, но осмелюсь предположить, что причина ужесточение безопасности браузера, с которой я столкнулся впервые, когда вышла Opera 10.10, и тогда же пришлось переписывать некий js скрипт.

Примерно тогда же я собрал маленькую библиотечку, при помощи которой можно полноценно запрашивать результат с сервера на транспорте тега «script»: здесь не нужно серверу отдавать результат в яваскрипте, любой текстовый результат будет получен при помощи волшебного события оперы «Beforescript», который поможет выдрать загруженный контент из тега «script».

Как выполнить запрос и получить ответ.

rmld_ajax("http://ya.ru", 'load_yes', 'error_load');

function load_yes(result)
{
alert (result);
}

function error_load()
{
alert('ошибка');
}


AJAX функция.

function rmld_ajax(url, f_name_poluchatel, f_if_error_server)
{
 f_if_error_server = f_if_error_server || '__none__';
 
 var kom_div = document.getElementById(window.komment_div);
 var f_name = 'rmld_ajax';
 if (!f_name_poluchatel){alert (f_name +': ne peredano imya funkcii poluchatelya rezultata'); return false;}
 
 var tmp = new Date().getTime(); 
 if (tmp != window.rmld_end_tmp)
 {
 window.rmld_end_tmp = tmp;
 
 var get_exist = url.indexOf("?")+1;
 if (get_exist)
 {
 var tmp_exist = url.indexOf("tmp")+1;
 if (tmp_exist){alert ('nelzya ispolzovat parametr tmp v adrese'); return false;}
 var url_end=url+"&tmp="+tmp;
 }
 else
 {
 var url_end=url+"?tmp="+tmp;
 }
 
 var script = document.createElement("script");
 script.src = url_end;
 script.type = "text/javascript";
 script.id = tmp;
 script.className = "rmld_ajax"; // создаем транспорт тег <script className = 'rmld_ajax'>
 
 document.body.appendChild(script);
 
 setTimeout("rmld_obr_result_ajax("+tmp+",'"+f_name_poluchatel+"','"+f_if_error_server+"')", 40);
 }
 else
 {
 // режим ожидания
 setTimeout("rmld_ajax('"+url+"','"+f_name_poluchatel+"','"+f_if_error_server+"')", 50);
 }
}
var rmld_ajax_result = new Array(); // хранит результаты AJAX
var rmld_end_tmp = false; // хранит время
function rmld_obr_result_ajax(tmp, f_name_poluchatel, f_if_error_server)
{
 // обработка запроса
 if (window.rmld_ajax_result[tmp])// если результат получен
 {
 if (window.rmld_ajax_result[tmp] == "__error__" && f_if_error_server != "__none__") // if error function
 {
 var code = ""+f_if_error_server+"()";
 eval(code);
 }
 else
 {
 // удаляем пробелы
 window.rmld_ajax_result[tmp] = window.rmld_ajax_result[tmp].replace(/^\s+/, '');// probely sleva
 window.rmld_ajax_result[tmp] = window.rmld_ajax_result[tmp].replace(/\s+$/, '');// sprava
 
 var code = f_name_poluchatel + "(window.rmld_ajax_result[" + tmp + "]);";
 eval(code);
 }
 document.body.removeChild(document.getElementById(tmp));
 delete (window.rmld_ajax_result[tmp]);
 }
 else
 {
 //жду ответ от сервера не больше 15 сек
 var tmp_now = new Date().getTime();
 if (tmp_now - tmp >15000)
 {
 // долго жду, сообщаю что перезагружу страницу (редко, но случается)
 document.getElementsByTagName("body")[0].innerHTML+="error ajax: data not load in ajax result
reload page after 5 seconds ...";
 setTimeout("location.reload()",5000);
 }
 else
 { 
 setTimeout("rmld_obr_result_ajax("+tmp+",'"+f_name_poluchatel+"','"+f_if_error_server+"')", 20);
 }
 } 
}

window.opera.addEventListener( "Beforescript", function (e){
 if (e.element.className != 'rmld_ajax') return true; 
 
 rez = e.element.text;
 id = e.element.id;
 if (rez == ''){rez='__error__'} // пустой результат определяется как недоступность сервера, и данные в тег <script> не загружены
 rmld_ajax_result[id] = rez;
 
 e.preventDefault(); 
 e.stopPropagation();
 }, true
);


Самое интересное, что, если сервер не отвечает, то e.element.text пустая строка.

Как я это использую.

Используя я эту функцию для обмена данными между браузером и локальным сервером. На основе этого когда у меня в опере работают грабберы, боты, распознаватели капчи и т.п.

Маленькие недостатки.

Чтобы код заработал, вероятно нужно будет добавить localhost в доверенные узлы либо браузер сам спросит разрешения. Т.к. нет возможности передать post данные, то ограничение на длину get запроса нужно настроить на сервере.

P.S. Если количество разных запросов растет, то и растет количество калбак функций, что приводит к «прыгающему» коду и неудобствам отлаживания (особенно в объектах), поэтому идеально было бы переделать этот код в синхронный ajax, чтобы результат запроса выдавался (как бы) через return, т.е:

var result =ajax('url'); 


Это что-то вроде file_get_contents d PHP.


0 комментариев

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.