XMLHttpRequest estado 0 (responseText está vacío)

104

No se pueden obtener datos con XMLHttpRequest (el estado 0 y responseText están vacíos):

xmlhttp = new XMLHttpRequest ();
xmlhttp.open ("OBTENER", "http://www.w3schools.com/XML/cd_catalog.xml", verdadero);
xmlhttp.onreadystatechange = función () 
{
  si (xmlhttp.readyState == 4)
    alerta ("estado" + xmlhttp.status);
}
xmlhttp.send ();

Alerta "estado 0".

La misma situación con la solicitud localhost (cd_catalog.xml se guarda como un archivo local)

xmlhttp.open ("OBTENER", "http: //localhost/cd_catalog.xml", verdadero);

Pero con la solicitud de IP localhost

xmlhttp.open ("OBTENER", "http://127.0.0.1/cd_catalog.xml", verdadero);

y con la solicitud de archivo local

xmlhttp.open ("OBTENER", "cd_catalog.xml", verdadero);

todo está bien (estado 200)

¿Qué puede causar el problema (estado = 0) con la solicitud en línea?

PD: Live HTTP Headers muestra que todo está bien en los 4 casos:

  HTTP / 1.1 200 OK
  Longitud del contenido: 4742

PS2: servidor web local Apache en VMWare (sistema operativo host Win7, sistema operativo invitado Ubuntu, adaptador de red - NAT). Navegador: Firefox.

arigasa
fuente
1
¿Está tu página de prueba http://127.0.0.1por casualidad? ;)
Roatin Marth
Si. <code> 127.0.0.1/CDCatalogTest.html </code>
arigasa
7
Respondiste tu pregunta. XMLHttpRequestno puede realizar solicitudes entre dominios. Sin embargo, existen algunas soluciones. Mira jquery, por ejemplo.
meze
Utilice php para obtener el archivo. Pequeña solución alternativa
2
@meze: las llamadas entre dominios funcionan con jQuery. Pero, ¿cómo no puede funcionar con JavaScript simple, ya que jQuery está implementado en JavaScript? No tiene sentido para mí. ¿JQuery está usando algún tipo de solución desagradable?
Gruber

Respuestas:

55

el estado es 0 cuando su archivo html que contiene el script se abre en el navegador a través del esquema de archivos. Asegúrese de colocar los archivos en su servidor (apache o tomcat lo que sea) y luego ábralo a través del protocolo http en el navegador. (es decir, http: //localhost/myfile.html ) Esta es la solución.

Abhishek_8
fuente
1
¿Por qué se rechaza esto? ¡Es realmente cierto! Las solicitudes XHR de file: // URL de archivos también en file: // URL tienen estado == 0 en caso de éxito (probado en FF 24.0.5).
Daniel Roethlisberger
3
También obtengo el estado == 0 en caso de éxito en Safari Versión 6.1.6.
Planar
Tengo estado = 0 (pero estado 200 en la red) usando Cargar complemento temporal en firefox
JobaDiniz
1
respuesta todavía válida. La respuesta HTTP es 200 para esquemas remotos reales (http et al.) Y 0 para archivo local ( file://esquema). Obviamente, primero debe permitir la carga de archivos locales desactivando CORS.
pid
31

La causa de sus problemas es que está intentando realizar una llamada entre dominios y falla .

Si está desarrollando un host local, puede realizar llamadas entre dominios; yo lo hago todo el tiempo.

Para Firefox, debe habilitarlo en su configuración de configuración

signed.applets.codebase_principal_support = true

Luego agregue algo como esto a su código abierto XHR:

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

Para IE, si mal no recuerdo, todo lo que tiene que hacer es habilitar la configuración de seguridad del navegador en "Varios → Acceder a fuentes de datos en todos los dominios" para que funcione con ActiveX XHR.

IE8 y versiones posteriores también agregaron capacidades de dominio cruzado a los objetos nativos XmlHttpRequest, pero aún no he jugado con ellos.

Prisión
fuente
8
En caso de que alguien lo necesite, para Chrome, debe iniciar una nueva instancia (sin ninguna ya abierta) y usar--allow-file-access-from-files
TheZ
@TheZ: ¿Estás al 100%? Escuché que solo necesita ejecutar una nueva instancia de Chrome, con el --allow-file-access-from-filesinterruptor, pero no tiene que cerrar todas las demás instancias en ejecución. Exactamente como en el caso del modo incógnito de Chrome : puede usarlo sin cerrar ninguna otra instancia en ejecución.
trejder
Parece que se ha eliminado el soporte para 'UniversalBrowserRead', por lo que esta solución no es una opción.
perilandmishap
Además, podría suceder cuando solicita una página http desde la página https (como la extensión en el navegador).
sibvic
Me encuentro con este problema, a pesar de que la página html y el script AJAX residen en el mismo dominio. Pero, extrañamente, solo afecta a algunos scripts, sobre todo a los que acceden a los recursos de MongoDB. ¿Alguna pista de por qué es esto?
David Edwards
26

En realidad, asegúrese de que su tipo de botón sea Botón no Enviar, eso causó un conflicto de estado donde me encontré recientemente.

dyuan
fuente
1
Hay un conflicto porque enviar un formulario tiene un comportamiento predeterminado que debe evitar si está manejando el evento y haciendo una llamada ajax usted mismo. Puede evitar el comportamiento predeterminado tomando el evento en su controlador y llamandoe.preventDefault()
Jordan
20

Si el servidor responde a un método OPTIONS y GET y POST (cualquiera de ellos que esté usando) con un encabezado como:

Access-Control-Allow-Origin: *

Podría funcionar bien. Parece estar en FireFox 3.5 y rekonq 0.4.0. Aparentemente, con ese encabezado y la respuesta inicial a OPTIONS, el servidor le dice al navegador: "Adelante, deje que esta solicitud entre dominios se realice".

Alex Robinson
fuente
3
¡Esta es la respuesta correcta! Consulte en.wikipedia.org/wiki/Cross-origin_resource_sharing para obtener más información. Si agrega este encabezado, no es "podría funcionar", pero "funcionará". NB Lo que debe agregar es un encabezado / respuesta / HTTP, por lo que solo puede hacer esto en un servidor que usted controla. Nunca será posible obtener directamente w3schools.com/XML/cd_catalog.xml usando XMLHttpRequest(es decir, según la pregunta original), porque ese recurso no incluye (al menos, a partir del 24 de abril de 2015) ningún encabezado CORS.
MikeBeaton
13

Considere también el tiempo de espera de la solicitud :

El navegador moderno devuelve readyState = 4 y s tatus = 0 si pasa demasiado tiempo antes de la respuesta del servidor.

Andrea Savojardo
fuente
3
@AndreaSavojardo: ¿Tiene alguna referencia (como una publicación en MDN) sobre si este comportamiento cumple con los estándares?
Alexander Abakumov
@AndreaSavojardo Tengo readyState = 4 y status = 0 y el servidor no se está ejecutando pero la alerta de error se me muestra rápidamente .... ¿cuánto tiempo pasa para "solicitar tiempo de espera"?
7

Agregue setRequestHeader("Access-Control-Allow-Origin","*")a la respuesta de su servidor.

Iván
fuente
3

Me había enfrentado a un problema similar. Todo estaba bien, el "readystate" era 4, pero el "estado" era 0. Era porque estaba usando un servidor portátil Apache PHP y mi archivo en el que usé el objeto "XMLHttpRequest" era un archivo html. Cambié la extensión del archivo a php y el problema se resolvió.

Reyan
fuente
3

Abra la consola de JavaScript . Verá un mensaje de error allí. En mi caso fue CORS.

Jarekczek
fuente
2

Para responder a la pregunta de por qué http://127.0.0.1/cd_catalog.xmlfunciona y http://localhost/cd_catalog.xmlno funciona: Firefox está tratando 127.0.0.1 y localhost como dos dominios diferentes.

Tomi Aarnio
fuente
2

Para ver cuál es el problema, cuando obtenga el error críptico 0 vaya a ... | Más herramientas | Herramientas de desarrollo (Ctrl + Shift + I) en Chrome (en la página que da el error)

Lea el texto rojo en el registro para obtener el verdadero mensaje de error. Si hay demasiado allí, haga clic con el botón derecho y Limpie la consola, luego haga su última solicitud nuevamente.

Mi primer problema fue que estaba pasando encabezados de autorización a mi propio servicio web entre dominios para el navegador por primera vez.

Yo ya tenía:

Access-Control-Allow-Origin: *

Pero no:

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

en el encabezado de respuesta de mi servicio web.

Después de agregar eso, mi error cero desapareció de mi propio servidor web, así como al ejecutar el archivo index.html localmente sin un servidor web, pero seguía dando errores en el lápiz de código.

Volver a ... | Más herramientas | Developer Tools mientras aparece el error en codepen, y se explica claramente: codepen usa https, por lo que no puedo hacer llamadas a http, ya que la seguridad es menor.

Por lo tanto, necesito alojar mi servicio web en https.

Saber cómo obtener el verdadero mensaje de error: ¡no tiene precio!

maya
fuente
Usé este enfoque (f12 en Chrome) y descubrí que estaba tratando de pasar de https a http, que fallaba silenciosamente sin proporcionar nada útil. MENSAJE DE ERROR: VM1152: 1 Contenido mixto: la página 'https://mysiteoriginsite' se cargó a través de HTTPS, pero solicitó un punto final XMLHttpRequest no seguro 'http://MyDestinationSite/MyService.svc'. Esta solicitud ha sido bloqueada; el contenido debe publicarse a través de HTTPS.
GrayDwarf
1

Aquí hay otro caso en el que status === 0, específico de la carga:

Si adjunta un 'load'controlador de eventos a XHR.upload, como lo sugiere MDN (desplácese hacia abajo hasta la parte de carga de 'Monitoreo del progreso'), el objeto XHR tendrá status=0y todas las demás propiedades serán cadenas vacías. Si adjunta el 'load'controlador directamente al objeto XHR, como lo haría al descargar contenido, debería estar bien (dado que no se está ejecutando desde localhost).

Sin embargo, si desea obtener buenos datos en sus 'progress'controladores de eventos, debe adjuntar un controlador XHR.upload, no directamente al objeto XHR en sí.

Solo he probado esto hasta ahora en Chrome OSX, por lo que no estoy seguro de qué parte del problema aquí es la documentación de MDN y cuánto es la implementación de Chrome ...

ericsoco
fuente
1

Alex Robinson ya (y primero) da la respuesta correcta a este problema. Pero para elaborarlo un poco más ...

Debe agregar el encabezado de respuesta HTTP:

Access-Control-Allow-Origin: *

Si hace esto, el resultado no es solo "podría funcionar", sino "funcionará".

NB Lo que necesita agregar es un encabezado de respuesta HTTP , por lo que solo puede hacer esto en un servidor que usted controla. Nunca será posible obtener directamente http://w3schools.com/XML/cd_catalog.xml de su URL original usando un XMLHttpRequest(según la pregunta de OP), porque ese recurso no lo hace (al menos, no a partir del 24 de abril de 2015) incluir cualquier encabezado CORS.

http://en.wikipedia.org/wiki/Cross-origin_resource_sharing ofrece más información.

MikeBeaton
fuente
0

Mi problema similar a este se resolvió verificando mi código html. Tenía un onclickcontrolador en el botón de envío de mi formulario a un método. desea: onclick="sendFalconRequestWithHeaders()". Este método a su vez llama a ajax como el tuyo y hace lo que quiero. Pero no como esperaba, mi navegador no devolvía nada.

Aprendido del arduo trabajo de alguien , he devuelto falso en este controlador y lo resolví. Permítanme mencionar que antes de llegar a este post, he pasado un fin de semana de 3 días y un día la mitad de la escritura de código oficina de ejecución CORS filters, jetty config, otras jersey and embedded jettycosas relacionadas - sólo para solucionar este problema, que gira en torno a toda mi comprensión. cross domain ajax requestsY esas cosas estándares. Era ridículo cómo los simples errores en javascript te vuelven tonto.

Para ser verdad, lo he intentado signed.applets.codebase_principal_support = truey escrito isLocalHost() **if**. Puede ser que este método deba ser implementado por nosotros, Firefox dice que no existe. Ahora tengo que limpiar mi código para enviar el parche git limpiamente. Gracias a ese alguien.

Siva Tumma
fuente
0

Una solicitud del navegador "127.0.0.1/somefile.html" llega sin cambios al servidor web local, mientras que "localhost / somefile.html" puede llegar como "0: 0: 0: 0: 0: 0: 0: 1 / somefile.html "si se admite IPv6. Por lo que este último puede procesarse como si se pasara de un dominio a otro.

Massimo Roscio
fuente
0

Alex Robinson y bmju proporcionaron información valiosa para comprender los problemas de origen cruzado. Quería agregar que es posible que deba realizar una llamada OPTIONS explícita en el código de su cliente antes de realizar el GET / POST deseado (por ejemplo, contra un punto final de servicio CORS OAuth). Es posible que su navegador / biblioteca no maneje automáticamente la solicitud de OPCIONES. Gruber, esta es una de las posibles respuestas a tu pregunta.

Tim McConnell
fuente
0

Tuve el mismo problema (readyState era 4 y estado 0) , luego seguí un enfoque diferente explicado en este tutorial: https://spring.io/guides/gs/consuming-rest-jquery/

No usó XMLHttpRequest en absoluto, sino que usó el método 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>

y para el archivo public / hello.js (o puede insertarlo directamente en el mismo código 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
fuente
2
Te das cuenta de que jQuery $.ajax()usa XMLHttpRequesten el interior, ¿no?
Manngo
-1

Acabo de tener este problema porque lo usé 0.0.0.0como mi servidor, lo cambié localhosty funciona.

Vad
fuente
-4

Editar: lea los comentarios de Malvolio a continuación, ya que el conocimiento de esta respuesta está desactualizado.

No puede realizar XMLHttpRequests entre dominios.

La llamada a 127.0.0.1funciona porque su página de prueba se encuentra en 127.0.0.1, y la prueba local también funciona ya que, bueno ... es una prueba local.

Las otras dos pruebas fallan porque JavaScript no puede comunicarse con un servidor distante a través de XMLHttpRequest.

En su lugar, podría considerar:

  • XMLHttp: solicite su propio servidor para obtener su contenido XML remoto por usted (script php, por ejemplo)
  • Intentar utilizar un servicio como GoogleAppEngine si desea mantenerlo en JavaScript completo.

Espero que ayude

Gabriel Sprenger
fuente
40
Esto está simplemente mal. Usted puede hacer XMLHttpRequests entre dominios.
Malvolio
1
"No puedes" como en "No deberías hacerlo porque nunca es una buena idea"
Gabriel Sprenger
24
- bastante justo, pero no sé si un comentario es el mejor foro para eso. Las solicitudes XMLHttpRequests entre dominios ciertamente tienen algunos desafíos de seguridad, pero ofrecen todas las herramientas necesarias para hacer frente a esos desafíos. Aparte de eso, permiten que los sitios web ofrezcan servicios a otros sitios web fácilmente, utilicen CDN para propagar datos y respondan más rápidamente a las solicitudes de los usuarios. Si tiene alguna pregunta específica, puede enviarme un mensaje, o mejor, publicar una pregunta aquí en SO y llamar mi atención sobre ella.
Malvolio
2
@GabrielSprenger: Los dominios cruzados XMLHttpRequestno solo son una buena idea, es tan común hoy en día que NO hacerlos en una aplicación web moderna (más allá de algún tipo de HelloWorlds) es algo ridículo. Cualquier servicio REST externo que consume su aplicación requiere un dominio cruzado XMLHttpRequest. Y es por eso que se agregaron todas esas cosas de CORS.
Alexander Abakumov