¿Detectando una redirección en una solicitud ajax?

94

Quiero usar jQuery para OBTENER una URL y verificar explícitamente si respondió con una redirección 302, pero no seguir la redirección.

jQuery $.ajaxparece seguir siempre las redirecciones. ¿Cómo puedo evitar esto y ver la redirección sin seguirla?

Hay varias preguntas con títulos como "redireccionamiento de jquery ajax", pero todas parecen implicar el logro de algún otro objetivo, en lugar de simplemente verificar directamente el estado que proporciona un servidor.

kdt
fuente

Respuestas:

41

¡Bienvenido al futuro!

Ahora mismo tenemos una propiedad "responseURL" del objeto xhr. ¡HURRA!

Consulte ¿Cómo obtener la URL de respuesta en XMLHttpRequest?

Sin embargo, jQuery (al menos 1.7.1) no da acceso al objeto XMLHttpRequest directamente. Puedes usar algo como esto:

var xhr;
var _orgAjax = jQuery.ajaxSettings.xhr;
jQuery.ajaxSettings.xhr = function () {
  xhr = _orgAjax();
  return xhr;
};

jQuery.ajax('http://test.com', {
  success: function(responseText) {
    console.log('responseURL:', xhr.responseURL, 'responseText:', responseText);
  }
});

No es una solución limpia y supongo que el equipo de jQuery hará algo para responseURL en futuras versiones.

SUGERENCIA : simplemente compare la URL original con responseUrl. Si es igual, no se proporcionó ninguna redirección. Si es "indefinido", entonces responseUrl probablemente no sea compatible. Sin embargo, como dijo Nick Garvey, la solicitud AJAX nunca tiene la oportunidad de NO seguir la redirección, pero puede resolver una serie de tareas utilizando la propiedad responseUrl .

Riki_tiki_tavi
fuente
1
Para agregar algunos recursos más en este atributo ( página MDN en XHR.responseURL) , el soporte general parece estar esperando en MSIE, que solo lo agregó en Edge / 14.
Eli Collins
Gracias ! Muy útil
Gautier
Descubrí que este código en realidad hace que $ .ajax ({url: 'someurl', xhrFields: {withCredentials: true}}) arroje un error en Internet Explorer porque la función _orgAjax depende de que la variable 'this' se resuelva en $ .ajaxSettings objeto. Cuando no lo hace, jQuery crea un objeto ActiveX IXMLHTTPRequest en lugar de un objeto XMLHttpRequest, que no admite la propiedad withCredentials. Arreglé esto llamando a xhr = _orgAjax.call ($. AjaxSettings); en lugar de xhr = _orgAjax (); Espero que esto ayude a alguien.
StephenKC
11

Si bien las otras personas que respondieron esta pregunta tienen (lamentablemente) razón en que el navegador nos oculta esta información, pensé en publicar una solución alternativa que se me ocurrió:

Configuré mi aplicación de servidor para establecer un encabezado de respuesta personalizado ( X-Response-Url) que contiene la URL solicitada. Siempre que mi código ajax recibe una respuesta, comprueba si xhr.getResponseHeader("x-response-url")está definido, en cuyo caso lo compara con la URL que solicitó originalmente a través de $.ajax(). Si las cadenas difieren, sé que hubo una redirección y, además, a qué URL llegamos realmente.

Esto tiene el inconveniente de requerir algo de ayuda del lado del servidor, y también puede fallar si la URL se manipula (debido a problemas de citación / codificación, etc.) durante el viaje de ida y vuelta ... pero para el 99% de los casos, esto parece funcionar el trabajo hecho.


En el lado del servidor, mi caso específico fue una aplicación de Python que usa el marco web Pyramid, y usé el siguiente fragmento:

import pyramid.events

@pyramid.events.subscriber(pyramid.events.NewResponse)
def set_response_header(event):
    request = event.request
    if request.is_xhr:
        event.response.headers['X-Response-URL'] = request.url
Eli Collins
fuente
De hecho, es cierto que no hay forma de saber si hay una redirección sin tomarla; pero tal vez comparar la URL del encabezado esperada con la redirigida puede ser una solución para mí en este momento. Gracias por la idea
Sergio A.
4

Ahora puede usar fetch API / It Returnsredirected: *boolean*

fvrab
fuente