http: allow url and options to be passed to http*.request and http*.get

Fixes: https://github.com/nodejs/node/issues/20795
PR-URL: https://github.com/nodejs/node/pull/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>
This commit is contained in:
Sam Ruby 2018-07-01 11:00:24 -04:00 committed by Matteo Collina
parent 19bc893c75
commit f9b739ebbc
5 changed files with 79 additions and 19 deletions

View File

@ -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}
@ -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'`.
@ -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.

View File

@ -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}
@ -155,9 +160,13 @@ 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`.
@ -165,7 +174,8 @@ changes:
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`

View File

@ -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) {
@ -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) {

View File

@ -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;
}

View File

@ -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();
})
);
})
);
}