3

I have an angular app communicating with an Api where I prefix JSON responses only consisting of an array with )]}', as the angular's official documentation recommends to do.

The problem is, my browser seems to try to decode the response before angular does.

I've gone step by step in the debugger, and right after the xhr.onload callback is fired, the response is already null.

The code I'm talking about is this one :

// From angular.js(1.5.9):12122
xhr.onload = function requestLoaded() {
        var statusText = xhr.statusText || '';

        // responseText is the old-school way of retrieving response (supported by IE9)
        // response/responseType properties were introduced in XHR Level2 spec (supported by IE10)
        var response = ('response' in xhr) ? xhr.response : xhr.responseText;

        // normalize IE9 bug (http://bugs.jquery.com/ticket/1450)
        var status = xhr.status === 1223 ? 204 : xhr.status;

        // fix status code when it is 0 (0 status is undocumented).
        // Occurs when accessing file resources or on Android 4.1 stock browser
        // while retrieving files from application cache.
        if (status === 0) {
          status = response ? 200 : urlResolve(url).protocol === 'file' ? 404 : 0;
        }

        completeRequest(callback,
            status,
            response,
            xhr.getAllResponseHeaders(),
            statusText);
      };
}

xhr.response is null before angular does anything (I think).

Angular try to strip the prefix with this code :

function defaultHttpResponseTransform(data, headers) {
  if (isString(data)) {
    // Strip json vulnerability protection prefix and trim whitespace
    var tempData = data.replace(JSON_PROTECTION_PREFIX, '').trim();

    if (tempData) {
      var contentType = headers('Content-Type');
      if ((contentType && (contentType.indexOf(APPLICATION_JSON) === 0)) || isJsonLike(tempData)) {
        data = fromJson(tempData);
      }
    }
  }

  return data;
}

But the data is never a string at this point, the browser has already tried to decode it (and failed).

The output of the Api looks like the following :

)]}',
[{"name": "A"},{"name": "B"}]

If I remove the prefix, it works normally. I've tried with : - Opera 45.0 - Firefox 46 - Chrome 58

They all behave similarly, so I may be missing something.

The response headers contain the following:

HTTP/1.1 200 OK
Server: nginx/1.11.5
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Cache-Control: no-cache, private
[...]
Content-Length: 1793

Any idea ?

Thanks you very much.

Stnaire
  • 1,100
  • 1
  • 18
  • 30
  • Why is your xhr.response null ? is your api returning a null response? – karthick May 22 '17 at 16:43
  • Check out this answer: https://stackoverflow.com/a/25334223/1915893 – Aluan Haddad May 22 '17 at 16:44
  • Yes It's working.. I've failed to find this question when I was searching.. Anyway, can you please post an answer so I can accept it ? It will increase the chances for other people with the same problem to find the answer. Thanks for your help btw. – Stnaire May 22 '17 at 16:49
  • Sure thing. Glad it worked. Just wish we could give credit to the original author. – Aluan Haddad May 22 '17 at 17:00

1 Answers1

1

As noted by Jeff Sheets in this answer, your request configuration object may contain responseType: 'json'. This can cause the object to be dropped by the browser's underlying XMLHttpRequest implementation, which specifies this property before it is passed back to the application.

Removing the responseType property, or setting it to text should resolve the issue.

responseType is documented on MDN where it is stated that

Setting the value of responseType to "document" is ignored if done in a  Worker environment. When setting responseType to a particular value, the author should make sure that the server is actually sending a response compatible to that format. If the server returns data that is not compatible to the responseType that was set, the value of response will be null. Also, setting responseType for synchronous requests will throw an InvalidAccessError exception.

(emphasis mine)

Aluan Haddad
  • 29,886
  • 8
  • 72
  • 84