Update: Code updated with the solution based on Eamonn Gahan's answer
I'm trying to fetch some files that are user generated and can't be trusted to be properly formatted. I thought this would be straightforward, but I'm stumped on what to do when the response is kind of like JSON, but isn't.
For example if a server responds with: a simple string {with brackets} everything works as expected. But, if the server responds with: { not_json: { malformed on purpose }, then I can't figure out how to get access to the response, either as a success or failure response.
What seems to happen is the Angular JSON parser throws a Syntax error without rejecting the $http promise.
Below is some code that highlights the issue.
var myApp = angular.module('myApp', []);
function MyCtrl($scope, $http){
// --- Added this block based on Eamonn Gahan's answer
function txfmParseText(data, hdrGetter){
var contentType = hdrGetter()['content-type'];
if ( contentType.match(/^text\/plain/) ){
data = JSON.stringify(data);
}
return data ;
}
$http.defaults.transformResponse.unshift(txfmParseText);
// --- end of updated block
$scope.sanityCheck="Alive";
// URL returns (as text/plain):
// { not_json: { malformed on purpose }
var urlOpts1 = {
method: 'GET',
url: 'https://s3.amazonaws.com/forforf-cdn/not_json_test'
};
// URL returns (as text/plain):
// a simple string {with brackets}
var urlOpts2 = {
method: 'GET',
url: 'https://s3.amazonaws.com/forforf-cdn/simple_string_with_brackets'
};
// First request fails [update: passes with transformResponse function]
$http(urlOpts1)
.then(function(resp){
//never gets here
console.log(resp);
$scope.notJson = resp.data;
})
.catch(function(err){
//nor is the promise rejected
console.log(err)
});
// Second request works as expected
$http(urlOpts2).then(function(resp){
//works as expected
console.log(resp);
$scope.stringWithBrackets = resp.data;
});
}
and the jsFiddle
updated jsFiddle with solution
Here's the HTTP of the failing Request and Response. The data is being served by S3, and the content type of the data is set to text/plain.
Request URL:https://s3.amazonaws.com/forforf-cdn/not_json_test
Request Method:GET
Status Code:304 Not Modified
Request Headers
GET /forforf-cdn/not_json_test HTTP/1.1
Host: s3.amazonaws.com
Connection: keep-alive
Cache-Control: max-age=0
Accept: application/json, text/plain, */*
Origin: http://fiddle.jshell.net
User-Agent: Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36
Referer: http://fiddle.jshell.net/_display/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
If-None-Match: "84cf04d01a85ed58af77293ea7b1884a"
If-Modified-Since: Sat, 15 Feb 2014 20:52:30 GMT
Response Headers
HTTP/1.1 304 Not Modified
x-amz-id-2: FvdtpH6WmRvEAFIt3clAsXC133iyGQ/Qezlzt/5P6UDFbZvDfUC7WeuPv+re0ywE
x-amz-request-id: FA51FED4F6A70DA2
Date: Sat, 15 Feb 2014 22:02:22 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET
Access-Control-Max-Age: 3000
Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
Last-Modified: Sat, 15 Feb 2014 20:52:30 GMT
ETag: "84cf04d01a85ed58af77293ea7b1884a"
Server: AmazonS3
Thinking it might be S3 wasn't setting the proper Content-Type, I also had S3 respond with:
Content-Type: text/plain; charset="utf-8", but it didn't help.
Anyone have any ideas?