Skip to content

Commit

Permalink
fix: allow to keep origin header key case (#344)
Browse files Browse the repository at this point in the history
  • Loading branch information
atian25 committed Jun 8, 2020
1 parent 31c03b8 commit 15c4170
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 3 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ httpclient.request('http://nodejs.org', function (err, body) {
- ***dataType*** String - Type of response data. Could be `text` or `json`. If it's `text`, the `callback`ed `data` would be a String. If it's `json`, the `data` of callback would be a parsed JSON Object and will auto set `Accept: application/json` header. Default `callback`ed `data` would be a `Buffer`.
- **fixJSONCtlChars** Boolean - Fix the control characters (U+0000 through U+001F) before JSON parse response. Default is `false`.
- ***headers*** Object - Request headers.
- ***keepHeaderCase*** Boolean - by default will convert header keys to lowercase
- ***timeout*** Number | Array - Request timeout in milliseconds for connecting phase and response receiving phase. Defaults to `exports.TIMEOUT`, both are 5s. You can use `timeout: 5000` to tell urllib use same timeout on two phase or set them seperately such as `timeout: [3000, 5000]`, which will set connecting timeout to 3s and response 5s.
- ***auth*** String - `username:password` used in HTTP Basic Authorization.
- ***digestAuth*** String - `username:password` used in HTTP [Digest Authorization](http://en.wikipedia.org/wiki/Digest_access_authentication).
Expand Down
30 changes: 28 additions & 2 deletions lib/urllib.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ var SOCKET_RESPONSE_COUNT = '_URLLIB_SOCKET_RESPONSE_COUNT';
* before JSON parse response. Default is `false`.
* `fixJSONCtlChars` can be a function, will pass data to the first argument. e.g.: `data = fixJSONCtlChars(data)`
* - {Object} [headers]: optional, request headers
* - {Boolean} [keepHeaderCase]: optional, by default will convert header keys to lowercase
* - {Number|Array} [timeout]: request timeout(in milliseconds), default is `exports.TIMEOUTS containing connect timeout and response timeout`
* - {Agent} [agent]: optional, http agent. Set `false` if you does not use agent.
* - {Agent} [httpsAgent]: optional, https agent. Set `false` if you does not use agent.
Expand Down Expand Up @@ -300,12 +301,18 @@ function requestWithCallback(url, args, callback) {
// https://github.com/nodejs/node/blob/archived-io.js-v0.12/lib/net.js#L952
lookup: lookup,
};

var originHeaderKeys = {};
if (args.headers) {
// only allow enumerable and ownProperty value of args.headers
var names = utility.getOwnEnumerables(args.headers, true);
for (var i = 0; i < names.length; i++) {
var name = names[i];
options.headers[name.toLowerCase()] = args.headers[name];
var key = name.toLowerCase();
if (key !== name) {
originHeaderKeys[key] = name;
}
options.headers[key] = args.headers[name];
}
}

Expand Down Expand Up @@ -450,6 +457,7 @@ function requestWithCallback(url, args, callback) {
// you can use this hook to change every thing.
args.beforeRequest(options);
}

var connectTimer = null;
var responseTimer = null;
var __err = null;
Expand Down Expand Up @@ -980,7 +988,25 @@ function requestWithCallback(url, args, callback) {

// request headers checker will throw error
try {
req = httplib.request(options, onResponse);
var finalOptions = options;

// restore origin header key
if (args.keepHeaderCase) {
var originKeys = Object.keys(originHeaderKeys);
if (originKeys.length) {
var finalHeaders = {};
var names = utility.getOwnEnumerables(options.headers, true);
for (var i = 0; i < names.length; i++) {
var name = names[i];
finalHeaders[originHeaderKeys[name] || name] = options.headers[name];
}

finalOptions = Object.assign({}, options);
finalOptions.headers = finalHeaders;
}
}

req = httplib.request(finalOptions, onResponse);
if (args.trace) {
req._callSite = {};
Error.captureStackTrace(req._callSite, requestWithCallback);
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"pedding": "^1.1.0",
"power-assert": "^1.4.2",
"semver": "5",
"spy": "^1.0.0",
"tar": "^4.4.8",
"through2": "^2.0.3",
"typescript": "^3.2.2"
Expand Down
58 changes: 57 additions & 1 deletion test/urllib.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ var os = require('os');
var through = require('through2');
var Stream = require('stream');
var muk = require('muk'); // muk support more node versions than mm
var spy = require('spy');
var dns = require('dns');
var semver = require('semver');
var server = require('./fixtures/server');
Expand Down Expand Up @@ -610,7 +611,7 @@ describe('test/urllib.test.js', function () {
});
});

it('should post data with custom Content-Type "test-foo-encode"',
it('should post data with custom Content-Type "test-foo-encode"',
function (done) {
var params = {
type: 'POST',
Expand Down Expand Up @@ -1826,6 +1827,61 @@ describe('test/urllib.test.js', function () {
});
});

describe('headers', function () {
it('should send lower case by default', function (done) {
var stub = spy(http, 'request');
urllib.request(host + '/headers', {
headers: {
'Case-Key': 'case1',
'CASE-KEY': 'case2',
'lower-key': 'lower',
},
dataType: 'json'
}, function(err, data, res) {
assert(!err);
assert(res.statusCode === 200);
assert(data['case-key'] === 'case2');
assert(data['lower-key'] === 'lower');
assert(!data['Case-key']);
assert(!data['CASE-KEY']);

var headers = stub.calls[0].arguments[0].headers;
assert(headers['case-key'] === 'case2');
assert(!headers['Case-Key']);
assert(!headers['CASE-KEY']);
stub.restore();
done();
});
});

it('should send origin case', function (done) {
var stub = spy(http, 'request');
urllib.request(host + '/headers', {
headers: {
'Case-Key': 'case1',
'CASE-KEY': 'case2',
'lower-key': 'lower',
},
keepHeaderCase: true,
dataType: 'json'
}, function(err, data, res) {
assert(!err);
assert(res.statusCode === 200);
assert(data['case-key'] === 'case2');
assert(data['lower-key'] === 'lower');
assert(!data['Case-key']);
assert(!data['CASE-KEY']);

var headers = stub.calls[0].arguments[0].headers;
assert(headers['CASE-KEY'] === 'case2');
assert(!headers['Case-Key']);
assert(!headers['case-key']);
stub.restore();
done();
});
});
});

// only test checkAddress in node 8+
if (parseInt(process.version.slice(1)) >= 8) {
describe('args.checkAddress', function() {
Expand Down

0 comments on commit 15c4170

Please sign in to comment.