Skip to content

Commit

Permalink
http: allow url and options to be passed to http*.request and http*.get
Browse files Browse the repository at this point in the history
Fixes: #20795
PR-URL: #21616
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Reviewed-By: Ron Korving <ron@ronkorving.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
  • Loading branch information
rubys authored and mcollina committed Jul 13, 2018
1 parent 19bc893 commit f9b739e
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 19 deletions.
19 changes: 16 additions & 3 deletions doc/api/http.md
Original file line number Diff line number Diff line change
Expand Up @@ -1796,15 +1796,20 @@ The `requestListener` is a function which is automatically
added to the [`'request'`][] event.

## http.get(options[, callback])
## http.get(url[, options][, callback])
<!-- YAML
added: v0.3.6
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/21616
description: allow both url and options to be passed to `http.get()`
- version: v7.5.0
pr-url: https://github.com/nodejs/node/pull/10638
description: The `options` parameter can be a WHATWG `URL` object.
-->

* `options` {Object | string | URL} Accepts the same `options` as
* `url` {string | URL}
* `options` {Object} Accepts the same `options` as
[`http.request()`][], with the `method` always set to `GET`.
Properties that are inherited from the prototype are ignored.
* `callback` {Function}
Expand Down Expand Up @@ -1868,15 +1873,20 @@ Global instance of `Agent` which is used as the default for all HTTP client
requests.

## http.request(options[, callback])
## http.request(url[, options][, callback])
<!-- YAML
added: v0.3.6
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/21616
description: allow both url and options to be passed to `http.request()`
- version: v7.5.0
pr-url: https://github.com/nodejs/node/pull/10638
description: The `options` parameter can be a WHATWG `URL` object.
-->

* `options` {Object | string | URL}
* `url` {string | URL}
* `options` {Object}
* `protocol` {string} Protocol to use. **Default:** `'http:'`.
* `host` {string} A domain name or IP address of the server to issue the
request to. **Default:** `'localhost'`.
Expand Down Expand Up @@ -1918,10 +1928,13 @@ changes:
Node.js maintains several connections per server to make HTTP requests.
This function allows one to transparently issue requests.

`options` can be an object, a string, or a [`URL`][] object. If `options` is a
`url` can be a string or a [`URL`][] object. If `url` is a
string, it is automatically parsed with [`new URL()`][]. If it is a [`URL`][]
object, it will be automatically converted to an ordinary `options` object.

If both `url` and `options` are specified, the objects are merged, with the
`options` properties taking precedence.

The optional `callback` parameter will be added as a one-time listener for
the [`'response'`][] event.

Expand Down
14 changes: 12 additions & 2 deletions doc/api/https.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,19 @@ https.createServer(options, (req, res) => {
```

## https.get(options[, callback])
## https.get(url[, options][, callback])
<!-- YAML
added: v0.3.6
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/21616
description: allow both url and options to be passed to `https.get()`
- version: v7.5.0
pr-url: https://github.com/nodejs/node/pull/10638
description: The `options` parameter can be a WHATWG `URL` object.
-->
- `options` {Object | string | URL} Accepts the same `options` as
- `url` {string | URL}
- `options` {Object} Accepts the same `options` as
[`https.request()`][], with the `method` always set to `GET`.
- `callback` {Function}

Expand Down Expand Up @@ -155,17 +160,22 @@ added: v0.5.9
Global instance of [`https.Agent`][] for all HTTPS client requests.

## https.request(options[, callback])
## https.request(url[, options][, callback])
<!-- YAML
added: v0.3.6
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/21616
description: allow both url and options to be passed to `https.request()`
- version: v9.3.0
pr-url: https://github.com/nodejs/node/pull/14903
description: The `options` parameter can now include `clientCertEngine`.
- version: v7.5.0
pr-url: https://github.com/nodejs/node/pull/10638
description: The `options` parameter can be a WHATWG `URL` object.
-->
- `options` {Object | string | URL} Accepts all `options` from
- `url` {string | URL}
- `options` {Object} Accepts all `options` from
[`http.request()`][], with some differences in default values:
- `protocol` **Default:** `'https:'`
- `port` **Default:** `443`
Expand Down
29 changes: 19 additions & 10 deletions lib/_http_client.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,16 @@ function validateHost(host, name) {
}

let urlWarningEmitted = false;
function ClientRequest(options, cb) {
function ClientRequest(input, options, cb) {
OutgoingMessage.call(this);

if (typeof options === 'string') {
const urlStr = options;
if (typeof input === 'string') {
const urlStr = input;
try {
options = urlToOptions(new URL(urlStr));
input = urlToOptions(new URL(urlStr));
} catch (err) {
options = url.parse(urlStr);
if (!options.hostname) {
input = url.parse(urlStr);
if (!input.hostname) {
throw err;
}
if (!urlWarningEmitted && !process.noDeprecation) {
Expand All @@ -80,14 +80,23 @@ function ClientRequest(options, cb) {
'DeprecationWarning', 'DEP0109');
}
}
} else if (options && options[searchParamsSymbol] &&
options[searchParamsSymbol][searchParamsSymbol]) {
} else if (input && input[searchParamsSymbol] &&
input[searchParamsSymbol][searchParamsSymbol]) {
// url.URL instance
options = urlToOptions(options);
input = urlToOptions(input);
} else {
options = util._extend({}, options);
cb = options;
options = input;
input = null;
}

if (typeof options === 'function') {
cb = options;
options = null;
}

options = util._extend(input || {}, options || {});

var agent = options.agent;
var defaultAgent = options._defaultAgent || Agent.globalAgent;
if (agent === false) {
Expand Down
8 changes: 4 additions & 4 deletions lib/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ function createServer(opts, requestListener) {
return new Server(opts, requestListener);
}

function request(options, cb) {
return new ClientRequest(options, cb);
function request(url, options, cb) {
return new ClientRequest(url, options, cb);
}

function get(options, cb) {
var req = request(options, cb);
function get(url, options, cb) {
var req = request(url, options, cb);
req.end();
return req;
}
Expand Down
28 changes: 28 additions & 0 deletions test/parallel/test-http-request-arguments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const http = require('http');

// Test providing both a url and options, with the options partially
// replacing address and port portions of the URL provided.
{
const server = http.createServer(
common.mustCall((req, res) => {
assert.strictEqual(req.url, '/testpath');
res.end();
server.close();
})
);
server.listen(
0,
common.mustCall(() => {
http.get(
'http://example.com/testpath',
{ hostname: 'localhost', port: server.address().port },
common.mustCall((res) => {
res.resume();
})
);
})
);
}

0 comments on commit f9b739e

Please sign in to comment.