Skip to content

Commit 4365379

Browse files
committed
http: allow url and options to be passed to http*.request and http*.get
fixes #20795
1 parent f85962f commit 4365379

File tree

5 files changed

+79
-19
lines changed

5 files changed

+79
-19
lines changed

doc/api/http.md

+16-3
Original file line numberDiff line numberDiff line change
@@ -1798,15 +1798,20 @@ The `requestListener` is a function which is automatically
17981798
added to the [`'request'`][] event.
17991799

18001800
## http.get(options[, callback])
1801+
## http.get(url[, options][, callback])
18011802
<!-- YAML
18021803
added: v0.3.6
18031804
changes:
1805+
- version: REPLACEME
1806+
pr-url: https://github.com/nodejs/node/pull/21616
1807+
description: allow both url and options to be passed to `http.get()`
18041808
- version: v7.5.0
18051809
pr-url: https://github.com/nodejs/node/pull/10638
18061810
description: The `options` parameter can be a WHATWG `URL` object.
18071811
-->
18081812

1809-
* `options` {Object | string | URL} Accepts the same `options` as
1813+
* `url` {string | URL}
1814+
* `options` {Object} Accepts the same `options` as
18101815
[`http.request()`][], with the `method` always set to `GET`.
18111816
Properties that are inherited from the prototype are ignored.
18121817
* `callback` {Function}
@@ -1870,15 +1875,20 @@ Global instance of `Agent` which is used as the default for all HTTP client
18701875
requests.
18711876

18721877
## http.request(options[, callback])
1878+
## http.request(url[, options][, callback])
18731879
<!-- YAML
18741880
added: v0.3.6
18751881
changes:
1882+
- version: REPLACEME
1883+
pr-url: https://github.com/nodejs/node/pull/21616
1884+
description: allow both url and options to be passed to `http.request()`
18761885
- version: v7.5.0
18771886
pr-url: https://github.com/nodejs/node/pull/10638
18781887
description: The `options` parameter can be a WHATWG `URL` object.
18791888
-->
18801889

1881-
* `options` {Object | string | URL}
1890+
* `url` {string | URL}
1891+
* `options` {Object}
18821892
* `protocol` {string} Protocol to use. **Default:** `'http:'`.
18831893
* `host` {string} A domain name or IP address of the server to issue the
18841894
request to. **Default:** `'localhost'`.
@@ -1920,10 +1930,13 @@ changes:
19201930
Node.js maintains several connections per server to make HTTP requests.
19211931
This function allows one to transparently issue requests.
19221932

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

1937+
If both `url` and `options` are specified, the objects are merged, with the
1938+
`options` properties taking precedence.
1939+
19271940
The optional `callback` parameter will be added as a one-time listener for
19281941
the [`'response'`][] event.
19291942

doc/api/https.md

