Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

config.useXDomain to use XDomainRequest/CORS in IE #1047

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/ng/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ function $HttpProvider() {
* - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the
* XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5
* requests with credentials} for more information.
* - **useXDomain** 0 `{boolean}` - use XDomainRequest in IE requests
*
* @returns {HttpPromise} Returns a {@link ng.$q promise} object with the
* standard `then` method and two http specific methods: `success` and `error`. The `then`
Expand Down Expand Up @@ -697,7 +698,7 @@ function $HttpProvider() {
// if we won't have the response in cache, send the request to the backend
if (!cachedResp) {
$httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,
config.withCredentials);
config.withCredentials, config.useXDomain || $http.defaults.useXDomain);
}

return promise;
Expand Down
109 changes: 73 additions & 36 deletions src/ng/httpBackend.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ var XHR = window.XMLHttpRequest || function() {
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e2) {}
try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e3) {}
throw new Error("This browser does not support XMLHttpRequest.");
};
}, XDR = !window.msPerformance && window.XDomainRequest || null;


/**
Expand All @@ -25,14 +25,14 @@ var XHR = window.XMLHttpRequest || function() {
*/
function $HttpBackendProvider() {
this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {
return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks,
return createHttpBackend($browser, XHR, XDR, $browser.defer, $window.angular.callbacks,
$document[0], $window.location.protocol.replace(':', ''));
}];
}

function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {
function createHttpBackend($browser, XHR, XDR, $browserDefer, callbacks, rawDocument, locationProtocol) {
// TODO(vojta): fix the signature
return function(method, url, post, callback, headers, timeout, withCredentials) {
return function(method, url, post, callback, headers, timeout, withCredentials, useXDomain) {
$browser.$$incOutstandingRequestCount();
url = url || $browser.url();

Expand All @@ -44,43 +44,80 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument,

jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),
function() {
if (callbacks[callbackId].data) {
completeRequest(callback, 200, callbacks[callbackId].data);
} else {
completeRequest(callback, -2);
}
delete callbacks[callbackId];
});
} else {
var xhr = new XHR();
xhr.open(method, url, true);
forEach(headers, function(value, key) {
if (value) xhr.setRequestHeader(key, value);
});

if (callbacks[callbackId].data) {
completeRequest(callback, 200, callbacks[callbackId].data);
} else {
completeRequest(callback, -2);
}
delete callbacks[callbackId];
});
} else {
var status;
if (useXDomain && XDR) {
var xdr = new XDR();
xdr.open(method.toLowerCase(), url);

// Required to XDomainRequest works
xdr.timeout = timeout;
xdr.onprogress = function() {};

xdr.ontimeout = function() {
completeRequest(callback, 408, 'Timeout', 'Content-Type: text/plain');
xdr.abort();
};

xdr.onload = function() {
completeRequest(callback, 200, xdr.responseText, 'Content-Type: ' + xdr.contentType);
};

// In IE6 and 7, this might be called synchronously when xhr.send below is called and the
// response is in the cache. the promise api will ensure that to the app code the api is
// always async
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
completeRequest(
callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());
xdr.onerror = function() {
completeRequest(callback, 500, 'Error', 'Content-Type: text/plain');
xdr.abort();
};


$browserDefer(function () {
xdr.send();
}, 0); //fix IE bug that raises '$apply already in progress' on cached requests

if (timeout > 0) {
$browserDefer(function() {
status = -1;
xdr.abort();
}, timeout);
}
};

if (withCredentials) {
xhr.withCredentials = true;
}
} else {
var xhr = new XHR();
xhr.open(method, url, true);

forEach(headers, function(value, key) {
if (value) xhr.setRequestHeader(key, value);
});

// In IE6 and 7, this might be called synchronously when xhr.send below is called and the
// response is in the cache. the promise api will ensure that to the app code the api is
// always async
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
completeRequest(
callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());
}
};

if (withCredentials) {
xhr.withCredentials = true;
}

xhr.send(post || '');
xhr.send(post || '');

if (timeout > 0) {
$browserDefer(function() {
status = -1;
xhr.abort();
}, timeout);
}

if (timeout > 0) {
$browserDefer(function() {
status = -1;
xhr.abort();
}, timeout);
}
}

Expand All @@ -93,7 +130,7 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument,
status = (protocol == 'file') ? (response ? 200 : 404) : status;

// normalize IE bug (http://bugs.jquery.com/ticket/1450)
status = status == 1223 ? 204 : status;
status = status == 1223 ? 204 : status;

callback(status, response, headersString);
$browser.$$completeOutstandingRequest(noop);
Expand Down
3 changes: 2 additions & 1 deletion src/ngResource/resource.js
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,8 @@ angular.module('ngResource', ['ng']).
$http({
method: action.method,
url: route.url(extend({}, extractParams(data), action.params || {}, params)),
data: data
data: data,
useXDomain: $http.defaults.useXDomain || false
}).then(function(response) {
var data = response.data;

Expand Down
15 changes: 7 additions & 8 deletions test/ng/httpBackendSpec.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
describe('$httpBackend', function() {

var $backend, $browser, callbacks,
xhr, fakeDocument, callback;
xhr, xdr, fakeDocument, callback;

// TODO(vojta): should be replaced by $defer mock
function fakeTimeout(fn, delay) {
Expand Down Expand Up @@ -38,7 +38,7 @@ describe('$httpBackend', function() {
})
}
};
$backend = createHttpBackend($browser, MockXhr, fakeTimeout, callbacks, fakeDocument);
$backend = createHttpBackend($browser, MockXhr, MockXhr, fakeTimeout, callbacks, fakeDocument);
callback = jasmine.createSpy('done');
}));

Expand Down Expand Up @@ -234,7 +234,7 @@ describe('$httpBackend', function() {


it('should convert 0 to 200 if content', function() {
$backend = createHttpBackend($browser, MockXhr, null, null, null, 'http');
$backend = createHttpBackend($browser, MockXhr, null, null, null, null, 'http');

$backend('GET', 'file:///whatever/index.html', null, callback);
respond(0, 'SOME CONTENT');
Expand All @@ -245,7 +245,7 @@ describe('$httpBackend', function() {


it('should convert 0 to 200 if content - relative url', function() {
$backend = createHttpBackend($browser, MockXhr, null, null, null, 'file');
$backend = createHttpBackend($browser, MockXhr, null, null, null, null, 'file');

$backend('GET', '/whatever/index.html', null, callback);
respond(0, 'SOME CONTENT');
Expand All @@ -256,7 +256,7 @@ describe('$httpBackend', function() {


it('should convert 0 to 404 if no content', function() {
$backend = createHttpBackend($browser, MockXhr, null, null, null, 'http');
$backend = createHttpBackend($browser, MockXhr, null, null, null, null, 'http');

$backend('GET', 'file:///whatever/index.html', null, callback);
respond(0, '');
Expand All @@ -267,7 +267,7 @@ describe('$httpBackend', function() {


it('should convert 0 to 200 if content - relative url', function() {
$backend = createHttpBackend($browser, MockXhr, null, null, null, 'file');
$backend = createHttpBackend($browser, MockXhr, null, null, null, null, 'file');

$backend('GET', '/whatever/index.html', null, callback);
respond(0, '');
Expand All @@ -276,5 +276,4 @@ describe('$httpBackend', function() {
expect(callback.mostRecentCall.args[0]).toBe(404);
});
});
});

});