Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ajax request with CORS redirect fails in IE11

I'm trying to make an ajax request to a resource on the same domain. Under certain circumstances the request gets redirected(303) to an external resource. The external resource supports CORS.

In browsers like Chrome, Firefox or Safari the request succeeds.
In IE11 the request fails with error:

SCRIPT 7002: XMLHttpRequest: Network Error 0x4c7, The operation was canceled by the user

The ajax request is made with jQuery:

$.ajax({
  url: "/data",
  type: "POST",
  dataType: "json",
  contentType: "application/json;charset=UTF-8",
  data: JSON.stringify({name: 'John Doe'})
}).done(function () {
  console.log('succeeded');
}).fail(function () {
  console.log('failed');
});

I've build a little example which demonstrates the problem. You could see the code here.

w/o redirect

w/o redirect

w/ redirect

w/ redirect

Is there a way to solve this problem? What am I missing?

like image 447
robson Avatar asked Oct 31 '22 06:10

robson


1 Answers

In the initial definition of the CORS-standard, redirects after a successful CORS-preflight request were not allowed.

IE11 implements this (now outdated) standard.

Since August 2016, this has changed, and all major browsers now support it (Here's the actual pull request).

I'm afraid to support <=IE11 you'll have to modify your server-side code as well to not issue a redirect (at least for <=IE11).

Part 1) Server-side (I'm using node.js express here):

function _isIE (request) {
  let userAgent = request.headers['user-agent']
  return userAgent.indexOf("MSIE ") > 0 || userAgent.indexOf("Trident/") > 0
}

router.post('data', function (request, response) {
  if (_isIE(request)) {
    // perform action
    res.set('Content-Type', 'text/plain')
    return res.status(200).send(`${redirectionTarget}`)
  } else {
    // perform action
    response.redirect(redirectionTarget)
  }
})

Part 2 Client-side

Note: This is pure Javascript, but you can easily adapt it to your jQuery/ajax implementation.

var isInternetExplorer = (function () {
  var ua = window.navigator.userAgent
  return ua.indexOf("MSIE ") > 0 || ua.indexOf("Trident/") > 0
})()

function requestResource (link, successFn, forcedRedirect) {
  var http
  if (window.XMLHttpRequest) {
    http = new XMLHttpRequest()
  } else if (window.XDomainRequest) {
    http = new XDomainRequest()
  } else {
    http = new ActiveXObject("Microsoft.XMLHTTP")
  }
  http.onreadystatechange = function () {
    var OK = 200
    if (http.readyState === XMLHttpRequest.DONE) {
      if (http.status === OK && successFn)  {
        if (isInternetExplorer && !forcedRedirect) {
          return requestResource(http.responseText, successFn, true)
        } else {
          successFn(http.responseText)
        }
      }
    }
  }
  http.onerror = http.ontimeout = function () {
    console.error('An error occured requesting '+link+' (code: '+http.status+'): '+http.responseText)
  }
  http.open('GET', link)
  http.send(null)
}
like image 105
maximilianvp Avatar answered Nov 11 '22 10:11

maximilianvp