XMLHttpRequest status 0 (responseText пуст)

105

Невозможно получить данные с помощью XMLHttpRequest (статус 0 и responseText пуст):

xmlhttp = новый XMLHttpRequest ();
xmlhttp.open («GET», «http://www.w3schools.com/XML/cd_catalog.xml», true);
xmlhttp.onreadystatechange = функция () 
{
  если (xmlhttp.readyState == 4)
    предупреждение ("статус" + xmlhttp.status);
}
xmlhttp.send ();

Предупреждает «статус 0».

Такая же ситуация с запросом localhost (cd_catalog.xml сохраняется как локальный файл)

xmlhttp.open ("GET", "http: //localhost/cd_catalog.xml", true);

Но с IP-запросом localhost

xmlhttp.open ("GET", "http://127.0.0.1/cd_catalog.xml", true);

и с запросом локального файла

xmlhttp.open («ПОЛУЧИТЬ», «cd_catalog.xml», истина);

все ок (статус 200)

Что может вызвать проблему (статус = 0) с онлайн-запросом?

PS: Live HTTP Headers показывает, что все в порядке во всех 4 случаях:

  HTTP / 1.1 200 ОК
  Длина содержимого: 4742

PS2: локальный веб-сервер Apache на VMWare (хост-ОС Win7, гостевая ОС Ubuntu, сетевой адаптер - NAT). Браузер - Firefox.

аригаса
источник
1
Ваша тестовая страница http://127.0.0.1случайно не попала? ;)
Roatin Marth
Да. <code> 127.0.0.1/CDCatalogTest.html </code>
arigasa
7
Вы ответили на свой вопрос. XMLHttpRequestне может выполнять междоменные запросы. Однако есть некоторые обходные пути. Взгляните, например, на jquery.
мезе
Используйте php, чтобы получить файл. Небольшой обходной
2
@meze: Междоменные вызовы работают с jQuery. Но как это может не работать с простым JavaScript, если jQuery реализован в JavaScript? Это не имеет никакого смысла для меня. Использует ли jQuery какой-нибудь неприятный обходной путь?
Gruber

Ответы:

55

status равен 0, когда ваш html-файл, содержащий скрипт, открыт в браузере через файловую схему. Обязательно поместите файлы на свой сервер (apache или tomcat, что угодно), а затем откройте его по протоколу http в браузере. (т.е. http: //localhost/myfile.html ) Это решение.

Abhishek_8
источник
1
Почему за это отказывают? Это правда! Запросы XHR из file: // URL-адреса файлов также на URL-адресах file: // фактически имеют статус == 0 в случае успеха (проверено на FF 24.0.5).
Daniel Roethlisberger
3
Я также получаю статус == 0 в случае успеха в Safari версии 6.1.6.
Planar
У меня статус = 0 (но статус 200 в сети) с использованием временной надстройки «Загрузить» в firefox
JobaDiniz
1
все еще действующий ответ. HTTP-ответ - 200 для реальных удаленных схем (http и др.) И 0 для локального файла ( file://схемы). Очевидно, вам нужно сначала разрешить загрузку локального файла, отключив CORS.
pid
32

Причина ваших проблем в том, что вы пытаетесь выполнить междоменный вызов, но это не удается .

Если вы занимаетесь разработкой localhost, вы можете совершать междоменные вызовы - я делаю это все время.

Для Firefox вы должны включить его в настройках конфигурации.

signed.applets.codebase_principal_support = true

Затем добавьте что-то вроде этого в свой открытый код XHR:

  if (isLocalHost()){
    if (typeof(netscape) != 'undefined' && typeof(netscape.security) != 'undefined'){
      netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');
    }
  }

Для IE, если я правильно помню, все, что вам нужно сделать, это включить настройку безопасности браузера в разделе «Разное → Доступ к источникам данных через домены», чтобы заставить его работать с ActiveX XHR.

IE8 и более поздние версии также добавили междоменные возможности к собственным объектам XmlHttpRequest, но я еще не играл с ними.

Slammer
источник
8
На случай, если кому-то это понадобится, для Chrome вам нужно запустить новый экземпляр (без каких-либо уже открытых) и использовать--allow-file-access-from-files
TheZ
@TheZ: Ты на 100%? Я слышал, что вам нужно только запустить новый экземпляр Chrome с --allow-file-access-from-filesпереключателем, но вам не нужно закрывать все другие запущенные экземпляры. Точно так же, как и в случае с Chrome Incognito Mode - вы можете использовать его, не закрывая другие запущенные экземпляры.
Trejder
Похоже, что поддержка «UniversalBrowserRead» была прекращена, поэтому этот обходной путь невозможен.
perilandmishap
Кроме того, это может произойти, когда вы запрашиваете http-страницу со страницы https (например, расширение в браузере).
sibvic
Я столкнулся с этой проблемой, несмотря на то, что html-страница и сценарий AJAX находятся в одном домене. Но, как ни странно, это влияет только на некоторые сценарии, особенно на любые сценарии, которые обращаются к ресурсам MongoDB. Есть какие-нибудь подсказки относительно того, почему это так?
Дэвид Эдвардс
26

На самом деле убедитесь, что ваш тип кнопки - Button not Submit, это вызвало конфликт статуса, с которым я недавно встречался.

Дьюань
источник
1
Возникает конфликт, потому что отправка формы имеет некоторое поведение по умолчанию, которое вам нужно предотвратить, если вы обрабатываете событие и сами выполняете вызов ajax. Вы можете предотвратить поведение по умолчанию, взяв событие в свой обработчик и позвонивe.preventDefault()
Джордан
20

Если сервер отвечает на метод OPTIONS, а также на GET и POST (в зависимости от того, какой из них вы используете) с заголовком, например:

Access-Control-Allow-Origin: *

Это может работать нормально. Кажется, в FireFox 3.5 и rekonq 0.4.0. По-видимому, с этим заголовком и начальным ответом на OPTIONS сервер говорит браузеру: «Давай, позволь этому междоменному запросу пройти».

Алекс Робинсон
источник
3
Это правильный ответ! Посетите en.wikipedia.org/wiki/Cross-origin_resource_sharing для получения дополнительной информации. Если вы добавите этот заголовок, он будет не «может работать», а «будет работать». NB. Вам нужно добавить HTTP / ответ / заголовок, поэтому вы можете сделать это только на сервере, который вы контролируете. Невозможно напрямую получить w3schools.com/XML/cd_catalog.xml с помощью XMLHttpRequest(т.е. согласно исходному вопросу), потому что этот ресурс (по крайней мере, по состоянию на 24 апреля 2015 г.) не включает такой заголовок CORS.
MikeBeaton
13

Учитывайте также тайм-аут запроса :

Современный браузер возвращает readyState = 4 и s tatus = 0, если до ответа сервера прошло слишком много времени.

Андреа Савохардо
источник
3
@AndreaSavojardo: Есть ли у вас какие-либо ссылки (например, сообщение на MDN) о том, соответствует ли это поведение стандартам?
Александр Абакумов
@AndreaSavojardo У меня readyState = 4 и status = 0, и сервер не работает, но предупреждение об ошибке показывается мне быстро .... сколько времени проходит для "тайм-аута запроса"?
7

Добавьте setRequestHeader("Access-Control-Allow-Origin","*")к своему серверу ответ.

Иван
источник
3

Я столкнулся с подобной проблемой. Все было в порядке, «состояние готовности» равнялось 4, а «статус» - 0. Это произошло потому, что я использовал портативный сервер Apache PHP, а мой файл, в котором я использовал объект «XMLHttpRequest», был файлом HTML. Я изменил расширение файла на php, и проблема была решена.

Рейан
источник
3

Откройте консоль javascript . Вы увидите там сообщение об ошибке. В моем случае это был CORS.

Ярекчек
источник
2

Чтобы ответить на вопрос, почему http://127.0.0.1/cd_catalog.xmlработает, а http://localhost/cd_catalog.xmlнет: Firefox рассматривает 127.0.0.1 и localhost как два разных домена.

Томи Аарнио
источник
2

Чтобы понять, в чем проблема, при появлении загадочной ошибки 0 перейдите в ... | Дополнительные инструменты | Инструменты разработчика (Ctrl + Shift + I) в Chrome (на странице с ошибкой)

Прочтите красный текст в журнале, чтобы получить истинное сообщение об ошибке. Если там слишком много, щелкните правой кнопкой мыши и «Очистить консоль», затем повторите последний запрос.

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

У меня уже было:

Access-Control-Allow-Origin: *

Но нет:

Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Authorization

в заголовке ответа моего веб-сервиса.

После того, как я добавил это, моя ошибка нуля исчезла с моего собственного веб-сервера, а также при запуске файла index.html локально без веб-сервера, но все еще давала ошибки в ручке кода.

Вернуться к ... | Дополнительные инструменты | Инструменты разработчика при получении ошибки в коде, и там четко объяснено: кодовое слово использует https, поэтому я не могу звонить по http, так как безопасность ниже.

Поэтому мне нужно разместить свой веб-сервис на https.

Знание, как получить истинное сообщение об ошибке - бесценно!

майя
источник
Я использовал этот подход (f12 в хроме) и обнаружил, что пытался перейти с https на http, что молча терпело неудачу, не предоставляя ничего полезного. СООБЩЕНИЕ ОБ ОШИБКЕ: VM1152: 1 Смешанное содержимое: страница по адресу 'https://mysiteoriginsite' была загружена по HTTPS, но запросила небезопасную конечную точку XMLHttpRequest 'http://MyDestinationSite/MyService.svc'. Этот запрос был заблокирован; контент должен обслуживаться по HTTPS.
GrayDwarf
1

Вот еще один случай status === 0, связанный с загрузкой:

Если вы прикрепите 'load'обработчик событий к XHR.upload, как предлагает MDN (прокрутите вниз до части загрузки «Мониторинг хода выполнения»), объект XHR будет иметь, status=0а все остальные свойства будут пустыми строками. Если прикрепить'load' обработчик непосредственно к объекту XHR, как при загрузке контента, все будет в порядке (если вы не работаете с localhost).

Однако, если вы хотите получить надежные данные в своих 'progress'обработчиках событий, вам необходимо прикрепить обработчик к самому объекту XHR XHR.upload, а не напрямую.

Я тестировал это пока только на Chrome OSX, поэтому я не уверен, насколько проблема здесь в документации MDN и сколько стоит реализация Chrome ...

Ericoco
источник
1

Алекс Робинсон уже (и первый) дает правильный ответ на этот вопрос. Но чтобы уточнить это немного подробнее ...

Вы должны добавить заголовок HTTP-ответа:

Access-Control-Allow-Origin: *

Если вы сделаете это, результат будет не просто «может сработать», но «будет работать».

NB. Вам нужно добавить заголовок HTTP- ответа, поэтому вы можете сделать это только на сервере, который вы контролируете. Невозможно напрямую получить http://w3schools.com/XML/cd_catalog.xml из исходного URL-адреса, используяXMLHttpRequest (согласно вопросу OP), потому что этот ресурс не поддерживает (по крайней мере, не с 24 апреля 2015 г.) включить любой такой заголовок CORS.

http://en.wikipedia.org/wiki/Cross-origin_resource_sharing дает дополнительную информацию.

Майк Битон
источник
0

Моя проблема, похожая на эту, была решена проверкой моего html-кода. У меня был onclickобработчик в моей кнопке отправки формы для метода. нравится это: onclick="sendFalconRequestWithHeaders()". Этот метод, в свою очередь, вызывает ajax, как и ваш, и делает то, что я хочу. Но не так, как ожидалось, мой браузер ничего не возвращал.

Узнал от чьего-то тяжелого труда , я вернул false в этом обработчике и решил. Позвольте мне сказать , что до прибытия на этот пост, я потратил целый 3-дневный уик - энд и полдня в офисе , написание кода , реализующий CORS filters, jetty config, другой jersey and embedded jettyсвязанный материал - просто , чтобы исправить это, вращаясь все мое понимание вокруг. cross domain ajax requestsИ стандартов вещи. Было смешно, как простые ошибки в javascript делают вас тупым.

По правде говоря, я попробовал signed.applets.codebase_principal_support = trueи написал isLocalHost() **if**. может быть, этот метод должен быть реализован нами, firefox говорит, что его нет. Теперь мне нужно очистить свой код, чтобы отправить исправление git. Благодаря этому кто-то.

Шива Тумма
источник
0

Запрос браузера «127.0.0.1/somefile.html» поступает на локальный веб-сервер без изменений, а «localhost / somefile.html» может поступать как «0: 0: 0: 0: 0: 0: 0: 1 / somefile.html. "если поддерживается IPv6. Таким образом, последний может быть обработан как переход от одного домена к другому.

Массимо Росио
источник
0

Алекс Робинсон и bmju предоставили ценную информацию для понимания проблем перекрестного происхождения. Я хотел добавить, что вам может потребоваться явный вызов OPTIONS в вашем клиентском коде, прежде чем делать желаемый GET / POST (например, для конечной точки службы CORS OAuth). Ваш браузер / библиотека не может автоматически обрабатывать запрос OPTIONS. Грубер, это один из возможных ответов на ваш вопрос.

Тим МакКоннелл
источник
0

У меня была такая же проблема (readyState было 4, а статус 0) , затем я применил другой подход, описанный в этом руководстве: https://spring.io/guides/gs/consuming-rest-jquery/

Он вообще не использовал XMLHttpRequest , вместо этого он использовал метод jquery $ .ajax () :

<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <script src="hello.js"></script>
</head>

<body>
    <div>
        <p class="greeting-id">The ID is </p>
        <p class="greeting-content">The content is </p>
    </div>
</body>

и для файла public / hello.js (или вы можете вставить его напрямую в тот же HTML-код):

$(document).ready(function() 
 {
    $.ajax({
        url: "http://rest-service.guides.spring.io/greeting"
   }).then(function(data) {
      $('.greeting-id').append(data.id);
      $('.greeting-content').append(data.content);
   });
 });
RMDev
источник
2
Вы ведь понимаете, что jQuery $.ajax()используется XMLHttpRequestвнутри, не так ли?
Manngo 02
-1

У меня была эта проблема, потому что я использовал в 0.0.0.0качестве своего сервера, изменил его на, localhostи он работает.

Вад
источник
-4

Изменить: пожалуйста, прочтите комментарии Мальволио ниже, поскольку знания этого ответа устарели.

Вы не можете выполнять междоменные запросы XMLHttpRequests.

Вызов 127.0.0.1работает, потому что ваша тестовая страница находится по адресу 127.0.0.1, и локальный тест также работает, так как, ну ... это локальный тест.

Два других теста терпят неудачу, потому что JavaScript не может взаимодействовать с удаленным сервером через XMLHttpRequest.

Вместо этого вы можете рассмотреть:

  • XMLHttp-запросите ваш собственный сервер для получения вашего удаленного XML-контента (например, скрипт php)
  • Попытка использовать такую ​​службу, как GoogleAppEngine, если вы хотите сохранить в ней полный JavaScript.

надеюсь, это поможет

Габриэль Шпренгер
источник
40
Это просто неправильно. Вы можете выполнять междоменные запросы XMLHttpRequests.
Мальволио
1
«Вы не можете», как в «Тебе не следует этого делать, потому что это никогда не бывает хорошей идеей»
Габриэль Спренгер
24
- достаточно честно, но я не знаю, является ли комментарий лучшим форумом для этого. Междоменные запросы XMLHttpRequests, безусловно, имеют некоторые проблемы с безопасностью, но они предлагают все инструменты, необходимые для решения этих проблем. Кроме того, они позволяют веб-сайтам легко предлагать услуги другим веб-сайтам, использовать CDN для распространения данных и быстрее реагировать на запросы пользователей. Если у вас есть какие-либо конкретные вопросы, вы можете написать мне или, что еще лучше, задать вопрос здесь, в SO, и привлечь к нему мое внимание.
Malvolio
2
@GabrielSprenger: Междоменные XMLHttpRequests - это не только хорошая идея, они настолько распространены в наши дни, что НЕ делать их в современном веб-приложении (помимо каких-то HelloWorlds) - это что-то нелепое. Любая внешняя служба REST, которую использует ваше приложение, требует междоменного доступа XMLHttpRequest. Вот почему был добавлен весь этот CORS-материал.
Александр Абакумов