+12-2
Original file line numberDiff line numberDiff line change
@@ -112,14 +112,19 @@ https.createServer(options, (req, res) => {
112112
```
113113

114114
## https.get(options[, callback])
115+
## https.get(url[, options][, callback])
115116
<!-- YAML
116117
added: v0.3.6
117118
changes:
119+
- version: REPLACEME
120+
pr-url: https://github.com/nodejs/node/pull/21616
121+
description: allow both url and options to be passed to `https.get()`
118122
- version: v7.5.0
119123
pr-url: https://github.com/nodejs/node/pull/10638
120124
description: The `options` parameter can be a WHATWG `URL` object.
121125
-->
122-
- `options` {Object | string | URL} Accepts the same `options` as
126+
- `url` {string | URL}
127+
- `options` {Object} Accepts the same `options` as
123128
[`https.request()`][], with the `method` always set to `GET`.
124129
- `callback` {Function}
125130

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

157162
## https.request(options[, callback])
163+
## https.request(url[, options][, callback])
158164
<!-- YAML
159165
added: v0.3.6
160166
changes:
167+
- version: REPLACEME
168+
pr-url: https://github.com/nodejs/node/pull/21616
169+
description: allow both url and options to be passed to `https.request()`
161170
- version: v9.3.0
162171
pr-url: https://github.com/nodejs/node/pull/14903
163172
description: The `options` parameter can now include `clientCertEngine`.
164173
- version: v7.5.0
165174
pr-url: https://github.com/nodejs/node/pull/10638
166175
description: The `options` parameter can be a WHATWG `URL` object.
167176
-->
168-
- `options` {Object | string | URL} Accepts all `options` from
177+
- `url` {string | URL}
178+
- `options` {Object} Accepts all `options` from
169179
[`http.request()`][], with some differences in default values:
170180
- `protocol` **Default:** `'https:'`
171181
- `port` **Default:** `443`

lib/_http_client.js

+19-10
Original file line numberDiff line numberDiff line change
@@ -60,16 +60,16 @@ function validateHost(host, name) {
6060
}
6161

6262
let urlWarningEmitted = false;
63-
function ClientRequest(options, cb) {
63+
function ClientRequest(input, options, cb) {
6464
OutgoingMessage.call(this);
6565

66-
if (typeof options === 'string') {
67-
const urlStr = options;
66+
if (typeof input === 'string') {
67+
const urlStr = input;
6868
try {
69-
options = urlToOptions(new URL(urlStr));
69+
input = urlToOptions(new URL(urlStr));
7070
} catch (err) {
71-
options = url.parse(urlStr);
72-
if (!options.hostname) {
71+
input = url.parse(urlStr);
72+
if (!input.hostname) {
7373
throw err;
7474
}
7575
if (!urlWarningEmitted && !process.noDeprecation) {
@@ -80,14 +80,23 @@ function ClientRequest(options, cb) {
8080
'DeprecationWarning', 'DEP0109');
8181
}
8282
}
83-
} else if (options && options[searchParamsSymbol] &&
84-
options[searchParamsSymbol][searchParamsSymbol]) {
83+
} else if (input && input[searchParamsSymbol] &&
84+
input[searchParamsSymbol][searchParamsSymbol]) {
8585
// url.URL instance
86-
options = urlToOptions(options);
86+
input = urlToOptions(input);
8787
} else {
88-
options = util._extend({}, options);
88+
cb = options;
89+
options = input;
90+
input = null;
8991
}
9092

93+
if (typeof options === 'function') {
94+
cb = options;
95+
options = null;
96+
}
97+
98+
options = util._extend(input || {}, options || {});
99+
91100
var agent = options.agent;
92101
var defaultAgent = options._defaultAgent || Agent.globalAgent;
93102
if (agent === false) {

lib/http.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@ function createServer(opts, requestListener) {
3737
return new Server(opts, requestListener);
3838
}
3939

40-
function request(options, cb) {
41-
return new ClientRequest(options, cb);
40+
function request(url, options, cb) {
41+
return new ClientRequest(url, options, cb);
4242
}
4343

44-
function get(options, cb) {
45-
var req = request(options, cb);
44+
function get(url, options, cb) {
45+
var req = request(url, options, cb);
4646
req.end();
4747
return req;
4848
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
'use strict';
2+
const common = require('../common');
3+
const assert = require('assert');
4+
const http = require('http');
5+
6+
// test providing both a url and options, with the options partially
7+
// replacing address and port portions of the URL provided
8+
{
9+
const server = http.createServer(
10+
common.mustCall((req, res) => {
11+
assert.strictEqual(req.url, '/testpath');
12+
res.end();
13+
server.close();
14+
})
15+
);
16+
server.listen(
17+
0,
18+
common.mustCall(() => {
19+
http.get(
20+
'http://example.com/testpath',
21+
{ hostname: 'localhost', port: server.address().port },
22+
common.mustCall((res) => {
23+
res.resume();
24+
})
25+
);
26+
})
27+
);
28+
}

0 commit comments

Comments
 (0)