diff --git a/docs/content/error/$http/baddata.ngdoc b/docs/content/error/$http/baddata.ngdoc new file mode 100644 index 000000000000..9349b76639c5 --- /dev/null +++ b/docs/content/error/$http/baddata.ngdoc @@ -0,0 +1,14 @@ +@ngdoc error +@name $http:baddata +@fullName Bad JSON Data +@description + +The default @{link ng.$http#default-transformations `transformResponse`} will try to parse the +response as JSON if the `Content-Type` header is `application/json` or the response looks like a +valid JSON-stringified object or array. +This error occurs when that data is not a valid JSON object. + +The error message should provide additional context such as the actual response. + +To resolve this error, make sure you pass valid JSON data to `transformResponse` or use an +appropriate `Content-Type` header for non-JSON data. diff --git a/src/ng/http.js b/src/ng/http.js index a4b54f68fad5..fe67455e3ca9 100644 --- a/src/ng/http.js +++ b/src/ng/http.js @@ -138,7 +138,12 @@ function defaultHttpResponseTransform(data, headers) { if (tempData) { var contentType = headers('Content-Type'); if ((contentType && (contentType.indexOf(APPLICATION_JSON) === 0)) || isJsonLike(tempData)) { - data = fromJson(tempData); + try { + data = fromJson(tempData); + } catch (e) { + throw $httpMinErr('baddata', 'Data must be a valid JSON object. Received: "{0}". ' + + 'Parse error: "{1}"', data, e); + } } } } diff --git a/test/ng/httpSpec.js b/test/ng/httpSpec.js index 1318a742125a..f03582bdde23 100644 --- a/test/ng/httpSpec.js +++ b/test/ng/httpSpec.js @@ -1369,17 +1369,15 @@ describe('$http', function() { } ); - it('should forward json deserialization errors to the http error handler', - function() { + it('should return JSON data with error message if JSON is invalid', function() { var errCallback = jasmine.createSpy('error'); - - $httpBackend.expect('GET', '/url').respond('abcd', {'Content-Type': 'application/json'}); - $http({method: 'GET', url: '/url'}).then(callback).catch(errCallback); + $httpBackend.expect('GET', '/url').respond('{abcd}', {'Content-Type': 'application/json'}); + $http.get('/url').then(callback).catch(errCallback); $httpBackend.flush(); expect(callback).not.toHaveBeenCalled(); expect(errCallback).toHaveBeenCalledOnce(); - expect(errCallback.calls.mostRecent().args[0]).toEqual(jasmine.any(SyntaxError)); + expect(errCallback.calls.mostRecent().args[0]).toEqualMinErr('$http', 'baddata'); }); });