Skip to content

Commit 698db30

Browse files
committed
feat($http): adds xhrFields to $http config object
The `xhrFields` object is passed to the XMLHttpRequest constructor making it possible to set non-standard properties on the XMLHttpRequest object. With this functionality it is possible to set the `mozSystem` and `mozAnon` properties, which is required to use angular in a packaged Firefox OS app. See https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#XMLHttpRequest() Closes angular#2318
1 parent 307e72e commit 698db30

File tree

4 files changed

+89
-8
lines changed

4 files changed

+89
-8
lines changed

src/ng/http.js

+7-2
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,10 @@ function $HttpProvider() {
485485
* for more information.
486486
* - **responseType** - `{string}` - see
487487
* [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType).
488+
* - **xhrFields** - `{object}` - Object that will be passed directly to
489+
* [XMLHttpRequest()](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#XMLHttpRequest%28%29),
490+
* that can be used to set [non-standard properties](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#Non-standard_properties).
491+
* This object can also be set on the `$http.defaults` object to apply it globally.
488492
*
489493
* @returns {HttpPromise} Returns a {@link ng.$q promise} object with the
490494
* standard `then` method and two http specific methods: `success` and `error`. The `then`
@@ -594,7 +598,8 @@ function $HttpProvider() {
594598
var config = {
595599
method: 'get',
596600
transformRequest: defaults.transformRequest,
597-
transformResponse: defaults.transformResponse
601+
transformResponse: defaults.transformResponse,
602+
xhrFields: defaults.xhrFields,
598603
};
599604
var headers = mergeHeaders(requestConfig);
600605

@@ -889,7 +894,7 @@ function $HttpProvider() {
889894
}
890895

891896
$httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,
892-
config.withCredentials, config.responseType);
897+
config.withCredentials, config.responseType, config.xhrFields);
893898
}
894899

895900
return promise;

src/ng/httpBackend.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
'use strict';
22

3-
function createXhr(method) {
3+
function createXhr(method, xhrFields) {
44
//if IE and the method is not RFC2616 compliant, or if XMLHttpRequest
55
//is not available, try getting an ActiveXObject. Otherwise, use XMLHttpRequest
66
//if it is available
77
if (msie <= 8 && (!method.match(/^(get|post|head|put|delete|options)$/i) ||
88
!window.XMLHttpRequest)) {
99
return new window.ActiveXObject("Microsoft.XMLHTTP");
1010
} else if (window.XMLHttpRequest) {
11-
return new window.XMLHttpRequest();
11+
if(isObject(xhrFields)){
12+
return new window.XMLHttpRequest(xhrFields);
13+
} else {
14+
return new window.XMLHttpRequest();
15+
}
1216
}
1317

1418
throw minErr('$httpBackend')('noxhr', "This browser does not support XMLHttpRequest.");
@@ -40,7 +44,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
4044
var ABORTED = -1;
4145

4246
// TODO(vojta): fix the signature
43-
return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {
47+
return function(method, url, post, callback, headers, timeout, withCredentials, responseType, xhrFields) {
4448
var status;
4549
$browser.$$incOutstandingRequestCount();
4650
url = url || $browser.url();
@@ -59,7 +63,7 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
5963
});
6064
} else {
6165

62-
var xhr = createXhr(method);
66+
var xhr = createXhr(method, xhrFields);
6367

6468
xhr.open(method, url, true);
6569
forEach(headers, function(value, key) {

test/ng/httpBackendSpec.js

+26-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* global createHttpBackend: false, createMockXhr: false, MockXhr: false */
1+
/* global createHttpBackend: false, createMockXhr: false, MockXhr: false, createXhr: false */
22
'use strict';
33

44
describe('$httpBackend', function() {
@@ -293,6 +293,30 @@ describe('$httpBackend', function() {
293293
expect(MockXhr.$$lastInstance.withCredentials).toBe(true);
294294
});
295295

296+
it('should pass xhrFields to createXhr', function() {
297+
var createXhr = jasmine.createSpy('createXhr').andCallFake(createMockXhr);
298+
$backend = createHttpBackend($browser, createXhr);
299+
var xhrFields = {someField: 1};
300+
$backend('GET', '/some.url', null, callback, {}, null, false, null, xhrFields);
301+
expect(createXhr).toHaveBeenCalledWith('GET', xhrFields);
302+
});
303+
304+
it('should pass xhrFields to XMLHttpRequest contructor', function(){
305+
if (window.XMLHttpRequest) {
306+
var xhrFields = {someField: 1};
307+
var XMLHttpRequest = spyOn(window, 'XMLHttpRequest');
308+
createXhr('GET', xhrFields);
309+
expect(XMLHttpRequest).toHaveBeenCalledWith(xhrFields);
310+
}
311+
});
312+
313+
it('should not pass xhrFields to XMLHttpRequest contructor if undefined', function(){
314+
if (window.XMLHttpRequest) {
315+
var XMLHttpRequest = spyOn(window, 'XMLHttpRequest');
316+
createXhr('GET', undefined);
317+
expect(XMLHttpRequest).toHaveBeenCalledWith();
318+
}
319+
});
296320

297321
describe('responseType', function() {
298322

@@ -521,5 +545,5 @@ describe('$httpBackend', function() {
521545
expect(callback.mostRecentCall.args[0]).toBe(503);
522546
});
523547
});
524-
});
525548

549+
});

test/ng/httpSpec.js

+48
Original file line numberDiff line numberDiff line change
@@ -1470,4 +1470,52 @@ describe('$http', function() {
14701470

14711471
$httpBackend.verifyNoOutstandingExpectation = noop;
14721472
});
1473+
1474+
it('shoud pass xhrFields params', function(){
1475+
var $httpBackend = jasmine.createSpy('$httpBackend');
1476+
1477+
$httpBackend.andCallFake(function(m, u, d, c, h, t, w, r, xhrFields) {
1478+
expect(xhrFields.someField).toBe(1);
1479+
});
1480+
1481+
module(function($provide) {
1482+
$provide.value('$httpBackend', $httpBackend);
1483+
});
1484+
1485+
inject(function($http, $rootScope) {
1486+
$http({
1487+
method: 'GET',
1488+
url: 'some.html',
1489+
xhrFields : { someField: 1 }
1490+
});
1491+
$rootScope.$digest();
1492+
expect($httpBackend).toHaveBeenCalledOnce();
1493+
});
1494+
1495+
$httpBackend.verifyNoOutstandingExpectation = noop;
1496+
});
1497+
1498+
it('should use xhrFields from default', function() {
1499+
var $httpBackend = jasmine.createSpy('$httpBackend');
1500+
1501+
$httpBackend.andCallFake(function(m, u, d, c, h, t, w, r, xhrFields) {
1502+
expect(xhrFields.someField).toBe(1);
1503+
});
1504+
1505+
module(function($provide) {
1506+
$provide.value('$httpBackend', $httpBackend);
1507+
});
1508+
1509+
inject(function($http, $rootScope) {
1510+
$http.defaults.xhrFields = {someField: 1};
1511+
$http({
1512+
method: 'GET',
1513+
url: 'some.html'
1514+
});
1515+
$rootScope.$digest();
1516+
expect($httpBackend).toHaveBeenCalledOnce();
1517+
});
1518+
1519+
$httpBackend.verifyNoOutstandingExpectation = noop;
1520+
});
14731521
});

0 commit comments

Comments
 (0)