Detectando um redirecionamento em uma solicitação ajax?

94

Quero usar o jQuery para OBTER um URL e verificar explicitamente se ele respondeu com um redirecionamento 302, mas não segue o redirecionamento.

O jQuery $.ajaxparece sempre seguir redirecionamentos. Como posso evitar isso e ver o redirecionamento sem segui-lo?

Existem várias questões com títulos como "jquery ajax redirect", mas todas parecem envolver a realização de algum outro objetivo, em vez de apenas verificar diretamente o status fornecido por um servidor.

kdt
fonte

Respostas:

87

A solicitação AJAX nunca tem a oportunidade de NÃO seguir o redirecionamento (ou seja, deve seguir o redirecionamento). Mais informações podem ser encontradas nesta resposta https://stackoverflow.com/a/2573589/965648

Nick Garvey
fonte
41

Bem vindo ao futuro!

Agora temos uma propriedade "responseURL" do objeto xhr. YAY!

Veja como obter o url de resposta em XMLHttpRequest?

No entanto, jQuery (pelo menos 1.7.1) não dá acesso ao objeto XMLHttpRequest diretamente. Você pode usar algo assim:

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);
  }
});

Não é uma solução limpa e suponho que a equipe jQuery fará algo para responseURL em versões futuras.

DICA : basta comparar o URL original com responseUrl. Se for igual, nenhum redirecionamento foi fornecido. Se for "indefinido", o responseUrl provavelmente não é compatível. No entanto, como disse Nick Garvey, a solicitação AJAX nunca tem a oportunidade de NÃO seguir o redirecionamento, mas você pode resolver uma série de tarefas usando a propriedade responseUrl .

Riki_tiki_tavi
fonte
1
Para adicionar mais alguns recursos neste atributo - página MDN em XHR.responseURL - o suporte geral parece estar esperando no MSIE, que apenas o adicionou no Edge / 14.
Eli Collins
Obrigado ! Muito útil
Gautier
Descobri que este código realmente faz $ .ajax ({url: 'someurl', xhrFields: {withCredentials: true}}) lançar um erro no Internet Explorer porque a função _orgAjax depende da variável 'this' resolvendo para $ .ajaxSettings objeto. Do contrário, o jQuery cria um objeto ActiveX IXMLHTTPRequest em vez de um objeto XMLHttpRequest, que não oferece suporte à propriedade withCredentials. Corrigi isso chamando xhr = _orgAjax.call ($. AjaxSettings); em vez de xhr = _orgAjax (); Espero que isso ajude alguém.
StephenKC
11

Embora as outras pessoas que responderam a esta pergunta estejam (infelizmente) corretas ao afirmar que essas informações são ocultadas de nós pelo navegador, pensei em postar uma solução alternativa que descobri:

Eu configurei meu aplicativo de servidor para definir um cabeçalho de resposta personalizado ( X-Response-Url) contendo o url que foi solicitado. Sempre que meu código ajax recebe uma resposta, ele verifica se xhr.getResponseHeader("x-response-url")está definido e, nesse caso, o compara com a url por meio da qual ele solicitou originalmente $.ajax(). Se as strings forem diferentes, eu sei que houve um redirecionamento e, além disso, a qual url realmente chegamos.

Isso tem a desvantagem de exigir alguma ajuda do servidor e também pode falhar se o url for bloqueado (devido a problemas de cotação / codificação, etc.) durante a viagem de ida e volta ... mas para 99% dos casos, isso parece o trabalho feito.


No lado do servidor, meu caso específico foi um aplicativo python usando a estrutura da web Pyramid, e usei o seguinte snippet:

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
fonte
É verdade que não há como saber se há um redirecionamento sem pegá-lo; mas talvez comparar o URL do cabeçalho esperado com o redirecionado pode ser uma solução alternativa para mim neste momento. Obrigado pela ideia
Sergio A.
4

Agora você pode usar fetch API / ele retornaredirected: *boolean*

fvrab
fonte