diff --git a/src/.jshintrc b/src/.jshintrc index 9bf993719bf0..e833bcf065d2 100644 --- a/src/.jshintrc +++ b/src/.jshintrc @@ -100,6 +100,8 @@ "NODE_TYPE_DOCUMENT": false, "NODE_TYPE_DOCUMENT_FRAGMENT": false, + "httpResponseTransform": false, + /* filters.js */ "getFirstThursdayOfYear": false, diff --git a/src/ng/http.js b/src/ng/http.js index 0ae6d0ef1b81..a04d468bb3cc 100644 --- a/src/ng/http.js +++ b/src/ng/http.js @@ -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 httpResponseTransform(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: [httpResponseTransform], // transform outgoing request data transformRequest: [function(d) { diff --git a/src/ng/templateRequest.js b/src/ng/templateRequest.js index 7155718e89a4..475dae4b07f8 100644 --- a/src/ng/templateRequest.js +++ b/src/ng/templateRequest.js @@ -25,7 +25,23 @@ 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) && + (idx = transformResponse.indexOf(httpResponseTransform)) >= 0) { + transformResponse = copy(transformResponse, []); + transformResponse.splice(idx, 1); + } else if (transformResponse === httpResponseTransform) { + 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) { diff --git a/test/ng/templateRequestSpec.js b/test/ng/templateRequestSpec.js index efc6a182116c..dbb36a4161bc 100644 --- a/test/ng/templateRequestSpec.js +++ b/test/ng/templateRequestSpec.js @@ -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}}!!'); + }); + }); });