Полноценный кроссдоменный AJAX для пользовательских скриптов Opera 10.6 на транспорте script
Недавно наткнулся на подобную заметку "Кросс-доменные запросы в Opera UserJS" — метод основан на window.name транспорте. Но в комментариях было замечание, что данная техника не работает в Opera 10.64, хотя работает в 10.10. Я детально не вчитывался, но осмелюсь предположить, что причина ужесточение безопасности браузера, с которой я столкнулся впервые, когда вышла Opera 10.10, и тогда же пришлось переписывать некий js скрипт.
Примерно тогда же я собрал маленькую библиотечку, при помощи которой можно полноценно запрашивать результат с сервера на транспорте тега «script»: здесь не нужно серверу отдавать результат в яваскрипте, любой текстовый результат будет получен при помощи волшебного события оперы «Beforescript», который поможет выдрать загруженный контент из тега «script».
Как выполнить запрос и получить ответ.
AJAX функция.
Самое интересное, что, если сервер не отвечает, то e.element.text пустая строка.
Как я это использую.
Используя я эту функцию для обмена данными между браузером и локальным сервером. На основе этого когда у меня в опере работают грабберы, боты, распознаватели капчи и т.п.
Маленькие недостатки.
Чтобы код заработал, вероятно нужно будет добавить localhost в доверенные узлы либо браузер сам спросит разрешения. Т.к. нет возможности передать post данные, то ограничение на длину get запроса нужно настроить на сервере.
P.S. Если количество разных запросов растет, то и растет количество калбак функций, что приводит к «прыгающему» коду и неудобствам отлаживания (особенно в объектах), поэтому идеально было бы переделать этот код в синхронный ajax, чтобы результат запроса выдавался (как бы) через return, т.е:
Это что-то вроде file_get_contents d PHP.
Примерно тогда же я собрал маленькую библиотечку, при помощи которой можно полноценно запрашивать результат с сервера на транспорте тега «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 комментариев