Skip to content

Commit

Permalink
feat($http): adds xhrFields to $http config object
Browse files Browse the repository at this point in the history
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
  • Loading branch information
sjurba committed Jun 19, 2014
1 parent 307e72e commit 83cb793
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 8 deletions.
9 changes: 7 additions & 2 deletions src/ng/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,10 @@ function $HttpProvider() {
* for more information.
* - **responseType** - `{string}` - see
* [requestType](https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType).
* - **xhrFields** - `{object}` - Object that will be passed directly to
* [XMLHttpRequest()](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#XMLHttpRequest%28%29),
* that can be used to set [non-standard properties](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#Non-standard_properties).
* This object can also be set on the `$http.defaults` object to apply it globally.
*
* @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 @@ -594,7 +598,8 @@ function $HttpProvider() {
var config = {
method: 'get',
transformRequest: defaults.transformRequest,
transformResponse: defaults.transformResponse
transformResponse: defaults.transformResponse,
xhrFields: defaults.xhrFields,
};
var headers = mergeHeaders(requestConfig);

Expand Down Expand Up @@ -889,7 +894,7 @@ function $HttpProvider() {
}

$httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,
config.withCredentials, config.responseType);
config.withCredentials, config.responseType, config.xhrFields);
}

return promise;
Expand Down
12 changes: 8 additions & 4 deletions src/ng/httpBackend.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
'use strict';

function createXhr(method) {
function createXhr(method, xhrFields) {
//if IE and the method is not RFC2616 compliant, or if XMLHttpRequest
//is not available, try getting an ActiveXObject. Otherwise, use XMLHttpRequest
//if it is available
if (msie <= 8 && (!method.match(/^(get|post|head|put|delete|options)$/i) ||
!window.XMLHttpRequest)) {
return new window.ActiveXObject("Microsoft.XMLHTTP");
} else if (window.XMLHttpRequest) {
return new window.XMLHttpRequest();
if(isObject(xhrFields)){
return new window.XMLHttpRequest(xhrFields);
} else {
return new window.XMLHttpRequest();
}
}

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

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

var xhr = createXhr(method);
var xhr = createXhr(method, xhrFields);

xhr.open(method, url, true);
forEach(headers, function(value, key) {
Expand Down
28 changes: 26 additions & 2 deletions test/ng/httpBackendSpec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* global createHttpBackend: false, createMockXhr: false, MockXhr: false */
/* global createHttpBackend: false, createMockXhr: false, MockXhr: false, createXhr: false */
'use strict';

describe('$httpBackend', function() {
Expand Down Expand Up @@ -293,6 +293,30 @@ describe('$httpBackend', function() {
expect(MockXhr.$$lastInstance.withCredentials).toBe(true);
});

it('should pass xhrFields to createXhr', function() {
var createXhr = jasmine.createSpy('createXhr').andCallFake(createMockXhr);
$backend = createHttpBackend($browser, createXhr);
var xhrFields = {someField: 1};
$backend('GET', '/some.url', null, callback, {}, null, false, null, xhrFields);
expect(createXhr).toHaveBeenCalledWith('GET', xhrFields);
});

it('should pass xhrFields to XMLHttpRequest contructor', function(){
if (window.XMLHttpRequest) {
var xhrFields = {someField: 1};
var XMLHttpRequest = spyOn(window, 'XMLHttpRequest');
createXhr('GET', xhrFields);
expect(XMLHttpRequest).toHaveBeenCalledWith(xhrFields);
}
});

it('should not pass xhrFields to XMLHttpRequest contructor if undefined', function(){
if (window.XMLHttpRequest) {
var XMLHttpRequest = spyOn(window, 'XMLHttpRequest');
createXhr('GET', undefined);
expect(XMLHttpRequest).toHaveBeenCalledWith();
}
});

describe('responseType', function() {

Expand Down Expand Up @@ -521,5 +545,5 @@ describe('$httpBackend', function() {
expect(callback.mostRecentCall.args[0]).toBe(503);
});
});
});

});
48 changes: 48 additions & 0 deletions test/ng/httpSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1470,4 +1470,52 @@ describe('$http', function() {

$httpBackend.verifyNoOutstandingExpectation = noop;
});

it('shoud pass xhrFields params', function(){
var $httpBackend = jasmine.createSpy('$httpBackend');

$httpBackend.andCallFake(function(m, u, d, c, h, t, w, r, xhrFields) {
expect(xhrFields.someField).toBe(1);
});

module(function($provide) {
$provide.value('$httpBackend', $httpBackend);
});

inject(function($http, $rootScope) {
$http({
method: 'GET',
url: 'some.html',
xhrFields : { someField: 1 }
});
$rootScope.$digest();
expect($httpBackend).toHaveBeenCalledOnce();
});

$httpBackend.verifyNoOutstandingExpectation = noop;
});

it('should use xhrFields from default', function() {
var $httpBackend = jasmine.createSpy('$httpBackend');

$httpBackend.andCallFake(function(m, u, d, c, h, t, w, r, xhrFields) {
expect(xhrFields.someField).toBe(1);
});

module(function($provide) {
$provide.value('$httpBackend', $httpBackend);
});

inject(function($http, $rootScope) {
$http.defaults.xhrFields = {someField: 1};
$http({
method: 'GET',
url: 'some.html'
});
$rootScope.$digest();
expect($httpBackend).toHaveBeenCalledOnce();
});

$httpBackend.verifyNoOutstandingExpectation = noop;
});
});

0 comments on commit 83cb793

Please sign in to comment.