24

I'm using jQuery 1.6.2 to make a POST AJAX request to a page on the same domain. That page does a 302 redirect to another page.

Now, on my local machine this work fine but on our production server, the redirect is never followed and in the Chrome inspector the request is said to be 'canceled'.

If I visit the same page without involving javascript, everything works fine, and as I said the AJAX works on my local machine but not on the production server.

Does anyone know what might cause this?

There are some differences between the servers (OS X, Apache2, PHP5.3.6, HTTP on local machine, Ubuntu, Lighttpd, PHP5.3.3, HTTPS on production) but none that to me should make any difference.

Johan
  • 554
  • 1
  • 4
  • 10
  • 1
    I assume the 302 redirects to another resource on the same domain? – Adam Hopkinson Aug 05 '11 at 11:26
  • Indeed. Turns out there was a bug in kohana though that caused the redirect to be HTTP instead of HTTPS. That must have caused the browser to cancel the request. – Johan Aug 05 '11 at 12:27
  • 3
    Excellent. Add that as an answer below - in two days, you'll be able to accept your answer as the correct one so that people who have similar problems in the future can find it. – Adam Hopkinson Aug 05 '11 at 12:56

4 Answers4

13

Turns out a bug in the redirect code caused the redirect to go to http:// while the page that was requested was https://. That makes the browser refuse to follow the redirect.

Johan
  • 554
  • 1
  • 4
  • 10
5
function doAjaxCall() {
   $.ajaxSetup({complete: onRequestCompleted});
   $.get(yourUrl,yourData,yourCallback);
}

function onRequestCompleted(xhr,textStatus) {
   if (xhr.status == 302) {
      location.href = xhr.getResponseHeader("Location");
   }
}

following questions related to your answer. you can find the answer from below links.

Catching 302 FOUND in JavaScript

How to manage a redirect request after a jQuery Ajax call

Community
  • 1
  • 1
Chamika Sandamal
  • 23,565
  • 5
  • 63
  • 86
  • 6
    Browsers should not pass a 302 to JS, as the browser handles the redirect transparently, so jQuery will never know it was redirected. I'm not clear on whether this is all browsers, however Chrome clearly does it this way and other have reported Opera/FF similarly. – DanH Jan 28 '13 at 07:02
  • 'Browsers should not pass a 302 to JS' doesn't mean that you have to down vote the answer. try the above code your self and then put the correct answer if this is wrong rather down voting without knowing. and see the 3 upvotes as well – Chamika Sandamal Jan 28 '13 at 09:27
  • 8
    `xhr.status == 302` should never happen as the 302 will be handled by the browser, which will then only return a 200 or other error code to the JS, so I consider this counterproductive advice. I'll remove the -1 however since you do link to other questions. I shall provide a different answer. – DanH Jan 29 '13 at 02:55
  • 1
    It seems I cannot un vote unless you edit the answer, sorry for the trouble. – DanH Jan 29 '13 at 03:02
  • see the screenshot in the question. it says 302. as per your comment it may be browser doesn't handled. so in this case we have to capture that error code as well. and by the way now you should be able to remove the -1 – Chamika Sandamal Jan 29 '13 at 06:22
  • I don't think the code snippet is a good solution. Consider you are making bunch of ajax calls to the server web apis and suddenly, your login expires and the response is a 302 to the login page. However you will never know when your login could expire, so you have to add this handling to all ajax calls.Check this: http://stackoverflow.com/questions/34325823/how-to-gracefully-handle-login-expiration-for-an-ajax-call – smwikipedia Jan 06 '16 at 13:06
  • @DanH Why should someone consider it a bad thing for 302 to be transparently handled by browser. – smwikipedia Jan 06 '16 at 13:12
  • 2
    BTW, this code is exactly the same code as @Strelok posted here:http://stackoverflow.com/questions/373087/catching-302-found-in-javascript, which is poorly down-voted. And that answer is way earlier. – smwikipedia Jan 06 '16 at 13:29
  • @smwikipedia I didn't say it was *bad* that browsers handle it transparently, however as browsers *do* handle the 302 transparently, JS will never receive an XHR with status 302. – DanH Jan 06 '16 at 15:20
  • @DanH Maybe I don't know your specific scenario. But that's exactly what I want. – smwikipedia Jan 07 '16 at 00:30
3

I consider this to be a server-side issue, and not client-side. The browser is correct not to follow redirections to http when it makes ajax request by https, as that would be a security flaw.

I realized I was using relative paths, such as HttpResponseRedirect('/path/to/'). On some layer, that url was prepended with the http:// prefix and that was what the browser received: http://example.com/path/to/

You must ensure that the Location gets sent in the response header with a full path, including the https://.

augustomen
  • 8,977
  • 3
  • 43
  • 63
2

Based on this answer: https://stackoverflow.com/a/8752354/698289 I found the following code to be very useful:

$('body').ajaxComplete(function (e, xhr, settings) {
    if (xhr.status == 200) {
        var redirect = null;
        try {
            redirect = $.parseJSON(xhr.responseText).redirect;
            if (redirect) {
                window.location.href = redirect;
            }
        } catch (e) {
            return;
        }
    }
});

Then you just provide JSON such as the following:

{redirect: '/redirect/to/this/path'}

And the ajaxComplete will make sure to redirect the browser.

Be mindful that $.ajax('complete') triggers AFTER $.ajax('success') or $.ajax('error')

Community
  • 1
  • 1
DanH
  • 5,498
  • 4
  • 49
  • 72
  • I don't think this is a good solution. Does it mean I have to put it on every page? Please correct me if I understand it wrong. – smwikipedia Jan 06 '16 at 13:08
  • The code above is Javascript, and so will only run as long as it is loaded in the web browser on every page it is required. – DanH Jan 06 '16 at 15:23