Skip to content

Instantly share code, notes, and snippets.

@monsur
Created November 19, 2010 17:37
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save monsur/706839 to your computer and use it in GitHub Desktop.
Save monsur/706839 to your computer and use it in GitHub Desktop.
Parses the response from XmlHttpRequest.getAllResponseHeaders() into a key/value pair.
/**
* XmlHttpRequest's getAllResponseHeaders() method returns a string of response
* headers according to the format described here:
* http://www.w3.org/TR/XMLHttpRequest/#the-getallresponseheaders-method
* This method parses that string into a user-friendly key/value pair object.
*/
function parseResponseHeaders(headerStr) {
var headers = {};
if (!headerStr) {
return headers;
}
var headerPairs = headerStr.split('\u000d\u000a');
for (var i = 0; i < headerPairs.length; i++) {
var headerPair = headerPairs[i];
// Can't use split() here because it does the wrong thing
// if the header value has the string ": " in it.
var index = headerPair.indexOf('\u003a\u0020');
if (index > 0) {
var key = headerPair.substring(0, index);
var val = headerPair.substring(index + 2);
headers[key] = val;
}
}
return headers;
}
@doom-bunny
Copy link

So... out of curiosity - why use
a) escaped unicode instead of ': ' (i can see why you might use it for newlines)
b) why not use headerPair.split(...)? Something like:

var tokens = headerPair.split('\u003a\u0020');
if (tokens.length === 2) {
    headers[tokens[0]] = tokens[1];
}

might be less verbose neh? Though your method IS much more readable.

@monsur
Copy link
Author

monsur commented Nov 20, 2010

a) Not a particular reason for favoring the actual characters over Unicode. It was just how the spec was written so I thought I'd mimic that.

b) The value of the header could have a ": " in it, in which case using split() would return an incorrect value. You could join the value back together, but that is extra work. Also, .split('\u003a\u0020', 2) doesn't do what I would expect; it only returns the first two elements of the split(), not the entire value. For example, "a.b.c.d".split(".", 2) only returns ["a", "b"], not ["a", "b.c.d"]

@igrooves
Copy link

XMLHttpRequest.prototype.responseHeaderObject = function () {

     var headerStr = this.getAllResponseHeaders();
     var headers = {};
     if (!headerStr) {
          return headers;
     }

    ....

@rbg246
Copy link

rbg246 commented Jan 20, 2015

Thanks you very much. Did the trick.

@pencilcheck
Copy link

In coffeescript

window.parseResponseHeaders = (headerStr) ->
  headers = {}
  if !headerStr
    return headers
  headerPairs = headerStr.split('\u000d\u000a')
  for i in [0...headerPairs.length] by 1
    headerPair = headerPairs[i]
    # Can't use split() here because it does the wrong thing
    # if the header value has the string ": " in it.
    index = headerPair.indexOf('\u003a\u0020')
    if index > 0
      key = headerPair.substring(0, index)
      val = headerPair.substring(index + 2)
      headers[key] = val
  return headers

@letmaik
Copy link

letmaik commented Nov 13, 2015

What if header keys appear multiple times? The Link header is a good candidate.

@devaniyer
Copy link

Hi Monsur. It appears gist:706839 is now being used by Aurelia http-client - aurelia/http-client@01afa7a#diff-1ea1ae08eaece225ce69433b5147bdb1;
Aurelia http-client is offered under the MIT License.
Do you have a specific license in mind that you wish to apply to gist:706839?
Thanks!

@james-voth
Copy link

Hello Monsur. Following up on devaniyer's comment above, it would be greatly appreciated if you could apply a license to this gist so that others can determine how/if the code can be used.

@automagisch
Copy link

No license is always proper to use right? I don't really think Monsur would mind if you would use this :p

@RickyRomero
Copy link

RickyRomero commented Apr 2, 2017

Here's my solution:

function getHeadersAsObject(xhr)
{
  let headers = {}

  xhr.getAllResponseHeaders()
    .split('\u000d\u000a')
    .forEach((line) => {
      if (line.length > 0)
      {
        let delimiter = '\u003a\u0020',
          header = line.split(delimiter)

        headers[header.shift().toLowerCase()] = header.join(delimiter)
      }
    })

  return headers
}

This work is dedicated to the public domain.

@FarisHijazi
Copy link

function parseResponseHeaders(headerStr) {
    return Object.fromEntries(
        (headerStr || '').split('\u000d\u000a') // '\n'
            .map(line => line.split('\u003a\u0020')) // ": "
            .filter(pair => pair[0] !== undefined && pair[1] !== undefined)
    );
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment