Wykrywanie przekierowania w żądaniu Ajax?

94

Chcę użyć jQuery, aby uzyskać adres URL i wyraźnie sprawdzić, czy odpowiedział przekierowaniem 302, ale nie podążać za przekierowaniem.

$.ajaxWydaje się, że jQuery zawsze podąża za przekierowaniami. Jak mogę temu zapobiec i zobaczyć przekierowanie bez podążania za nim?

Istnieje wiele pytań związanych z tytułami takimi jak „jquery ajax redirect”, ale wszystkie wydają się dotyczyć osiągnięcia jakiegoś innego celu, a nie tylko bezpośredniego sprawdzania statusu, jaki nadaje serwer.

kdt
źródło
W moim przypadku oczekuję odpowiedzi JSON po sukcesie i odpowiedzi HTML, jeśli było przekierowanie do strony logowania. Skończyło się na sprawdzeniu, czy xhr.getResponseHeader("content-type")zaczyna się od text/htmli zawiera słowo kluczowe, takie jak „login”, i w razie potrzeby pokazuję, że „sesja wygasła”. To oczywiście nie jest tak naprawdę odpowiedź, ale obejście.
Salman A

Odpowiedzi:

41

Witamy w przyszłości!

W tej chwili mamy właściwość „responseURL” z obiektu xhr. YAY!

Zobacz Jak uzyskać adres URL odpowiedzi w XMLHttpRequest?

Jednak jQuery (przynajmniej 1.7.1) nie daje bezpośredniego dostępu do obiektu XMLHttpRequest. Możesz użyć czegoś takiego:

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

To nie jest czyste rozwiązanie i przypuszczam, że zespół jQuery zrobi coś dla responseURL w przyszłych wydaniach.

WSKAZÓWKA : po prostu porównaj oryginalny adres URL z responseUrl. Jeśli jest równy, nie podano przekierowania. Jeśli jest „niezdefiniowany”, to responseUrl prawdopodobnie nie jest obsługiwany. Jednak, jak powiedział Nick Garvey, żądanie AJAX nigdy nie ma możliwości NIE podążania za przekierowaniem, ale możesz rozwiązać szereg zadań za pomocą właściwości responseUrl .

Riki_tiki_tavi
źródło
1
Aby dodać więcej zasobów do tego atrybutu - strona MDN na XHR.responseURL - wydaje się, że ogólne wsparcie czeka na MSIE, które dodało je tylko w Edge / 14.
Eli Collins,
Dzięki ! Bardzo przydatne
Gautier
Zauważyłem, że ten kod faktycznie powoduje, że $ .ajax ({url: 'someurl', xhrFields: {withCredentials: true}}) generuje błąd w Internet Explorerze, ponieważ funkcja _orgAjax zależy od zmiennej „this”, która jest tłumaczona na $ .ajaxSettings obiekt. Jeśli tak się nie stanie, jQuery tworzy obiekt ActiveX IXMLHTTPRequest zamiast obiektu XMLHttpRequest, który nie obsługuje właściwości withCredentials. Naprawiłem to, dzwoniąc xhr = _orgAjax.call ($. AjaxSettings); zamiast xhr = _orgAjax (); Mam nadzieję, że to komuś pomoże.
StephenKC
11

Podczas gdy inni ludzie, którzy odpowiedzieli na to pytanie, (niestety) mają rację, że te informacje są ukrywane przed nami przez przeglądarkę, pomyślałem, że opublikuję obejście, które wymyśliłem:

Skonfigurowałem aplikację serwera tak, aby ustawić niestandardowy nagłówek odpowiedzi ( X-Response-Url) zawierający żądany adres URL. Za każdym razem, gdy mój kod Ajax otrzyma odpowiedź, sprawdza, czy xhr.getResponseHeader("x-response-url")jest zdefiniowany, w takim przypadku porównuje go z adresem URL, którego pierwotnie zażądał $.ajax(). Jeśli ciągi się różnią, wiem, że nastąpiło przekierowanie, a dodatkowo, do jakiego adresu URL doszliśmy.

Ma to tę wadę, że wymaga pomocy po stronie serwera, a także może się zepsuć, jeśli adres URL zostanie zablokowany (z powodu problemów z cytowaniem / kodowaniem itp.) Podczas podróży w obie strony ... ale w 99% przypadków wydaje się, że praca wykonana.


Po stronie serwera moim konkretnym przypadkiem była aplikacja w Pythonie korzystająca z frameworka internetowego Pyramid i użyłem następującego fragmentu kodu:

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
źródło
Prawdą jest, że nie ma sposobu, aby dowiedzieć się, czy istnieje przekierowanie bez jego podjęcia; ale może porównanie oczekiwanego adresu URL nagłówka z przekierowanym może być obecnie dla mnie obejściem. Dzięki za pomysł
Sergio A.
4

Możesz teraz użyć API pobierania / zwracaredirected: *boolean*

fvrab
źródło