diff --git a/doc/api/http.md b/doc/api/http.md index 9b9175a003f56c..886bbe26ecc95c 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -3848,8 +3848,13 @@ changes: * `port` {number} Port of remote server. **Default:** `defaultPort` if set, else `80`. * `protocol` {string} Protocol to use. **Default:** `'http:'`. + * `setDefaultHeaders` {boolean}: Specifies whether or not to automatically add + default headers such as `Connection`, `Content-Length`, `Transfer-Encoding`, + and `Host`. If set to `false` then all necessary headers must be added + manually. Defaults to `true`. * `setHost` {boolean}: Specifies whether or not to automatically add the - `Host` header. Defaults to `true`. + `Host` header. If provided, this overrides `setDefaultHeaders`. Defaults to + `true`. * `signal` {AbortSignal}: An AbortSignal that may be used to abort an ongoing request. * `socketPath` {string} Unix domain socket. Cannot be used if one of `host` diff --git a/lib/_http_client.js b/lib/_http_client.js index 91ba264339fa4f..00b59f357fa45d 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -199,7 +199,13 @@ function ClientRequest(input, options, cb) { const host = optsWithoutSignal.host = validateHost(options.hostname, 'hostname') || validateHost(options.host, 'host') || 'localhost'; - const setHost = (options.setHost === undefined || Boolean(options.setHost)); + const setHost = options.setHost !== undefined ? + Boolean(options.setHost) : + options.setDefaultHeaders !== false; + + this._removedConnection = options.setDefaultHeaders === false; + this._removedContLen = options.setDefaultHeaders === false; + this._removedTE = options.setDefaultHeaders === false; this.socketPath = options.socketPath; diff --git a/test/parallel/test-http-dont-set-default-headers-with-set-header.js b/test/parallel/test-http-dont-set-default-headers-with-set-header.js new file mode 100644 index 00000000000000..bafdae5571e33c --- /dev/null +++ b/test/parallel/test-http-dont-set-default-headers-with-set-header.js @@ -0,0 +1,33 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const http = require('http'); + +const server = http.createServer(common.mustCall(function(req, res) { + assert.deepStrictEqual(req.rawHeaders, [ + 'test', 'value', + 'HOST', `127.0.0.1:${server.address().port}`, + 'foo', 'bar', + 'foo', 'baz', + 'connection', 'close', + ]); + + res.end('ok'); + server.close(); +})); +server.listen(0, common.localhostIPv4, function() { + const req = http.request({ + method: 'POST', + host: common.localhostIPv4, + port: this.address().port, + setDefaultHeaders: false, + }); + + req.setHeader('test', 'value'); + req.setHeader('HOST', `${common.localhostIPv4}:${server.address().port}`); + req.setHeader('foo', ['bar', 'baz']); + req.setHeader('connection', 'close'); + + req.end(); +}); diff --git a/test/parallel/test-http-dont-set-default-headers-with-setHost.js b/test/parallel/test-http-dont-set-default-headers-with-setHost.js new file mode 100644 index 00000000000000..e2a4e39c24b837 --- /dev/null +++ b/test/parallel/test-http-dont-set-default-headers-with-setHost.js @@ -0,0 +1,23 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const http = require('http'); + +const server = http.createServer(common.mustCall(function(req, res) { + assert.deepStrictEqual(req.rawHeaders, [ + 'Host', `${common.localhostIPv4}:${server.address().port}`, + ]); + + res.end('ok'); + server.close(); +})); +server.listen(0, common.localhostIPv4, function() { + http.request({ + method: 'POST', + host: common.localhostIPv4, + port: this.address().port, + setDefaultHeaders: false, + setHost: true + }).end(); +}); diff --git a/test/parallel/test-http-dont-set-default-headers.js b/test/parallel/test-http-dont-set-default-headers.js new file mode 100644 index 00000000000000..3f73c11e5112ee --- /dev/null +++ b/test/parallel/test-http-dont-set-default-headers.js @@ -0,0 +1,31 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const http = require('http'); + +const server = http.createServer(common.mustCall(function(req, res) { + assert.deepStrictEqual(req.rawHeaders, [ + 'host', `${common.localhostIPv4}:${server.address().port}`, + 'foo', 'bar', + 'test', 'value', + 'foo', 'baz', + ]); + + res.end('ok'); + server.close(); +})); +server.listen(0, common.localhostIPv4, function() { + http.request({ + method: 'POST', + host: common.localhostIPv4, + port: this.address().port, + setDefaultHeaders: false, + headers: [ + 'host', `${common.localhostIPv4}:${server.address().port}`, + 'foo', 'bar', + 'test', 'value', + 'foo', 'baz', + ] + }).end(); +});