Detecting a redirect in ajax request?

111,796

Solution 1

The AJAX request never has the opportunity to NOT follow the redirect (i.e., it must follow the redirect). More information can be found in this answer https://stackoverflow.com/a/2573589/965648

Solution 2

Welcome to the future!

Right now we have a "responseURL" property from xhr object. YAY!

See How to get response url in XMLHttpRequest?

However, jQuery (at least 1.7.1) doesn't give an access to XMLHttpRequest object directly. You can use something like this:

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

It's not a clean solution and i suppose jQuery team will make something for responseURL in the future releases.

TIP: just compare original URL with responseUrl. If it's equal then no redirect was given. If it's "undefined" then responseUrl is probably not supported. However as Nick Garvey said, AJAX request never has the opportunity to NOT follow the redirect but you may resolve a number of tasks by using responseUrl property.

Solution 3

While the other folks who answered this question are (sadly) correct that this information is hidden from us by the browser, I thought I'd post a workaround I came up with:

I configured my server app to set a custom response header (X-Response-Url) containing the url that was requested. Whenever my ajax code receives a response, it checks if xhr.getResponseHeader("x-response-url") is defined, in which case it compares it to the url that it originally requested via $.ajax(). If the strings differ, I know there was a redirect, and additionally, what url we actually arrived at.

This does have the drawback of requiring some server-side help, and also may break down if the url gets munged (due to quoting/encoding issues etc) during the round trip... but for 99% of cases, this seems to get the job done.


On the server side, my specific case was a python application using the Pyramid web framework, and I used the following 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

Solution 4

You can now use fetch API/ It returns redirected: *boolean*

Share:
111,796
kdt
Author by

kdt

Updated on July 08, 2022

Comments

  • kdt
    kdt almost 2 years

    I want to use jQuery to GET a URL and explicitly check if it responded with a 302 redirect, but not follow the redirect.

    jQuery's $.ajax appears to always follow redirects. How can I prevent this, and see the redirect without following it?

    There are various questions with titles like "jquery ajax redirect" but they all appear to involve accomplishing some other goal, rather than just directly checking the status that a server gives.

  • Eli Collins
    Eli Collins almost 6 years
    To add some more resources on this attribute -- MDN page on XHR.responseURL -- general support seems to be waiting on MSIE, which only added it in Edge/14.
  • Gautier
    Gautier almost 6 years
    Thanks ! Very usefull
  • StephenKC
    StephenKC over 4 years
    I found that this code actually makes $.ajax({url: 'someurl', xhrFields:{withCredentials:true}}) throw an error in Internet Explorer because the function _orgAjax depends upon the 'this' variable resolving to the $.ajaxSettings object. When it doesn't, jQuery creates an ActiveX IXMLHTTPRequest object instead of an XMLHttpRequest object, which doesn't support the withCredentials property. I fixed this by calling xhr = _orgAjax.call($.ajaxSettings); instead of xhr = _orgAjax(); I hope this helps someone.
  • Sergio A.
    Sergio A. over 4 years
    It is true indeed that there is no way to know if there is a redirect without taking it; but maybe comparing the expected header URL with the redirected one can be a workaround for me at this moment. Thanks for the idea