mirror of
https://github.com/zhigang1992/angular.js.git
synced 2026-01-12 22:45:52 +08:00
fix($templateRequest): ignore JSON Content-Type header and content
Normally, if there is a Content-Type header with the string "application/json", or else the content looks sort of JSON-y, $http will attempt to deserialize the JSON into an object. $templateRequest is intended to request markup, and as such should never attempt to parse JSON, regardless of the headers or shape of the content. Closes #5756 Closes #9619
This commit is contained in:
@@ -100,6 +100,8 @@
|
||||
"NODE_TYPE_DOCUMENT": false,
|
||||
"NODE_TYPE_DOCUMENT_FRAGMENT": false,
|
||||
|
||||
"httpResponseTransform": false,
|
||||
|
||||
/* filters.js */
|
||||
"getFirstThursdayOfYear": false,
|
||||
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
'use strict';
|
||||
|
||||
var APPLICATION_JSON = 'application/json';
|
||||
var CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'};
|
||||
var JSON_START = /^\s*(\[|\{[^\{])/;
|
||||
var JSON_END = /[\}\]]\s*$/;
|
||||
var JSON_PROTECTION_PREFIX = /^\)\]\}',?\n/;
|
||||
|
||||
function defaultHttpResponseTransform(data, headers) {
|
||||
if (isString(data)) {
|
||||
// strip json vulnerability protection prefix
|
||||
data = data.replace(JSON_PROTECTION_PREFIX, '');
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse headers into key value object
|
||||
*
|
||||
@@ -86,12 +105,6 @@ function isSuccess(status) {
|
||||
* Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.
|
||||
* */
|
||||
function $HttpProvider() {
|
||||
var JSON_START = /^\s*(\[|\{[^\{])/,
|
||||
JSON_END = /[\}\]]\s*$/,
|
||||
PROTECTION_PREFIX = /^\)\]\}',?\n/,
|
||||
APPLICATION_JSON = 'application/json',
|
||||
CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': APPLICATION_JSON + ';charset=utf-8'};
|
||||
|
||||
/**
|
||||
* @ngdoc property
|
||||
* @name $httpProvider#defaults
|
||||
@@ -115,18 +128,7 @@ function $HttpProvider() {
|
||||
**/
|
||||
var defaults = this.defaults = {
|
||||
// transform incoming response data
|
||||
transformResponse: [function defaultHttpResponseTransform(data, headers) {
|
||||
if (isString(data)) {
|
||||
// strip json vulnerability protection prefix
|
||||
data = data.replace(PROTECTION_PREFIX, '');
|
||||
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;
|
||||
}],
|
||||
transformResponse: [defaultHttpResponseTransform],
|
||||
|
||||
// transform outgoing request data
|
||||
transformRequest: [function(d) {
|
||||
|
||||
@@ -25,7 +25,28 @@ function $TemplateRequestProvider() {
|
||||
var self = handleRequestFn;
|
||||
self.totalPendingRequests++;
|
||||
|
||||
return $http.get(tpl, { cache : $templateCache })
|
||||
var transformResponse = $http.defaults && $http.defaults.transformResponse;
|
||||
var idx;
|
||||
|
||||
if (isArray(transformResponse)) {
|
||||
var original = transformResponse;
|
||||
transformResponse = [];
|
||||
for (var i=0; i<original.length; ++i) {
|
||||
var transformer = original[i];
|
||||
if (transformer !== defaultHttpResponseTransform) {
|
||||
transformResponse.push(transformer);
|
||||
}
|
||||
}
|
||||
} else if (transformResponse === defaultHttpResponseTransform) {
|
||||
transformResponse = null;
|
||||
}
|
||||
|
||||
var httpOptions = {
|
||||
cache: $templateCache,
|
||||
transformResponse: transformResponse
|
||||
};
|
||||
|
||||
return $http.get(tpl, httpOptions)
|
||||
.then(function(response) {
|
||||
var html = response.data;
|
||||
if(!html || html.length === 0) {
|
||||
|
||||
@@ -86,4 +86,48 @@ describe('$templateRequest', function() {
|
||||
expect($templateRequest.totalPendingRequests).toBe(0);
|
||||
}));
|
||||
|
||||
it('should not try to parse a response as JSON',
|
||||
inject(function($templateRequest, $httpBackend) {
|
||||
var spy = jasmine.createSpy('success');
|
||||
$httpBackend.expectGET('a.html').respond('{{text}}', {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
$templateRequest('a.html').then(spy);
|
||||
$httpBackend.flush();
|
||||
expect(spy).toHaveBeenCalledOnceWith('{{text}}');
|
||||
}));
|
||||
|
||||
it('should use custom response transformers (array)', function() {
|
||||
module(function($httpProvider) {
|
||||
$httpProvider.defaults.transformResponse.push(function(data) {
|
||||
return data + '!!';
|
||||
});
|
||||
});
|
||||
inject(function($templateRequest, $httpBackend) {
|
||||
var spy = jasmine.createSpy('success');
|
||||
$httpBackend.expectGET('a.html').respond('{{text}}', {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
$templateRequest('a.html').then(spy);
|
||||
$httpBackend.flush();
|
||||
expect(spy).toHaveBeenCalledOnceWith('{{text}}!!');
|
||||
});
|
||||
});
|
||||
|
||||
it('should use custom response transformers (function)', function() {
|
||||
module(function($httpProvider) {
|
||||
$httpProvider.defaults.transformResponse = function(data) {
|
||||
return data + '!!';
|
||||
};
|
||||
});
|
||||
inject(function($templateRequest, $httpBackend) {
|
||||
var spy = jasmine.createSpy('success');
|
||||
$httpBackend.expectGET('a.html').respond('{{text}}', {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
$templateRequest('a.html').then(spy);
|
||||
$httpBackend.flush();
|
||||
expect(spy).toHaveBeenCalledOnceWith('{{text}}!!');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user