Книга: JavaScript. Подробное руководство, 6-е издание
18.1.6. Выполнение междоменных НТТР-запросов
18.1.6. Выполнение междоменных НТТР-запросов
Будучи субъектом политики общего происхождения (раздел 13.6.2), объект XMLHttpRequest
может использоваться для отправки HTTP-запросов только серверу, откуда был получен использующий его документ. Это ограничение закрывает дыру безопасности, но также предотвращает возможность использования объекта для вполне законных междоменных запросов. Элементы <form>
и <iframe>
позволяют указывать URL-адреса с другими доменными именами, и в этих случаях броузеры будут отображать документы, полученные из других доменов. Но из-за ограничений политики общего происхождения броузер не позволит оригинальному сценарию исследовать содержимое стороннего документа. При использовании объекта XMLHttpRequest
содержимое документа всегда доступно через свойство responseText
, поэтому политика общего происхождения не позволяет объекту XMLHttpRequest
выполнять междоменные запросы. (Обратите внимание, что элемент <script>
в действительности никогда не был субъектом политики общего происхождения: он будет загружать и выполнять любые сценарии, независимо от их происхождения. Как будет показано в разделе 18.2, такая свобода выполнения междоменных запросов делает элемент <script>
привлекательной альтернативой Ajax-транспорту на основе объекта XMLHttpRequest
.)
Спецификация «ХНН2» позволяет выполнять междоменные запросы к другим веб-сайтам, указанным в заголовке «CORS» (Cross-Origin Resource Sharing) HTTP-ответа. На момент написания этих строк текущие версии броузеров Firefox, Safari и Chrome поддерживали заголовок «CORS», а версия IE8 поддерживала собственный объект XDomainRequest
, который здесь не описывается. Веб-программисту при этом не придется делать ничего особенного: если броузер поддерживает заголовок «CORS» для объекта XMLHttpRequest
и если вы пытаетесь выполнить междоменный запрос к веб-сайту, доступ к которому разрешен в заголовке «CORS», политика общего происхождения просто не будет препятствовать выполнению междоменного запроса, и все будет работать само собой.
Хотя при наличии поддержки заголовка «CORS» не требуется предпринимать какие-то дополнительные шаги для выполнения междоменных запросов, тем не менее имеются некоторые детали, касающиеся безопасности, которые желательно понимать. Во-первых, при передаче имени пользователя и пароля методу open()
объекта XMLHttpRequest
они не будут передаваться в междоменных запросах (в противном случае это дало бы злоумышленникам возможность взламывать пароли). Кроме того, междоменные запросы обычно не допускают включение в них никакой другой информации, подтверждающей подлинность пользователя: cookies и HTTP-лексемы аутентификации обычно не передаются в составе запроса, а любые cookies, полученные в результате выполнения междоменного запроса, уничтожаются. Если для выполнения междоменного запроса требуется выполнить аутентификацию пользователя, перед вызовом метода send()
следует установить свойство withCredentials
объекта XMLHttpRequest
в значение true. Проверка наличия свойства withCredentials
позволит определить наличие поддержки заголовка «CORS» в броузере, хотя обычно этого не требуется.
В примере 18.13 приводится ненавязчивый JavaScript-код, использующий объект XMLHttpRequest
для выполнения HEAD-запросов HTTP с целью получения информации о типах, размерах и датах последнего изменения ресурсов, на которые ссылаются элементы <а>.
HEAD-запросы выполняются по требованию, а полученная информация отображается во всплывающих подсказках. В этом примере предполагается, что информация не будет доступна для междоменных ссылок, тем не менее в броузерах с поддержкой заголовка «CORS» все равно будут выполняться попытки получить ее.
Пример 18.13. Получение информации о ссылках с помощью HEAD-запросов при наличии поддержки заголовка «CORS»
/**
* linkdetails.js
*
* Этот модуль в стиле ненавязчивого JavaScript отыскивает все элементы <а>
* с атрибутом href и без атрибута title, и добавляет в них обработчики
* события onmouseover. Обработчик события выполняет HEAD-запрос с помощью
* объекта XMLHttpRequest, чтобы получить сведения о ресурсе, на который
* указывает ссылка, и сохраняет эту информацию в атрибуте title ссылки,
* благодаря чему эта информация будет отображаться во всплывающей подсказке.
*/
whenReady(function() {
// Поддерживается ли возможность выполнения междоменных запросов?
var supportsCORS = (new XMLHttpRequest()).withCredentials !== undefined;
// Обойти в цикле все ссылки в документе
var links = document.getElementsByTagName('a');
for(var і = 0; і < links.length; і++) {
var link = links[і];
if (!link.href) continue; // Пропустить якоря, не являющиеся ссылками
if (link.title) continue; // Пропустить ссылки с атрибутом title
// Если это междоменная ссылка
if (link.host!==location.host || link.protocol !== location.protocol)
{
link.title = "Ссылка на другой сайт"; // Предполагается, что нельзя
// получить дополнительную информацию
if (!supportsCORS) continue; // Пропустить, если заголовок
// C0RS не поддерживается
// Иначе есть надежда получить больше сведений о ссылке. Поэтому регистрируем
// обработчик события, который предпримет попытку сделать это.
}
// Зарегистрировать обработчик события, который получит сведения
// о ссылке при наведении на нее указателя мыши
if (link.addEventListener)
link.addEventListener("mouseover", mouseoverHandler, false);
else
link.attachEvent("onmouseover", mouseoverHandler);
}
function mouseoverHandler(e) {
var link = e.target || e.srcElement; // Элемент <a>
var url = link, liref; // URL-адрес ссылки
var req = new XMLHttpRequest(); // Новый запрос
req.open("HEAD", url); // Запросить только заголовки
req.onreadystatechange = function() { // Обработчик события
if (req.readyState !== 4) return; // Игнорировать незаверш. запросы
if (req.status === 200) { // В случае успеха
var type = req.getResponseHeader("Content-Type"); //Получить
var size = req.getResponseHeader("Content-Length"); //сведения
var date = req.getResponseHeader("Last-Modified"); //о ссылке
// Отобразить сведения во всплывающей подсказке,
link.title = "Тип: " + type + " n" +
"Размер: " + size + " n" + "Дата: " + date;
}
else {
// Если запрос не удался и подсказка для ссылки еще не содержит текст
// "Ссылка на другой сайт", вывести сообщение об ошибке,
if (!link.title)
link.title = "Невозможно получить сведения: n" + req.status + " " + req.statusText;
}
};
req.send(null);
// Удалить обработчик: попытка получить сведения выполняется только один раз.
if (link.removeEventListener)
link.removeEventListener("mouseover", mouseoverHandler, false);
else
link.detachEvent("onmouseover", mouseoverHandler);
}
});
- Улучшенный оптимизатор запросов
- Асинхронный сервер и отмена выполняющихся запросов
- 1. Оператор Select – базовый оператор языка структурированных запросов
- 2. Унарные операции на языке структурированных запросов
- 3. Бинарные операции на языке структурированных запросов
- 4. Использование подзапросов
- Обработка запросов с помощью PHP
- 8.4.5. Выполнение внешних команд
- Лекция 11. История запросов
- 6.3. Импорт запросов на перенос
- Выполнение макросов
- Практическая работа 46. Выполнение расчетов с использованием Мастера функций