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

fix($http): honor application/json response header and parse json primit... #9402

Closed
wants to merge 1 commit 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
10 changes: 7 additions & 3 deletions src/ng/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ function $HttpProvider() {
var JSON_START = /^\s*(\[|\{[^\{])/,
JSON_END = /[\}\]]\s*$/,
PROTECTION_PREFIX = /^\)\]\}',?\n/,
CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': 'application/json;charset=utf-8'};
APPLICATION_JSON = 'application/json',
CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'};

/**
* @ngdoc property
Expand All @@ -114,12 +115,15 @@ function $HttpProvider() {
**/
var defaults = this.defaults = {
// transform incoming response data
transformResponse: [function(data) {
transformResponse: [function defaultHttpResponseTransform(data, headers) {
if (isString(data)) {
// strip json vulnerability protection prefix
data = data.replace(PROTECTION_PREFIX, '');
if (JSON_START.test(data) && JSON_END.test(data))
var contentType = headers('Content-Type');
if ((contentType && contentType.indexOf(APPLICATION_JSON) === 0) ||
(JSON_START.test(data) && JSON_END.test(data))) {
data = fromJson(data);
}
}
return data;
}],
Expand Down
55 changes: 55 additions & 0 deletions test/ng/httpSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1020,6 +1020,61 @@ describe('$http', function() {
});


it('should deserialize json numbers when response header contains application/json',
function() {
$httpBackend.expect('GET', '/url').respond('123', {'Content-Type': 'application/json'});
$http({method: 'GET', url: '/url'}).success(callback);
$httpBackend.flush();

expect(callback).toHaveBeenCalledOnce();
expect(callback.mostRecentCall.args[0]).toEqual(123);
});


it('should deserialize json strings when response header contains application/json',
function() {
$httpBackend.expect('GET', '/url').respond('"asdf"', {'Content-Type': 'application/json'});
$http({method: 'GET', url: '/url'}).success(callback);
$httpBackend.flush();

expect(callback).toHaveBeenCalledOnce();
expect(callback.mostRecentCall.args[0]).toEqual('asdf');
});


it('should deserialize json nulls when response header contains application/json',
function() {
$httpBackend.expect('GET', '/url').respond('null', {'Content-Type': 'application/json'});
$http({method: 'GET', url: '/url'}).success(callback);
$httpBackend.flush();

expect(callback).toHaveBeenCalledOnce();
expect(callback.mostRecentCall.args[0]).toEqual(null);
});


it('should deserialize json true when response header contains application/json',
function() {
$httpBackend.expect('GET', '/url').respond('true', {'Content-Type': 'application/json'});
$http({method: 'GET', url: '/url'}).success(callback);
$httpBackend.flush();

expect(callback).toHaveBeenCalledOnce();
expect(callback.mostRecentCall.args[0]).toEqual(true);
});


it('should deserialize json false when response header contains application/json',
function() {
$httpBackend.expect('GET', '/url').respond('false', {'Content-Type': 'application/json'});
$http({method: 'GET', url: '/url'}).success(callback);
$httpBackend.flush();

expect(callback).toHaveBeenCalledOnce();
expect(callback.mostRecentCall.args[0]).toEqual(false);
});


it('should deserialize json with security prefix', function() {
$httpBackend.expect('GET', '/url').respond(')]}\',\n[1, "abc", {"foo":"bar"}]');
$http({method: 'GET', url: '/url'}).success(callback);
Expand Down