From b052350cc7b0535f6a07fc0a3e6d8fe1edb7b569 Mon Sep 17 00:00:00 2001 From: OZ Date: Wed, 18 Mar 2015 05:29:57 +0300 Subject: [PATCH] feat($http): CORS requests support for IE9 IE9 use it's own way to do CORS requests, so for this case (only) we should use XDomainRequest. More about it: http://www.html5rocks.com/en/tutorials/cors/ --- src/ng/httpBackend.js | 71 ++++++++++++++++++++++++++++++++----------- 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/src/ng/httpBackend.js b/src/ng/httpBackend.js index 5ba78b749932..1d59481cd2a8 100644 --- a/src/ng/httpBackend.js +++ b/src/ng/httpBackend.js @@ -4,6 +4,10 @@ function createXhr() { return new window.XMLHttpRequest(); } +function createXdr() { + return new window.XDomainRequest(); +} + /** * @ngdoc service * @name $httpBackend @@ -22,11 +26,11 @@ function createXhr() { */ function $HttpBackendProvider() { this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) { - return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0]); + return createHttpBackend($browser, createXhr, $browser.defer, $window.angular.callbacks, $document[0], createXdr); }]; } -function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument) { +function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDocument, createXdr) { // TODO(vojta): fix the signature return function(method, url, post, callback, headers, timeout, withCredentials, responseType) { $browser.$$incOutstandingRequestCount(); @@ -46,16 +50,56 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc }); } else { - var xhr = createXhr(); + var xhr; + var isXdr = false; + // only if we are in IE9 + if (createXdr && window.XDomainRequest) { + // and it's CORS + var hostname = window.location.hostname + (window.location.port ? ':' + window.location.port : ''); + if (!(!/^https?:\/\/([^\?\/]+)/.test(url) || RegExp.$1 === hostname)) { + isXdr = true; + } + } + if (!isXdr) { + xhr = createXhr(); + } else { + xhr = createXdr(); + // these methods MUST be defined (and before xhr.open), otherwise requests will fail in IE9 + xhr.onprogress = function() {}; + xhr.ontimeout = function() {}; + if (method !== 'GET') { + method = 'POST'; + } + xhr.getAllResponseHeaders = function() { + return ''; + }; + } + + var requestError = function() { + // The response is always empty + // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error + completeRequest(callback, -1, null, null, ''); + }; + + xhr.onerror = requestError; + if (!isXdr) { + xhr.onabort = requestError; + } xhr.open(method, url, true); - forEach(headers, function(value, key) { - if (isDefined(value)) { - xhr.setRequestHeader(key, value); - } - }); + if (!isXdr) { + forEach(headers, function(value, key) { + if (isDefined(value)) { + xhr.setRequestHeader(key, value); + } + }); + } xhr.onload = function requestLoaded() { + if (isXdr) { + xhr.status = 200; + xhr.statusText = 'OK'; + } var statusText = xhr.statusText || ''; // responseText is the old-school way of retrieving response (supported by IE8 & 9) @@ -79,16 +123,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc statusText); }; - var requestError = function() { - // The response is always empty - // See https://xhr.spec.whatwg.org/#request-error-steps and https://fetch.spec.whatwg.org/#concept-network-error - completeRequest(callback, -1, null, null, ''); - }; - - xhr.onerror = requestError; - xhr.onabort = requestError; - - if (withCredentials) { + if (withCredentials && !isXdr) { xhr.withCredentials = true; }