urllib 2.34.1 → 2.36.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/History.md +31 -0
- package/{LICENSE.txt → LICENSE} +5 -5
- package/README.md +1 -0
- package/lib/index.d.ts +7 -0
- package/lib/urllib.js +70 -33
- package/package.json +10 -1
package/History.md
CHANGED
@@ -1,4 +1,35 @@
|
|
1
1
|
|
2
|
+
2.36.1 / 2020-06-09
|
3
|
+
==================
|
4
|
+
|
5
|
+
**others**
|
6
|
+
* [[`35eecc0`](http://github.com/node-modules/urllib/commit/35eecc021f55e324b2520f91a032a33517d94f29)] - chore: add type declaration for RequestOptions#keepHeaderCase (#345) (William <<willizm.cn@gmail.com>>)
|
7
|
+
|
8
|
+
2.36.0 / 2020-06-08
|
9
|
+
==================
|
10
|
+
|
11
|
+
**fixes**
|
12
|
+
* [[`15c4170`](http://github.com/node-modules/urllib/commit/15c4170beab4404b0576caa01e199f445c476b7d)] - fix: allow to keep origin header key case (#344) (TZ | 天猪 <<atian25@qq.com>>)
|
13
|
+
|
14
|
+
**others**
|
15
|
+
* [[`31c03b8`](http://github.com/node-modules/urllib/commit/31c03b853ae5db00c7223c0a1a545dfcf0b07aa5)] - chore: Update and rename LICENSE.txt to LICENSE (#343) (Yuxiang LIU <<david-khala@hotmail.com>>)
|
16
|
+
|
17
|
+
2.35.0 / 2020-05-15
|
18
|
+
==================
|
19
|
+
|
20
|
+
**features**
|
21
|
+
* [[`47c21bd`](http://github.com/node-modules/urllib/commit/47c21bd93648080589bdc6528d9e9cf3e0489951)] - feat: change header to lowercase (#337) (TZ | 天猪 <<atian25@qq.com>>)
|
22
|
+
|
23
|
+
**fixes**
|
24
|
+
* [[`8f2ca64`](http://github.com/node-modules/urllib/commit/8f2ca648608995d140d0ca3873ef728bdbd4ee41)] - fix: need to handle response data on close event (#340) (fengmk2 <<fengmk2@gmail.com>>)
|
25
|
+
* [[`175ad2b`](http://github.com/node-modules/urllib/commit/175ad2b3e17196626c701ef72396dd6932d14c7a)] - fix: res.socket is null in node-v14.x (#339) (hyj1991 <<yeekwanvong@gmail.com>>)
|
26
|
+
|
27
|
+
2.34.2 / 2019-12-09
|
28
|
+
==================
|
29
|
+
|
30
|
+
**fixes**
|
31
|
+
* [[`67d5b1c`](http://github.com/node-modules/urllib/commit/67d5b1c35dc302778aa4b992ea4998fe427e3cc8)] - fix: index.d.ts (#334) (Daniels.Sun <<better.sunjian@gmail.com>>)
|
32
|
+
|
2
33
|
2.34.1 / 2019-09-02
|
3
34
|
==================
|
4
35
|
|
package/{LICENSE.txt → LICENSE}
RENAMED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
MIT License
|
2
2
|
|
3
3
|
Copyright(c) 2011 - 2014 fengmk2 and other contributors.
|
4
4
|
Copyright(c) 2015 - present node-modules and other contributors.
|
@@ -10,13 +10,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
10
|
copies of the Software, and to permit persons to whom the Software is
|
11
11
|
furnished to do so, subject to the following conditions:
|
12
12
|
|
13
|
-
The above copyright notice and this permission notice shall be included in
|
14
|
-
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
14
|
+
copies or substantial portions of the Software.
|
15
15
|
|
16
16
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
17
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
18
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
19
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
20
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
|
-
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
22
|
+
SOFTWARE.
|
package/README.md
CHANGED
@@ -130,6 +130,7 @@ httpclient.request('http://nodejs.org', function (err, body) {
|
|
130
130
|
- ***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`.
|
131
131
|
- **fixJSONCtlChars** Boolean - Fix the control characters (U+0000 through U+001F) before JSON parse response. Default is `false`.
|
132
132
|
- ***headers*** Object - Request headers.
|
133
|
+
- ***keepHeaderCase*** Boolean - by default will convert header keys to lowercase
|
133
134
|
- ***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.
|
134
135
|
- ***auth*** String - `username:password` used in HTTP Basic Authorization.
|
135
136
|
- ***digestAuth*** String - `username:password` used in HTTP [Digest Authorization](http://en.wikipedia.org/wiki/Digest_access_authentication).
|
package/lib/index.d.ts
CHANGED
@@ -31,6 +31,11 @@ export interface RequestOptions {
|
|
31
31
|
writeStream?: Writable;
|
32
32
|
/** consume the writeStream, invoke the callback after writeStream close. */
|
33
33
|
consumeWriteStream?: boolean;
|
34
|
+
/**
|
35
|
+
* The files will send with multipart/form-data format, base on formstream.
|
36
|
+
* If method not set, will use POST method by default.
|
37
|
+
*/
|
38
|
+
files?: Array<Readable | Buffer | string> | object | Readable | Buffer | string;
|
34
39
|
/** Type of request data.Could be json.If it's json, will auto set Content-Type: application/json header. */
|
35
40
|
contentType?: string;
|
36
41
|
/**
|
@@ -49,6 +54,8 @@ export interface RequestOptions {
|
|
49
54
|
fixJSONCtlChars?: boolean;
|
50
55
|
/** Request headers. */
|
51
56
|
headers?: IncomingHttpHeaders;
|
57
|
+
/** by default will convert header keys to lowercase */
|
58
|
+
keepHeaderCase?: boolean;
|
52
59
|
/**
|
53
60
|
* Request timeout in milliseconds for connecting phase and response receiving phase.
|
54
61
|
* Defaults to exports.
|
package/lib/urllib.js
CHANGED
@@ -105,6 +105,7 @@ var SOCKET_RESPONSE_COUNT = '_URLLIB_SOCKET_RESPONSE_COUNT';
|
|
105
105
|
* before JSON parse response. Default is `false`.
|
106
106
|
* `fixJSONCtlChars` can be a function, will pass data to the first argument. e.g.: `data = fixJSONCtlChars(data)`
|
107
107
|
* - {Object} [headers]: optional, request headers
|
108
|
+
* - {Boolean} [keepHeaderCase]: optional, by default will convert header keys to lowercase
|
108
109
|
* - {Number|Array} [timeout]: request timeout(in milliseconds), default is `exports.TIMEOUTS containing connect timeout and response timeout`
|
109
110
|
* - {Agent} [agent]: optional, http agent. Set `false` if you does not use agent.
|
110
111
|
* - {Agent} [httpsAgent]: optional, https agent. Set `false` if you does not use agent.
|
@@ -196,6 +197,7 @@ exports.requestThunk = function requestThunk(url, args) {
|
|
196
197
|
};
|
197
198
|
|
198
199
|
function requestWithCallback(url, args, callback) {
|
200
|
+
var req;
|
199
201
|
// requestWithCallback(url, callback)
|
200
202
|
if (!url || (typeof url !== 'string' && typeof url !== 'object')) {
|
201
203
|
var msg = util.format('expect request url to be a string or a http request options, but got %j', url);
|
@@ -299,12 +301,18 @@ function requestWithCallback(url, args, callback) {
|
|
299
301
|
// https://github.com/nodejs/node/blob/archived-io.js-v0.12/lib/net.js#L952
|
300
302
|
lookup: lookup,
|
301
303
|
};
|
304
|
+
|
305
|
+
var originHeaderKeys = {};
|
302
306
|
if (args.headers) {
|
303
307
|
// only allow enumerable and ownProperty value of args.headers
|
304
308
|
var names = utility.getOwnEnumerables(args.headers, true);
|
305
309
|
for (var i = 0; i < names.length; i++) {
|
306
310
|
var name = names[i];
|
307
|
-
|
311
|
+
var key = name.toLowerCase();
|
312
|
+
if (key !== name) {
|
313
|
+
originHeaderKeys[key] = name;
|
314
|
+
}
|
315
|
+
options.headers[key] = args.headers[name];
|
308
316
|
}
|
309
317
|
}
|
310
318
|
|
@@ -386,7 +394,7 @@ function requestWithCallback(url, args, callback) {
|
|
386
394
|
var formHeaderNames = utility.getOwnEnumerables(formHeaders, true);
|
387
395
|
for (var i = 0; i < formHeaderNames.length; i++) {
|
388
396
|
var name = formHeaderNames[i];
|
389
|
-
options.headers[name] = formHeaders[name];
|
397
|
+
options.headers[name.toLowerCase()] = formHeaders[name];
|
390
398
|
}
|
391
399
|
debug('set multipart headers: %j, method: %s', formHeaders, options.method);
|
392
400
|
args.stream = form;
|
@@ -399,7 +407,7 @@ function requestWithCallback(url, args, callback) {
|
|
399
407
|
// read: GET, HEAD, use query string
|
400
408
|
body = args.nestedQuerystring ? qs.stringify(body) : querystring.stringify(body);
|
401
409
|
} else {
|
402
|
-
var contentType = options.headers['
|
410
|
+
var contentType = options.headers['content-type'];
|
403
411
|
// auto add application/x-www-form-urlencoded when using urlencode form request
|
404
412
|
if (!contentType) {
|
405
413
|
if (args.contentType === 'json') {
|
@@ -407,7 +415,7 @@ function requestWithCallback(url, args, callback) {
|
|
407
415
|
} else {
|
408
416
|
contentType = 'application/x-www-form-urlencoded';
|
409
417
|
}
|
410
|
-
options.headers['
|
418
|
+
options.headers['content-type'] = contentType;
|
411
419
|
}
|
412
420
|
|
413
421
|
if (parseContentType(contentType).type === 'application/json') {
|
@@ -433,13 +441,15 @@ function requestWithCallback(url, args, callback) {
|
|
433
441
|
if (!Buffer.isBuffer(body)) {
|
434
442
|
length = Buffer.byteLength(body);
|
435
443
|
}
|
436
|
-
requestSize =
|
444
|
+
requestSize = length;
|
445
|
+
|
446
|
+
options.headers['content-length'] = length.toString();
|
437
447
|
}
|
438
448
|
}
|
439
449
|
|
440
450
|
if (args.dataType === 'json') {
|
441
|
-
if (!options.headers.
|
442
|
-
options.headers.
|
451
|
+
if (!options.headers.accept) {
|
452
|
+
options.headers.accept = 'application/json';
|
443
453
|
}
|
444
454
|
}
|
445
455
|
|
@@ -447,6 +457,7 @@ function requestWithCallback(url, args, callback) {
|
|
447
457
|
// you can use this hook to change every thing.
|
448
458
|
args.beforeRequest(options);
|
449
459
|
}
|
460
|
+
|
450
461
|
var connectTimer = null;
|
451
462
|
var responseTimer = null;
|
452
463
|
var __err = null;
|
@@ -516,14 +527,14 @@ function requestWithCallback(url, args, callback) {
|
|
516
527
|
|
517
528
|
// handle digest auth
|
518
529
|
if (statusCode === 401 && headers['www-authenticate']
|
519
|
-
&& !options.headers.
|
530
|
+
&& !options.headers.authorization && args.digestAuth) {
|
520
531
|
var authenticate = headers['www-authenticate'];
|
521
532
|
if (authenticate.indexOf('Digest ') >= 0) {
|
522
533
|
debug('Request#%d %s: got digest auth header WWW-Authenticate: %s', reqId, url, authenticate);
|
523
|
-
options.headers.
|
524
|
-
debug('Request#%d %s: auth with digest header: %s', reqId, url, options.headers.
|
534
|
+
options.headers.authorization = digestAuthHeader(options.method, options.path, authenticate, args.digestAuth);
|
535
|
+
debug('Request#%d %s: auth with digest header: %s', reqId, url, options.headers.authorization);
|
525
536
|
if (res.headers['set-cookie']) {
|
526
|
-
options.headers.
|
537
|
+
options.headers.cookie = res.headers['set-cookie'].join(';');
|
527
538
|
}
|
528
539
|
args.headers = options.headers;
|
529
540
|
return exports.requestWithCallback(url, args, cb);
|
@@ -592,10 +603,11 @@ function requestWithCallback(url, args, callback) {
|
|
592
603
|
if (serverSocketTimeout < freeSocketTimeout) {
|
593
604
|
// https://github.com/node-modules/agentkeepalive/blob/master/lib/agent.js#L127
|
594
605
|
// agentkeepalive@4
|
606
|
+
var socket = res.socket || (req && req.socket);
|
595
607
|
if (agent.options && agent.options.freeSocketTimeout) {
|
596
|
-
|
608
|
+
socket.freeSocketTimeout = serverSocketTimeout;
|
597
609
|
} else {
|
598
|
-
|
610
|
+
socket.freeSocketKeepAliveTimeout = serverSocketTimeout;
|
599
611
|
}
|
600
612
|
}
|
601
613
|
}
|
@@ -637,9 +649,9 @@ function requestWithCallback(url, args, callback) {
|
|
637
649
|
debug('Request#%d %s: `redirected` from %s to %s', reqId, options.path, url, newUrl);
|
638
650
|
// make sure timer stop
|
639
651
|
cancelResponseTimer();
|
640
|
-
// should clean up headers.
|
641
|
-
if (options.headers.
|
642
|
-
options.headers.
|
652
|
+
// should clean up headers.host on `location: http://other-domain/url`
|
653
|
+
if (options.headers.host && PROTO_RE.test(location)) {
|
654
|
+
options.headers.host = null;
|
643
655
|
args.headers = options.headers;
|
644
656
|
}
|
645
657
|
// avoid done will be execute in the future change.
|
@@ -663,23 +675,20 @@ function requestWithCallback(url, args, callback) {
|
|
663
675
|
if (options.headers['user-agent']) {
|
664
676
|
delete options.headers['user-agent'];
|
665
677
|
}
|
666
|
-
if (options.headers['User-Agent']) {
|
667
|
-
delete options.headers['User-Agent'];
|
668
|
-
}
|
669
678
|
} else {
|
670
679
|
// need to set user-agent
|
671
|
-
var hasAgentHeader = options.headers['
|
680
|
+
var hasAgentHeader = options.headers['user-agent'];
|
672
681
|
if (!hasAgentHeader) {
|
673
|
-
options.headers['
|
682
|
+
options.headers['user-agent'] = USER_AGENT;
|
674
683
|
}
|
675
684
|
}
|
676
685
|
|
677
686
|
if (args.gzip) {
|
678
687
|
var isAcceptEncodingNull = (args.headers && (args.headers['Accept-Encoding'] === null || args.headers['accept-encoding'] === null));
|
679
688
|
if (!isAcceptEncodingNull) {
|
680
|
-
var hasAcceptEncodingHeader = options.headers['
|
689
|
+
var hasAcceptEncodingHeader = options.headers['accept-encoding'];
|
681
690
|
if (!hasAcceptEncodingHeader) {
|
682
|
-
options.headers['
|
691
|
+
options.headers['accept-encoding'] = 'gzip, deflate';
|
683
692
|
}
|
684
693
|
}
|
685
694
|
}
|
@@ -737,11 +746,6 @@ function requestWithCallback(url, args, callback) {
|
|
737
746
|
return done(null, null, res);
|
738
747
|
}
|
739
748
|
|
740
|
-
res.on('close', function () {
|
741
|
-
debug('Request#%d %s: `res close` event emit, total size %d, socket handled %s requests and %s responses',
|
742
|
-
reqId, url, responseSize, socketHandledRequests, socketHandledResponses);
|
743
|
-
});
|
744
|
-
|
745
749
|
res.on('error', function () {
|
746
750
|
debug('Request#%d %s: `res error` event emit, total size %d, socket handled %s requests and %s responses',
|
747
751
|
reqId, url, responseSize, socketHandledRequests, socketHandledResponses);
|
@@ -843,10 +847,18 @@ function requestWithCallback(url, args, callback) {
|
|
843
847
|
chunks.push(chunk);
|
844
848
|
});
|
845
849
|
|
846
|
-
|
850
|
+
var isEmitted = false;
|
851
|
+
function handleResponseCloseAndEnd(event) {
|
852
|
+
debug('Request#%d %s: `res %s` event emit, total size %d, socket handled %s requests and %s responses',
|
853
|
+
reqId, url, event, responseSize, socketHandledRequests, socketHandledResponses);
|
854
|
+
if (isEmitted) {
|
855
|
+
return;
|
856
|
+
}
|
857
|
+
isEmitted = true;
|
858
|
+
|
847
859
|
var body = Buffer.concat(chunks, responseSize);
|
848
|
-
debug('Request#%d %s:
|
849
|
-
reqId, url,
|
860
|
+
debug('Request#%d %s: _dumped: %s',
|
861
|
+
reqId, url, res._dumped);
|
850
862
|
|
851
863
|
if (__err) {
|
852
864
|
// req.abort() after `res data` event emit.
|
@@ -898,6 +910,14 @@ function requestWithCallback(url, args, callback) {
|
|
898
910
|
|
899
911
|
done(err, data, res);
|
900
912
|
});
|
913
|
+
}
|
914
|
+
|
915
|
+
// node >= 14 only emit close if req abort
|
916
|
+
res.on('close', function () {
|
917
|
+
handleResponseCloseAndEnd('close');
|
918
|
+
});
|
919
|
+
res.on('end', function () {
|
920
|
+
handleResponseCloseAndEnd('end');
|
901
921
|
});
|
902
922
|
}
|
903
923
|
|
@@ -966,10 +986,27 @@ function requestWithCallback(url, args, callback) {
|
|
966
986
|
}
|
967
987
|
}
|
968
988
|
|
969
|
-
var req;
|
970
989
|
// request headers checker will throw error
|
971
990
|
try {
|
972
|
-
|
991
|
+
var finalOptions = options;
|
992
|
+
|
993
|
+
// restore origin header key
|
994
|
+
if (args.keepHeaderCase) {
|
995
|
+
var originKeys = Object.keys(originHeaderKeys);
|
996
|
+
if (originKeys.length) {
|
997
|
+
var finalHeaders = {};
|
998
|
+
var names = utility.getOwnEnumerables(options.headers, true);
|
999
|
+
for (var i = 0; i < names.length; i++) {
|
1000
|
+
var name = names[i];
|
1001
|
+
finalHeaders[originHeaderKeys[name] || name] = options.headers[name];
|
1002
|
+
}
|
1003
|
+
|
1004
|
+
finalOptions = Object.assign({}, options);
|
1005
|
+
finalOptions.headers = finalHeaders;
|
1006
|
+
}
|
1007
|
+
}
|
1008
|
+
|
1009
|
+
req = httplib.request(finalOptions, onResponse);
|
973
1010
|
if (args.trace) {
|
974
1011
|
req._callSite = {};
|
975
1012
|
Error.captureStackTrace(req._callSite, requestWithCallback);
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "urllib",
|
3
|
-
"version": "2.
|
3
|
+
"version": "2.36.1",
|
4
4
|
"description": "Help in opening URLs (mostly HTTP) in a complex world — basic and digest authentication, redirections, cookies and more.",
|
5
5
|
"keywords": [
|
6
6
|
"urllib",
|
@@ -58,6 +58,7 @@
|
|
58
58
|
"busboy": "^0.2.14",
|
59
59
|
"co": "*",
|
60
60
|
"coffee": "1",
|
61
|
+
"egg-ci": "^1.15.0",
|
61
62
|
"git-contributor": "^1.0.10",
|
62
63
|
"http-proxy": "^1.16.2",
|
63
64
|
"intelli-espower-loader": "^1.0.1",
|
@@ -69,6 +70,7 @@
|
|
69
70
|
"pedding": "^1.1.0",
|
70
71
|
"power-assert": "^1.4.2",
|
71
72
|
"semver": "5",
|
73
|
+
"spy": "^1.0.0",
|
72
74
|
"tar": "^4.4.8",
|
73
75
|
"through2": "^2.0.3",
|
74
76
|
"typescript": "^3.2.2"
|
@@ -76,5 +78,12 @@
|
|
76
78
|
"engines": {
|
77
79
|
"node": ">= 0.10.0"
|
78
80
|
},
|
81
|
+
"ci": {
|
82
|
+
"type": "github",
|
83
|
+
"os": {
|
84
|
+
"github": "linux, windows, macos"
|
85
|
+
},
|
86
|
+
"version": "6, 8, 10, 12, 14"
|
87
|
+
},
|
79
88
|
"license": "MIT"
|
80
89
|
}
|