Skip to content

Commit

Permalink
Maintain request header casing.
Browse files Browse the repository at this point in the history
While headers are meant to be case sensitive, many servers do not
respect this.  Node maintains the casing of the request headers in order
to work with this and http-browserify should do likewise in order to be
consistent with the node implementation.

This patch maintains the casing with which the header was last set, e.g.
setting header "fOo", then header "Foo" will still only send one header,
but will use the final casing "Foo". This is compatible with the node
implementation in
https://github.com/nodejs/node/blob/85ab4a5f1281c4e1dd06450ac7bd3250326267fa/lib/_http_outgoing.js
  • Loading branch information
Liam O'Boyle committed Mar 23, 2016
1 parent 17b2990 commit 6493496
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 2 deletions.
8 changes: 6 additions & 2 deletions lib/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ var Request = module.exports = function (xhr, params) {
};

self._headers = {};
self._headerNames = {};

if (params.headers) {
var keys = objectKeys(params.headers);
Expand Down Expand Up @@ -78,6 +79,7 @@ inherits(Request, Stream);

Request.prototype.setHeader = function (key, value) {
this._headers[key.toLowerCase()] = value
this._headerNames[key.toLowerCase()] = key;
};

Request.prototype.getHeader = function (key) {
Expand All @@ -86,6 +88,7 @@ Request.prototype.getHeader = function (key) {

Request.prototype.removeHeader = function (key) {
delete this._headers[key.toLowerCase()]
delete this._headerNames[key.toLowerCase()]
};

Request.prototype.write = function (s) {
Expand All @@ -105,12 +108,13 @@ Request.prototype.end = function (s) {
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var value = this._headers[key];
var name = this._headerNames[key];
if (isArray(value)) {
for (var j = 0; j < value.length; j++) {
this.xhr.setRequestHeader(key, value[j]);
this.xhr.setRequestHeader(name, value[j]);
}
}
else this.xhr.setRequestHeader(key, value)
else this.xhr.setRequestHeader(name, value)
}

if (this.body.length === 0) {
Expand Down
30 changes: 30 additions & 0 deletions test/request_url.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ var noop = function() {};
global.XMLHttpRequest = function() {
this.open = noop;
this.send = noop;
this.setRequestHeader = noop;
};

global.FormData = function () {};
Expand Down Expand Up @@ -112,3 +113,32 @@ test('Test POST XHR2 types', function(t) {
};
request.end(new global.FormData());
});

test('Test header access is case insensitive, but is still sent in given case', function (t) {
t.plan(3);

var Request = require('../lib/request');
var headers = {};
var xhr = function () {
this.open = noop;
this.send = noop;
this.setRequestHeader = function (key, value) {
headers[key] = value;
};
};

var params = {
path: '/api/foo',
host: 'localhost',
scheme: 'http',
headers: { Foo: 'bar' }
};
var request = new Request(new xhr, params);
request.end();

t.ok(request.getHeader('foo') === params.headers.Foo, 'headers should be accessible regardless of case');
t.ok(headers['Foo'] === params.headers.Foo, 'the original header casing should be sent in the request');

request.removeHeader('foo');
t.ok(request.getHeader('Foo') === undefined, 'headers should be removable regardless of case');
});

0 comments on commit 6493496

Please sign in to comment.