XMLHTTP (XMLHttpRequest, XHR) — набор API, используемый в языках JavaScript, JScript, VBScript и им подобных для пересылки различных данных (XML, XHTML, JSON и т.д.) по HTTP-протоколу между браузером и веб-сервером. Позволяет осуществлять HTTP-запросы к удаленному серверу без необходимости перезагружать страницу.
XMLHTTP является важной составляющей технологии AJAX (Asynchronous JavaScript And XML), используется многими сайтами для создания динамичных, быстро реагирующих на запросы пользователя приложений. Например XMLHTTP используется такими сайтами как Gmail, Google Suggest, MSN Virtual Earth. XMLHTTP работает только с файлами, находящимися на том же домене, что и использующая XMLHTTP страница. Как и в случае JavaScript, это сделано в целях безопасности (cross-site scripting).
Кроме пересылки XML, через XMLHTTP можно обмениваться данными формы и просто текстовыми строками.
История
Впервые был разработан компанией Microsoft, появившись в компоненте Outlook Web Access программы Microsoft Exchange Server 2000. Он был назван IXMLHTTPRequest. Позднее, наработки были включены в состав MSXML 2.0 в виде объекта ActiveX, доступного через JScript, VBScript, или другие скриптовые языки, поддерживающиеся браузером. MSXML 2.0 был включён в состав браузера Internet Explorer 5.
Программисты проекта Mozilla затем разработали совместимую версию, называющуюся nsIXMLHttpRequest в Mozilla 0.6. Доступ к компоненту был реализован через JavaScript-объект, названный XMLHttpRequest. Однако, полной функциональности удалось добиться только в Mozilla 1.0. В дальнейшем эта возможность также была реализована компаниями Apple начиная с Safari 1.2, родственным браузером Konqueror, компанией Opera Software начиная с Opera 8.01, и, вероятно, другими.
Последняя официальная спецификация - версия 1.0 (XMLHttpRequest Version 1.0 от 19 ноября 2009 года), которая имеет статус черновика на утверждении(Last Call Working Draft) и версия 2.0 (XMLHttpRequest Level 2 от 20 августа 2009 года), которая имеет статус черновика.
Методы класса XMLHttpRequest
| Метод | Описание |
|---|---|
| abort() | Отменяет текущий запрос, удаляет все заголовки, ставит текст ответа сервера в null. |
| getAllResponseHeaders() | Возвращает полный список HTTP-заголовков в виде строки. Заголовки разделяются знаками переноса (CR+LF). Если флаг ошибки равен true, возвращает пустую строку. Если статус 0 или 1, вызывает ошибку INVALID_STATE_ERR. |
| getResponseHeader(headerName) | Возвращает значение указанного заголовка. Если флаг ошибки равен true, возвращает null. Если заголовок не найден, возвращает null. Если статус 0 или 1, вызывает ошибку INVALID_STATE_ERR. |
| open(method, URL, async, userName, password) | Определяет метод, URL и другие опциональные параметры запроса; параметр async определяет, происходит ли работа в асинхронном режиме. Последние три параметра необязательны. |
| send(content) | Отправляет запрос на сервер. |
| setRequestHeader(label, value) | Добавляет HTTP-заголовок к запросу. |
| overrideMimeType(mimeType) | Позволяет указать mime-type документа, если сервер его не передал или передал неправильно. Внимание: метод отсутствует в Internet Explorer! |
Свойства класса XMLHttpRequest
| Свойство | Тип | Описание |
|---|---|---|
| onreadystatechange | EventListener | Обработчик события, которое происходит при каждой смене состояния объекта. Имя должно быть записано в нижнем регистре. |
| readyState | unsigned short | Текущее состояние объекта (0 — не инициализирован, 1 — открыт, 2 — отправка данных, 3 — получение данных и 4 — данные загружены) |
| responseText | DOMString | Текст ответа на запрос. Если статус не 3 или 4, возвращает пустую строку. |
| responseXML | Document | Текст ответа на запрос в виде XML, который затем может быть обработан посредством DOM. Если статус не 4, возвращает null. |
| status | unsigned short | HTTP-статус в виде числа (404 — «Not Found», 200 — «OK» и т. д.) |
| statusText | DOMString | Статус в виде строки («Not Found», «OK» и т. д.). Если статус не распознан, браузер пользователя должен вызвать ошибку INVALID_STATE_ERR. |
Ошибки, вызываемые классом XMLHttpRequest
| Название | Код | Описание |
|---|---|---|
| SECURITY_ERR | 18 | Вызывается при попытке совершить запрос, запрещённый настройками безопасности в браузере пользователя. |
| NETWORK_ERR | 101 | Вызывается при ошибке сети (во время синхронного запроса). |
| ABORT_ERR | 102 | Вызывается при прерывании пользователем запроса (во время синхронного запроса). |
Пример использования
План работы с объектом XMLHttpRequest можно представить следующим образом:
- Создание экземпляра объекта XMLHttpRequest
- Установка обработчика события
- Открытие соединения и отправка запроса.
Создание экземпляра объекта XMLHttpRequest
На этой стадии необходима отдельная реализация для разных браузеров. Конструкция создания объекта отличается: в IE 5 - IE 6 она реализована через ActiveXObject, а в остальных браузерах (IE 7 и выше, Mozilla, Opera, Chrome, Netscape и Safari) — как встроенный объект типа XMLHttpRequest.
Вызов для ранних версий Internet Explorer выглядит так:
var req = new ActiveXObject("Microsoft.XMLHTTP");
var req = new XMLHttpRequest();
function createRequestObject() { if (XMLHttpRequest == undefined) { XMLHttpRequest = function() { try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch(e) {} try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch(e) {} try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) {} try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) {} throw new Error("This browser does not support XMLHttpRequest."); }; } return null; }
Установка обработчика событий, открытие соединения и отправка запросов
Эти вызовы выглядят так:req.open(<"GET"|"POST"|...>, <url>, <asyncFlag>); req.onreadystatechange = processReqChange;
req.send(null);
var req; function loadXMLDoc(url) { req = null; if (window.XMLHttpRequest) { try { req = new XMLHttpRequest(); } catch (e){} } else if (window.ActiveXObject) { try { req = new ActiveXObject('Msxml2.XMLHTTP'); } catch (e){ try { req = new ActiveXObject('Microsoft.XMLHTTP'); } catch (e){} } } if (req) { req.open("GET", url, true); req.onreadystatechange = processReqChange; req.send(null); } } function processReqChange() { try { // Важно! // только при состоянии "complete" if (req.readyState == 4) { // для статуса "OK" if (req.status == 200) { // обработка ответа } else { alert("Не удалось получить данные:n" + req.statusText); } } } catch( e ) { // alert('Caught Exception: ' + e.description); // В связи с багом XMLHttpRequest в Firefox приходится отлавливать ошибку // Bugzilla Bug 238559 XMLHttpRequest needs a way to report networking errors // https://bugzilla.mozilla.org/show_bug.cgi?id=238559 } }
Известные проблемы
Проблема с кешированием в Microsoft Internet Explorer
Internet Explorer кеширует GET-запросы. Те авторы, которые не знакомы с кешированием HTTP, ожидают, что GET-запросы не кешируются, или что кеш может быть обойдён, как в случае нажатия кнопки обновления. В некоторых ситуациях избегание кеширования действительно является ошибкой. Одним из решений является использование метода POST, который никогда не кешируется; однако он предназначен для других операций. Другим решением является использование метода запроса GET, включающего уникальную строку запроса с каждым вызовом, как показано на примере ниже.req.open("GET", "xmlprovider.php?hash=" + Math.random());
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // disable IE caching header("Last-Modified: " . gmdate( "D, d M Y H:i:s") . " GMT"); header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1 header("Pragma: no-cache"); // HTTP/1.0
response.setHeader("Pragma", "no-cache"); response.setHeader("Cache-Control", "must-revalidate"); response.setHeader("Cache-Control", "no-cache"); response.setHeader("Cache-Control", "no-store"); response.setDateHeader("Expires", 0);
req.open("GET", "xmlprovider.php"); req.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT"); req.send(null);

