'How to make a JSON object out of getAllResponseHeaders method

I am currently writing a google chrome extension, and I need to find out information about websites' response headers. In order to do this, I used the getAllResponseHeaders method, but I need to put it in a JSON object. Unfortunately, I keep getting the error message SyntaxError: Unexpected token D in JSON at position 0 at main.

Here is the code I am using to do this so far:

xmlhttp.open("GET", url, false);
xmlhttp.onreadystatechange=function() {
    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
        allResponseHeaders = xmlhttp.getAllResponseHeaders();
    }
};
xmlhttp.send();

var responseHeaders = JSON.parse(allResponseHeaders);
obj.headers = responseHeaders;

When I put an alert immediately after the allResponseHeaders = xmlhttp.getAllResponseHeaders(); call, the alert shows that the call was a success; the response headers have all been retrieved. The first response header is the Date, which I think has to do with the Unexpected token D part of my error message, but I don't know why it won't parse properly. How do I fix this? Thanks in advance.

EDIT: I would like my JSON object to look something like this:

{
  "headers": {
    "Date": "June 20, 2016",
    "Content-Type": "charset=UTF/8",
    ...
  }
}


Solution 1:[1]

See https://msdn.microsoft.com/en-us/library/ms536428(v=vs.85).aspx. The return headers are a crlf delimited string where each line contains key values separated by a colon. You will probably have to adjust the code below to account for whitespace.

var arr = allResponseHeaders.split('\r\n');
var headers = arr.reduce(function (acc, current, i){
      var parts = current.split(': ');
      acc[parts[0]] = parts[1];
      return acc;
}, {});

Solution 2:[2]

I use the following function to extract all response headers as JS object using getAllResponseHeaders():

function getResponseHeaderMap(xhr) {
  const headers = {};
  xhr.getAllResponseHeaders()
      .trim()
      .split(/[\r\n]+/)
      .map(value => value.split(/: /))
      .forEach(keyValue => {
        headers[keyValue[0].trim()] = keyValue[1].trim();
      });
  return headers;
}

Solution 3:[3]

You should put JSON.parse logic inside the callback onreadystatechange, since Ajax is an asynchronous call and allResponseHeaders may not be initialized when you use it right after sending the http request.

Solution 4:[4]

Simplified version of the accepted answer and fixed issue reported by @Emrah Tuncel :

The first item of the return value is incorrect. { "": undefined }

// ES6:
const headers = request.getAllResponseHeaders().trim().split('\r\n').reduce((acc, current) => {
      const [x,v] = current.split(': ');
      return Object.assign(acc, { [x] : v });
}, {});

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 beaver
Solution 2 Sebastian Barth
Solution 3 Haibara Ai
Solution 4 lepe