urllib 2.37.3 → 3.0.0-alpha.0

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/README.md CHANGED
@@ -1,21 +1,15 @@
1
1
  # urllib
2
2
 
3
3
  [![NPM version][npm-image]][npm-url]
4
- [![build status][travis-image]][travis-url]
5
- [![Build Status](https://dev.azure.com/eggjs/egg/_apis/build/status/node-modules.urllib)](https://dev.azure.com/eggjs/egg/_build/latest?definitionId=7)
4
+ [![Node.js CI](https://github.com/node-modules/urllib/actions/workflows/nodejs.yml/badge.svg)](https://github.com/node-modules/urllib/actions/workflows/nodejs.yml)
6
5
  [![Test coverage][codecov-image]][codecov-url]
7
- [![David deps][david-image]][david-url]
8
6
  [![Known Vulnerabilities][snyk-image]][snyk-url]
9
7
  [![npm download][download-image]][download-url]
10
8
 
11
9
  [npm-image]: https://img.shields.io/npm/v/urllib.svg?style=flat-square
12
10
  [npm-url]: https://npmjs.org/package/urllib
13
- [travis-image]: https://img.shields.io/travis/node-modules/urllib.svg?style=flat-square
14
- [travis-url]: https://travis-ci.org/node-modules/urllib
15
11
  [codecov-image]: https://codecov.io/gh/node-modules/urllib/branch/master/graph/badge.svg
16
12
  [codecov-url]: https://codecov.io/gh/node-modules/urllib
17
- [david-image]: https://img.shields.io/david/node-modules/urllib.svg?style=flat-square
18
- [david-url]: https://david-dm.org/node-modules/urllib
19
13
  [snyk-image]: https://snyk.io/test/npm/urllib/badge.svg?style=flat-square
20
14
  [snyk-url]: https://snyk.io/test/npm/urllib
21
15
  [download-image]: https://img.shields.io/npm/dm/urllib.svg?style=flat-square
@@ -27,63 +21,29 @@ and digest authentication, redirections, cookies, timeout and more.
27
21
  ## Install
28
22
 
29
23
  ```bash
30
- $ npm install urllib --save
24
+ npm install urllib --save
31
25
  ```
32
26
 
33
27
  ## Usage
34
28
 
35
- ### callback
29
+ ### TypeScript and ESM
36
30
 
37
31
  ```js
38
- var urllib = require('urllib');
32
+ import { request } from 'urllib';
39
33
 
40
- urllib.request('http://cnodejs.org/', function (err, data, res) {
41
- if (err) {
42
- throw err; // you need to handle error
43
- }
44
- console.log(res.statusCode);
45
- console.log(res.headers);
46
- // data is Buffer instance
47
- console.log(data.toString());
48
- });
34
+ const { data, res } = await request('http://cnodejs.org/');
35
+ // result: { data: Buffer, res: Response }
36
+ console.log('status: %s, body size: %d, headers: %j', res.statusCode, data.length, res.headers);
49
37
  ```
50
38
 
51
- ### Promise
52
-
53
- If you've installed [bluebird][bluebird],
54
- [bluebird][bluebird] will be used.
55
- `urllib` does not install [bluebird][bluebird] for you.
56
-
57
- Otherwise, if you're using a node that has native v8 Promises (v0.11.13+),
58
- then that will be used.
59
-
60
- Otherwise, this library will crash the process and exit,
61
- so you might as well install [bluebird][bluebird] as a dependency!
39
+ ### CommonJS
62
40
 
63
41
  ```js
64
- var urllib = require('urllib');
42
+ const { request } = require('urllib');
65
43
 
66
- urllib.request('http://nodejs.org').then(function (result) {
67
- // result: {data: buffer, res: response object}
68
- console.log('status: %s, body size: %d, headers: %j', result.res.statusCode, result.data.length, result.res.headers);
69
- }).catch(function (err) {
70
- console.error(err);
71
- });
72
- ```
73
-
74
- ### co & generator
75
-
76
- If you are using [co](https://github.com/visionmedia/co) or [koa](https://github.com/koajs/koa):
77
-
78
- ```js
79
- var co = require('co');
80
- var urllib = require('urllib');
81
-
82
- co(function* () {
83
- var result = yield urllib.requestThunk('http://nodejs.org');
84
- console.log('status: %s, body size: %d, headers: %j',
85
- result.status, result.data.length, result.headers);
86
- })();
44
+ const { data, res } = await request('http://cnodejs.org/');
45
+ // result: { data: Buffer, res: Response }
46
+ console.log('status: %s, body size: %d, headers: %j', res.statusCode, data.length, res.headers);
87
47
  ```
88
48
 
89
49
  ## Global `response` event
@@ -91,9 +51,10 @@ co(function* () {
91
51
  You should create a urllib instance first.
92
52
 
93
53
  ```js
94
- var httpclient = require('urllib').create();
54
+ import { HttpClient } from 'urllib';
95
55
 
96
- httpclient.on('response', function (info) {
56
+ const httpclient = new HttpClient();
57
+ httpclient.on('response', (info) => {
97
58
  error: err,
98
59
  ctx: args.ctx,
99
60
  req: {
@@ -104,89 +65,83 @@ httpclient.on('response', function (info) {
104
65
  res: res
105
66
  });
106
67
 
107
- httpclient.request('http://nodejs.org', function (err, body) {
108
- console.log('body size: %d', body.length);
109
- });
68
+ const { data, res } = await httpclient.request('https://nodejs.org');
69
+ console.log('status: %s, body size: %d, headers: %j', res.statusCode, data.length, res.headers);
110
70
  ```
111
71
 
112
72
  ## API Doc
113
73
 
114
- ### Method: `http.request(url[, options][, callback])`
74
+ ### Method: `async request(url[, options])`
115
75
 
116
76
  #### Arguments
117
77
 
118
78
  - **url** String | Object - The URL to request, either a String or a Object that return by [url.parse](http://nodejs.org/api/url.html#url_url_parse_urlstr_parsequerystring_slashesdenotehost).
119
79
  - ***options*** Object - Optional
120
- - ***method*** String - Request method, defaults to `GET`. Could be `GET`, `POST`, `DELETE` or `PUT`. Alias 'type'.
121
- - ***data*** Object - Data to be sent. Will be stringify automatically.
122
- - ***dataAsQueryString*** Boolean - Force convert `data` to query string.
123
- - ***content*** String | [Buffer](http://nodejs.org/api/buffer.html) - Manually set the content of payload. If set, `data` will be ignored.
124
- - ***stream*** [stream.Readable](http://nodejs.org/api/stream.html#stream_class_stream_readable) - Stream to be pipe to the remote. If set, `data` and `content` will be ignored.
125
- - ***writeStream*** [stream.Writable](http://nodejs.org/api/stream.html#stream_class_stream_writable) - A writable stream to be piped by the response stream. Responding data will be write to this stream and `callback` will be called with `data` set `null` after finished writing.
126
- - ***files*** {Array<ReadStream|Buffer|String> | Object | ReadStream | Buffer | String - The files will send with `multipart/form-data` format, base on `formstream`. If `method` not set, will use `POST` method by default.
127
- - ***consumeWriteStream*** [true] - consume the writeStream, invoke the callback after writeStream close.
128
- - ***contentType*** String - Type of request data. Could be `json`. If it's `json`, will auto set `Content-Type: application/json` header.
129
- - ***nestedQuerystring*** Boolean - urllib default use querystring to stringify form data which don't support nested object, will use [qs](https://github.com/ljharb/qs) instead of querystring to support nested object by set this option to true.
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
- - **fixJSONCtlChars** Boolean - Fix the control characters (U+0000 through U+001F) before JSON parse response. Default is `false`.
132
- - ***headers*** Object - Request headers.
133
- - ***keepHeaderCase*** Boolean - by default will convert header keys to lowercase
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.
135
- - ***auth*** String - `username:password` used in HTTP Basic Authorization.
136
- - ***digestAuth*** String - `username:password` used in HTTP [Digest Authorization](http://en.wikipedia.org/wiki/Digest_access_authentication).
137
- - ***agent*** [http.Agent](http://nodejs.org/api/http.html#http_class_http_agent) - HTTP Agent object.
80
+ - ***method*** String - Request method, defaults to `GET`. Could be `GET`, `POST`, `DELETE` or `PUT`. Alias 'type'.
81
+ - ***data*** Object - Data to be sent. Will be stringify automatically.
82
+ - ***dataAsQueryString*** Boolean - Force convert `data` to query string.
83
+ - ***content*** String | [Buffer](http://nodejs.org/api/buffer.html) - Manually set the content of payload. If set, `data` will be ignored.
84
+ - ***stream*** [stream.Readable](http://nodejs.org/api/stream.html#stream_class_stream_readable) - Stream to be pipe to the remote. If set, `data` and `content` will be ignored.
85
+ - ***writeStream*** [stream.Writable](http://nodejs.org/api/stream.html#stream_class_stream_writable) - A writable stream to be piped by the response stream. Responding data will be write to this stream and `callback` will be called with `data` set `null` after finished writing.
86
+ - ***files*** {Array<ReadStream|Buffer|String> | Object | ReadStream | Buffer | String - The files will send with `multipart/form-data` format, base on `formstream`. If `method` not set, will use `POST` method by default.
87
+ - ***consumeWriteStream*** [true] - consume the writeStream, invoke the callback after writeStream close.
88
+ - ***contentType*** String - Type of request data. Could be `json` (**Notes**: not use `application/json` here). If it's `json`, will auto set `Content-Type: application/json` header.
89
+ - ***nestedQuerystring*** Boolean - urllib default use querystring to stringify form data which don't support nested object, will use [qs](https://github.com/ljharb/qs) instead of querystring to support nested object by set this option to true.
90
+ - ***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`.
91
+ - **fixJSONCtlChars** Boolean - Fix the control characters (U+0000 through U+001F) before JSON parse response. Default is `false`.
92
+ - ***headers*** Object - Request headers.
93
+ - ***keepHeaderCase*** Boolean - by default will convert header keys to lowercase
94
+ - ***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.
95
+ - ***auth*** String - `username:password` used in HTTP Basic Authorization.
96
+ - ***digestAuth*** String - `username:password` used in HTTP [Digest Authorization](http://en.wikipedia.org/wiki/Digest_access_authentication).
97
+ - ***agent*** [http.Agent](http://nodejs.org/api/http.html#http_class_http_agent) - HTTP Agent object.
138
98
  Set `false` if you does not use agent.
139
- - ***httpsAgent*** [https.Agent](http://nodejs.org/api/https.html#https_class_https_agent) - HTTPS Agent object.
99
+ - ***httpsAgent*** [https.Agent](http://nodejs.org/api/https.html#https_class_https_agent) - HTTPS Agent object.
140
100
  Set `false` if you does not use agent.
141
- - ***ca*** String | Buffer | Array - An array of strings or Buffers of trusted certificates.
101
+ - ***ca*** String | Buffer | Array - An array of strings or Buffers of trusted certificates.
142
102
  If this is omitted several well known "root" CAs will be used, like VeriSign.
143
103
  These are used to authorize connections.
144
104
  **Notes**: This is necessary only if the server uses the self-signed certificate
145
- - ***rejectUnauthorized*** Boolean - If true, the server certificate is verified against the list of supplied CAs.
105
+ - ***rejectUnauthorized*** Boolean - If true, the server certificate is verified against the list of supplied CAs.
146
106
  An 'error' event is emitted if verification fails. Default: true.
147
- - ***pfx*** String | Buffer - A string or Buffer containing the private key,
107
+ - ***pfx*** String | Buffer - A string or Buffer containing the private key,
148
108
  certificate and CA certs of the server in PFX or PKCS12 format.
149
- - ***key*** String | Buffer - A string or Buffer containing the private key of the client in PEM format.
109
+ - ***key*** String | Buffer - A string or Buffer containing the private key of the client in PEM format.
150
110
  **Notes**: This is necessary only if using the client certificate authentication
151
- - ***cert*** String | Buffer - A string or Buffer containing the certificate key of the client in PEM format.
111
+ - ***cert*** String | Buffer - A string or Buffer containing the certificate key of the client in PEM format.
152
112
  **Notes**: This is necessary only if using the client certificate authentication
153
- - ***passphrase*** String - A string of passphrase for the private key or pfx.
154
- - ***ciphers*** String - A string describing the ciphers to use or exclude.
155
- - ***secureProtocol*** String - The SSL method to use, e.g. SSLv3_method to force SSL version 3.
156
- - ***followRedirect*** Boolean - follow HTTP 3xx responses as redirects. defaults to false.
157
- - ***maxRedirects*** Number - The maximum number of redirects to follow, defaults to 10.
158
- - ***formatRedirectUrl*** Function - Format the redirect url by your self. Default is `url.resolve(from, to)`.
159
- - ***beforeRequest*** Function - Before request hook, you can change every thing here.
160
- - ***streaming*** Boolean - let you get the `res` object when request connected, default `false`. alias `customResponse`
161
- - ***gzip*** Boolean - Accept gzip response content and auto decode it, default is `false`.
162
- - ***timing*** Boolean - Enable timing or not, default is `false`.
163
- - ***enableProxy*** Boolean - Enable proxy request, default is `false`.
164
- - ***proxy*** String | Object - proxy agent uri or options, default is `null`.
165
- - ***lookup*** Function - Custom DNS lookup function, default is `dns.lookup`. Require node >= 4.0.0(for http protocol) and node >=8(for https protocol)
166
- - ***checkAddress*** Function: optional, check request address to protect from SSRF and similar attacks. It receive tow arguments(`ip` and `family`) and should return true or false to identified the address is legal or not. It rely on `lookup` and have the same version requirement.
167
- - ***trace*** Boolean - Enable capture stack include call site of library entrance, default is `false`.
168
- - ***socketPath*** String - optional Unix Domain Socket. (Refer to [Node.js Document](https://nodejs.org/dist/latest-v14.x/docs/api/http.html#http_http_request_options_callback))
169
- - ***callback(err, data, res)*** Function - Optional callback.
170
- - **err** Error - Would be `null` if no error accured.
171
- - **data** Buffer | Object - The data responsed. Would be a Buffer if `dataType` is set to `text` or an JSON parsed into Object if it's set to `json`.
172
- - **res** [http.IncomingMessage](http://nodejs.org/api/http.html#http_http_incomingmessage) - The response.
113
+ - ***passphrase*** String - A string of passphrase for the private key or pfx.
114
+ - ***ciphers*** String - A string describing the ciphers to use or exclude.
115
+ - ***secureProtocol*** String - The SSL method to use, e.g. SSLv3_method to force SSL version 3.
116
+ - ***followRedirect*** Boolean - follow HTTP 3xx responses as redirects. defaults to false.
117
+ - ***maxRedirects*** Number - The maximum number of redirects to follow, defaults to 10.
118
+ - ***formatRedirectUrl*** Function - Format the redirect url by your self. Default is `url.resolve(from, to)`.
119
+ - ***beforeRequest*** Function - Before request hook, you can change every thing here.
120
+ - ***streaming*** Boolean - let you get the `res` object when request connected, default `false`. alias `customResponse`
121
+ - ***gzip*** Boolean - Accept gzip response content and auto decode it, default is `false`.
122
+ - ***timing*** Boolean - Enable timing or not, default is `false`.
123
+ - ***enableProxy*** Boolean - Enable proxy request, default is `false`.
124
+ - ***proxy*** String | Object - proxy agent uri or options, default is `null`.
125
+ - ***lookup*** Function - Custom DNS lookup function, default is `dns.lookup`. Require node >= 4.0.0(for http protocol) and node >=8(for https protocol)
126
+ - ***checkAddress*** Function: optional, check request address to protect from SSRF and similar attacks. It receive tow arguments(`ip` and `family`) and should return true or false to identified the address is legal or not. It rely on `lookup` and have the same version requirement.
127
+ - ***trace*** Boolean - Enable capture stack include call site of library entrance, default is `false`.
128
+ - ***socketPath*** String - optional Unix Domain Socket. (Refer to [Node.js Document](https://nodejs.org/dist/latest-v14.x/docs/api/http.html#http_http_request_options_callback))
173
129
 
174
130
  #### Returns
175
131
 
176
- [http.ClientRequest](http://nodejs.org/api/http.html#http_class_http_clientrequest) - The request.
177
-
178
- Calling `.abort()` method of the request stream can cancel the request.
132
+ - **data** Buffer | Object - The data responsed. Would be a Buffer if `dataType` is set to `text` or an JSON parsed into Object if it's set to `json`.
133
+ - **res** [http.IncomingMessage](http://nodejs.org/api/http.html#http_http_incomingmessage) - The response.
179
134
 
180
135
  #### Options: `options.data`
181
136
 
182
137
  When making a request:
183
138
 
184
139
  ```js
185
- urllib.request('http://example.com', {
140
+ await request('https://example.com', {
186
141
  method: 'GET',
187
142
  data: {
188
143
  'a': 'hello',
189
- 'b': 'world'
144
+ 'b': 'world',
190
145
  }
191
146
  });
192
147
  ```
@@ -207,14 +162,14 @@ for example making a `Content-Type: application/json` request.
207
162
  Notes that if you want to send a JSON body, you should stringify it yourself:
208
163
 
209
164
  ```js
210
- urllib.request('http://example.com', {
165
+ await request('https://example.com', {
211
166
  method: 'POST',
212
167
  headers: {
213
168
  'Content-Type': 'application/json'
214
169
  },
215
170
  content: JSON.stringify({
216
171
  a: 'hello',
217
- b: 'world'
172
+ b: 'world',
218
173
  })
219
174
  });
220
175
  ```
@@ -235,14 +190,14 @@ Content-Type: application/json
235
190
  This exmaple can use `options.data` with `application/json` content type:
236
191
 
237
192
  ```js
238
- urllib.request('http://example.com', {
193
+ await request('https://example.com', {
239
194
  method: 'POST',
240
195
  headers: {
241
196
  'Content-Type': 'application/json'
242
197
  },
243
198
  data: {
244
199
  a: 'hello',
245
- b: 'world'
200
+ b: 'world',
246
201
  }
247
202
  });
248
203
  ```
@@ -252,24 +207,20 @@ urllib.request('http://example.com', {
252
207
  Upload a file with a `hello` field.
253
208
 
254
209
  ```js
255
- var urllib = request('urllib');
256
-
257
- var req = urllib.request('http://my.server.com/upload', {
210
+ await request('https://example.com/upload', {
211
+ method: 'POST',
258
212
  files: __filename,
259
213
  data: {
260
214
  hello: 'hello urllib',
261
215
  },
262
- }, function (err, data, res) {
263
- // upload finished
264
216
  });
265
217
  ```
266
218
 
267
219
  Upload multi files with a `hello` field.
268
220
 
269
221
  ```js
270
- var urllib = request('urllib');
271
-
272
- var req = urllib.request('http://my.server.com/upload', {
222
+ await request('https://example.com/upload', {
223
+ method: 'POST',
273
224
  files: [
274
225
  __filename,
275
226
  fs.createReadStream(__filename),
@@ -278,22 +229,17 @@ var req = urllib.request('http://my.server.com/upload', {
278
229
  data: {
279
230
  hello: 'hello urllib with multi files',
280
231
  },
281
- }, function (err, data, res) {
282
- // upload finished
283
232
  });
284
233
  ```
285
234
 
286
235
  Custom file field name with `uploadfile`.
287
236
 
288
237
  ```js
289
- var urllib = request('urllib');
290
-
291
- var req = urllib.request('http://my.server.com/upload', {
238
+ await request('https://example.com/upload', {
239
+ method: 'POST',
292
240
  files: {
293
241
  uploadfile: __filename,
294
242
  },
295
- }, function (err, data, res) {
296
- // upload finished
297
243
  });
298
244
  ```
299
245
 
@@ -302,19 +248,16 @@ var req = urllib.request('http://my.server.com/upload', {
302
248
  Uploads a file with [formstream](https://github.com/node-modules/formstream):
303
249
 
304
250
  ```js
305
- var urllib = require('urllib');
306
- var formstream = require('formstream');
251
+ import formstream from 'formstream';
307
252
 
308
- var form = formstream();
253
+ const form = formstream();
309
254
  form.file('file', __filename);
310
255
  form.field('hello', '你好urllib');
311
256
 
312
- var req = urllib.request('http://my.server.com/upload', {
257
+ await request('https://example.com/upload', {
313
258
  method: 'POST',
314
259
  headers: form.headers(),
315
- stream: form
316
- }, function (err, data, res) {
317
- // upload finished
260
+ stream: form,
318
261
  });
319
262
  ```
320
263
 
@@ -322,19 +265,19 @@ var req = urllib.request('http://my.server.com/upload', {
322
265
 
323
266
  Response is normal object, it contains:
324
267
 
325
- * `status` or `statusCode`: response status code.
326
- * `-1` meaning some network error like `ENOTFOUND`
327
- * `-2` meaning ConnectionTimeoutError
328
- * `statusMessage`: response status message.
329
- * `headers`: response http headers, default is `{}`
330
- * `size`: response size
331
- * `aborted`: response was aborted or not
332
- * `rt`: total request and response time in ms.
333
- * `timing`: timing object if timing enable.
334
- * `remoteAddress`: http server ip address
335
- * `remotePort`: http server ip port
336
- * `socketHandledRequests`: socket already handled request count
337
- * `socketHandledResponses`: socket already handled response count
268
+ - `status` or `statusCode`: response status code.
269
+ - `-1` meaning some network error like `ENOTFOUND`
270
+ - `-2` meaning ConnectionTimeoutError
271
+ - `statusMessage`: response status message.
272
+ - `headers`: response http headers, default is `{}`
273
+ - `size`: response size
274
+ - `aborted`: response was aborted or not
275
+ - `rt`: total request and response time in ms.
276
+ - `timing`: timing object if timing enable.
277
+ - `remoteAddress`: http server ip address
278
+ - `remotePort`: http server ip port
279
+ - `socketHandledRequests`: socket already handled request count
280
+ - `socketHandledResponses`: socket already handled response count
338
281
 
339
282
  #### Response: `res.aborted`
340
283
 
@@ -342,30 +285,30 @@ If the underlaying connection was terminated before `response.end()` was called,
342
285
  `res.aborted` should be `true`.
343
286
 
344
287
  ```js
345
- require('http').createServer(function (req, res) {
288
+ import { createServer } from 'http';
289
+
290
+ createServer((req, res) => {
346
291
  req.resume();
347
- req.on('end', function () {
292
+ req.on('end', () => {
348
293
  res.write('foo haha\n');
349
- setTimeout(function () {
294
+ setTimeout(() => {
350
295
  res.write('foo haha 2');
351
- setTimeout(function () {
296
+ setTimeout(() => {
352
297
  res.socket.end();
353
298
  }, 300);
354
299
  }, 200);
355
300
  return;
356
301
  });
357
- }).listen(1984);
302
+ }).listen(2022);
358
303
 
359
- urllib.request('http://127.0.0.1:1984/socket.end', function (err, data, res) {
360
- data.toString().should.equal('foo haha\nfoo haha 2');
361
- should.ok(res.aborted);
362
- done();
363
- });
304
+ const { data, res } = await request('http://127.0.0.1:2022/socket.end');
305
+ assert.equal(data.toString(), 'foo haha\nfoo haha 2');
306
+ assert(res.aborted);
364
307
  ```
365
308
 
366
309
  ### HttpClient2
367
310
 
368
- HttpClient2 is a new instance for future. request method only return a promise, compatible with `async/await` and generator in co.
311
+ HttpClient2 base on HttpClient.
369
312
 
370
313
  #### Options
371
314
 
@@ -379,47 +322,10 @@ options extends from urllib, besides below
379
322
 
380
323
  It's not supported by using retry and writeStream, because the retry request can't stop the stream which is consuming.
381
324
 
382
- ## Proxy
383
-
384
- Support both `http` and `https` protocol.
385
-
386
- **Notice: Only support on Node.js >= 4.0.0**
387
-
388
- ### Programming
389
-
390
- ```js
391
- urllib.request('https://twitter.com/', {
392
- enableProxy: true,
393
- proxy: 'http://localhost:8008',
394
- }, (err, data, res) => {
395
- console.log(res.status, res.headers);
396
- });
397
- ```
398
-
399
- ### System environment variable
400
-
401
- - http
402
-
403
- ```bash
404
- HTTP_PROXY=http://localhost:8008
405
- http_proxy=http://localhost:8008
406
- ```
407
-
408
- - https
409
-
410
- ```bash
411
- HTTP_PROXY=http://localhost:8008
412
- http_proxy=http://localhost:8008
413
- HTTPS_PROXY=https://localhost:8008
414
- https_proxy=https://localhost:8008
415
- ```
416
-
417
- ```bash
418
- $ http_proxy=http://localhost:8008 node index.js
419
- ```
420
-
421
325
  ### Trace
326
+
422
327
  If set trace true, error stack will contains full call stack, like
328
+
423
329
  ```
424
330
  Error: connect ECONNREFUSED 127.0.0.1:11
425
331
  at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1113:14)
@@ -435,28 +341,28 @@ When open the trace, urllib may have poor perfomance, please consider carefully.
435
341
 
436
342
  ## TODO
437
343
 
438
- * [ ] Support component
439
- * [ ] Browser env use Ajax
440
- * [√] Support Proxy
441
- * [√] Upload file like form upload
442
- * [√] Auto redirect handle
443
- * [√] https & self-signed certificate
444
- * [√] Connection timeout & Response timeout
445
- * [√] Support `Accept-Encoding=gzip` by `options.gzip = true`
446
- * [√] Support [Digest access authentication](http://en.wikipedia.org/wiki/Digest_access_authentication)
344
+ - Support Proxy
345
+ - Upload file like form upload
346
+ - Auto redirect handle
347
+ - https & self-signed certificate
348
+ - Connection timeout & Response timeout
349
+ - Support `Accept-Encoding=gzip` by default
350
+ - Support [Digest access authentication](http://en.wikipedia.org/wiki/Digest_access_authentication)
447
351
 
448
352
  <!-- GITCONTRIBUTOR_START -->
449
353
 
450
354
  ## Contributors
451
355
 
452
- |[<img src="https://avatars0.githubusercontent.com/u/156269?v=4" width="100px;"/><br/><sub><b>fengmk2</b></sub>](https://github.com/fengmk2)<br/>|[<img src="https://avatars3.githubusercontent.com/u/985607?v=4" width="100px;"/><br/><sub><b>dead-horse</b></sub>](https://github.com/dead-horse)<br/>|[<img src="https://avatars2.githubusercontent.com/u/288288?v=4" width="100px;"/><br/><sub><b>xingrz</b></sub>](https://github.com/xingrz)<br/>|[<img src="https://avatars1.githubusercontent.com/u/360661?v=4" width="100px;"/><br/><sub><b>popomore</b></sub>](https://github.com/popomore)<br/>|[<img src="https://avatars3.githubusercontent.com/u/327019?v=4" width="100px;"/><br/><sub><b>JacksonTian</b></sub>](https://github.com/JacksonTian)<br/>|[<img src="https://avatars3.githubusercontent.com/u/543405?v=4" width="100px;"/><br/><sub><b>ibigbug</b></sub>](https://github.com/ibigbug)<br/>|
356
+ |[<img src="https://avatars.githubusercontent.com/u/156269?v=4" width="100px;"/><br/><sub><b>fengmk2</b></sub>](https://github.com/fengmk2)<br/>|[<img src="https://avatars.githubusercontent.com/u/985607?v=4" width="100px;"/><br/><sub><b>dead-horse</b></sub>](https://github.com/dead-horse)<br/>|[<img src="https://avatars.githubusercontent.com/u/288288?v=4" width="100px;"/><br/><sub><b>xingrz</b></sub>](https://github.com/xingrz)<br/>|[<img src="https://avatars.githubusercontent.com/u/360661?v=4" width="100px;"/><br/><sub><b>popomore</b></sub>](https://github.com/popomore)<br/>|[<img src="https://avatars.githubusercontent.com/u/327019?v=4" width="100px;"/><br/><sub><b>JacksonTian</b></sub>](https://github.com/JacksonTian)<br/>|[<img src="https://avatars.githubusercontent.com/u/543405?v=4" width="100px;"/><br/><sub><b>ibigbug</b></sub>](https://github.com/ibigbug)<br/>|
453
357
  | :---: | :---: | :---: | :---: | :---: | :---: |
454
- |[<img src="https://avatars1.githubusercontent.com/u/14790466?v=4" width="100px;"/><br/><sub><b>greenkeeperio-bot</b></sub>](https://github.com/greenkeeperio-bot)<br/>|[<img src="https://avatars2.githubusercontent.com/u/2569835?v=4" width="100px;"/><br/><sub><b>haoxins</b></sub>](https://github.com/haoxins)<br/>|[<img src="https://avatars2.githubusercontent.com/u/227713?v=4" width="100px;"/><br/><sub><b>atian25</b></sub>](https://github.com/atian25)<br/>|[<img src="https://avatars3.githubusercontent.com/u/5381764?v=4" width="100px;"/><br/><sub><b>paambaati</b></sub>](https://github.com/paambaati)<br/>|[<img src="https://avatars1.githubusercontent.com/u/1147375?v=4" width="100px;"/><br/><sub><b>alsotang</b></sub>](https://github.com/alsotang)<br/>|[<img src="https://avatars1.githubusercontent.com/u/546535?v=4" width="100px;"/><br/><sub><b>leoner</b></sub>](https://github.com/leoner)<br/>|
455
- |[<img src="https://avatars3.githubusercontent.com/u/1747852?v=4" width="100px;"/><br/><sub><b>isayme</b></sub>](https://github.com/isayme)<br/>|[<img src="https://avatars0.githubusercontent.com/u/252317?v=4" width="100px;"/><br/><sub><b>cyjake</b></sub>](https://github.com/cyjake)<br/>|[<img src="https://avatars0.githubusercontent.com/u/5856440?v=4" width="100px;"/><br/><sub><b>whxaxes</b></sub>](https://github.com/whxaxes)<br/>|[<img src="https://avatars1.githubusercontent.com/u/5139554?v=4" width="100px;"/><br/><sub><b>danielwpz</b></sub>](https://github.com/danielwpz)<br/>|[<img src="https://avatars3.githubusercontent.com/u/5127897?v=4" width="100px;"/><br/><sub><b>danielsss</b></sub>](https://github.com/danielsss)<br/>|[<img src="https://avatars2.githubusercontent.com/u/3367820?v=4" width="100px;"/><br/><sub><b>Jeff-Tian</b></sub>](https://github.com/Jeff-Tian)<br/>|
456
- |[<img src="https://avatars1.githubusercontent.com/u/32407?v=4" width="100px;"/><br/><sub><b>jedahan</b></sub>](https://github.com/jedahan)<br/>|[<img src="https://avatars3.githubusercontent.com/u/2842176?v=4" width="100px;"/><br/><sub><b>XadillaX</b></sub>](https://github.com/XadillaX)<br/>|[<img src="https://avatars1.githubusercontent.com/u/17075261?v=4" width="100px;"/><br/><sub><b>nick-ng</b></sub>](https://github.com/nick-ng)<br/>|[<img src="https://avatars2.githubusercontent.com/u/1706595?v=4" width="100px;"/><br/><sub><b>rishavsharan</b></sub>](https://github.com/rishavsharan)<br/>|[<img src="https://avatars1.githubusercontent.com/u/1886161?v=4" width="100px;"/><br/><sub><b>willizm</b></sub>](https://github.com/willizm)<br/>|[<img src="https://avatars1.githubusercontent.com/u/7227589?v=4" width="100px;"/><br/><sub><b>davidkhala</b></sub>](https://github.com/davidkhala)<br/>|
457
- [<img src="https://avatars0.githubusercontent.com/u/535479?v=4" width="100px;"/><br/><sub><b>aleafs</b></sub>](https://github.com/aleafs)<br/>|[<img src="https://avatars1.githubusercontent.com/u/3689968?v=4" width="100px;"/><br/><sub><b>Amunu</b></sub>](https://github.com/Amunu)<br/>|[<img src="https://avatars3.githubusercontent.com/in/9426?v=4" width="100px;"/><br/><sub><b>azure-pipelines[bot]</b></sub>](https://github.com/apps/azure-pipelines)<br/>|[<img src="https://avatars3.githubusercontent.com/u/929503?v=4" width="100px;"/><br/><sub><b>yuzhigang33</b></sub>](https://github.com/yuzhigang33)<br/>|[<img src="https://avatars1.githubusercontent.com/u/981128?v=4" width="100px;"/><br/><sub><b>fishbar</b></sub>](https://github.com/fishbar)<br/>|[<img src="https://avatars2.githubusercontent.com/u/1207064?v=4" width="100px;"/><br/><sub><b>gxcsoccer</b></sub>](https://github.com/gxcsoccer)<br/>
358
+ |[<img src="https://avatars.githubusercontent.com/u/14790466?v=4" width="100px;"/><br/><sub><b>greenkeeperio-bot</b></sub>](https://github.com/greenkeeperio-bot)<br/>|[<img src="https://avatars.githubusercontent.com/u/227713?v=4" width="100px;"/><br/><sub><b>atian25</b></sub>](https://github.com/atian25)<br/>|[<img src="https://avatars.githubusercontent.com/u/5381764?v=4" width="100px;"/><br/><sub><b>paambaati</b></sub>](https://github.com/paambaati)<br/>|[<img src="https://avatars.githubusercontent.com/u/1433247?v=4" width="100px;"/><br/><sub><b>denghongcai</b></sub>](https://github.com/denghongcai)<br/>|[<img src="https://avatars.githubusercontent.com/u/2842176?v=4" width="100px;"/><br/><sub><b>XadillaX</b></sub>](https://github.com/XadillaX)<br/>|[<img src="https://avatars.githubusercontent.com/u/1147375?v=4" width="100px;"/><br/><sub><b>alsotang</b></sub>](https://github.com/alsotang)<br/>|
359
+ |[<img src="https://avatars.githubusercontent.com/u/546535?v=4" width="100px;"/><br/><sub><b>leoner</b></sub>](https://github.com/leoner)<br/>|[<img src="https://avatars.githubusercontent.com/u/19908330?v=4" width="100px;"/><br/><sub><b>hyj1991</b></sub>](https://github.com/hyj1991)<br/>|[<img src="https://avatars.githubusercontent.com/u/1747852?v=4" width="100px;"/><br/><sub><b>isayme</b></sub>](https://github.com/isayme)<br/>|[<img src="https://avatars.githubusercontent.com/u/252317?v=4" width="100px;"/><br/><sub><b>cyjake</b></sub>](https://github.com/cyjake)<br/>|[<img src="https://avatars.githubusercontent.com/u/5856440?v=4" width="100px;"/><br/><sub><b>whxaxes</b></sub>](https://github.com/whxaxes)<br/>|[<img src="https://avatars.githubusercontent.com/u/309219?v=4" width="100px;"/><br/><sub><b>chadxz</b></sub>](https://github.com/chadxz)<br/>|
360
+ |[<img src="https://avatars.githubusercontent.com/u/5139554?v=4" width="100px;"/><br/><sub><b>danielwpz</b></sub>](https://github.com/danielwpz)<br/>|[<img src="https://avatars.githubusercontent.com/u/5127897?v=4" width="100px;"/><br/><sub><b>danielsss</b></sub>](https://github.com/danielsss)<br/>|[<img src="https://avatars.githubusercontent.com/u/3367820?v=4" width="100px;"/><br/><sub><b>Jeff-Tian</b></sub>](https://github.com/Jeff-Tian)<br/>|[<img src="https://avatars.githubusercontent.com/u/32407?v=4" width="100px;"/><br/><sub><b>jedahan</b></sub>](https://github.com/jedahan)<br/>|[<img src="https://avatars.githubusercontent.com/u/17075261?v=4" width="100px;"/><br/><sub><b>nick-ng</b></sub>](https://github.com/nick-ng)<br/>|[<img src="https://avatars.githubusercontent.com/u/1706595?v=4" width="100px;"/><br/><sub><b>rishavsharan</b></sub>](https://github.com/rishavsharan)<br/>|
361
+ |[<img src="https://avatars.githubusercontent.com/u/1886161?v=4" width="100px;"/><br/><sub><b>willizm</b></sub>](https://github.com/willizm)<br/>|[<img src="https://avatars.githubusercontent.com/u/7227589?v=4" width="100px;"/><br/><sub><b>davidkhala</b></sub>](https://github.com/davidkhala)<br/>|[<img src="https://avatars.githubusercontent.com/u/535479?v=4" width="100px;"/><br/><sub><b>aleafs</b></sub>](https://github.com/aleafs)<br/>|[<img src="https://avatars.githubusercontent.com/u/3689968?v=4" width="100px;"/><br/><sub><b>Amunu</b></sub>](https://github.com/Amunu)<br/>|[<img src="https://avatars.githubusercontent.com/in/9426?v=4" width="100px;"/><br/><sub><b>azure-pipelines[bot]</b></sub>](https://github.com/apps/azure-pipelines)<br/>|[<img src="https://avatars.githubusercontent.com/u/1281323?v=4" width="100px;"/><br/><sub><b>changzhiwin</b></sub>](https://github.com/changzhiwin)<br/>|
362
+ |[<img src="https://avatars.githubusercontent.com/u/929503?v=4" width="100px;"/><br/><sub><b>yuzhigang33</b></sub>](https://github.com/yuzhigang33)<br/>|[<img src="https://avatars.githubusercontent.com/u/981128?v=4" width="100px;"/><br/><sub><b>fishbar</b></sub>](https://github.com/fishbar)<br/>|[<img src="https://avatars.githubusercontent.com/u/1207064?v=4" width="100px;"/><br/><sub><b>gxcsoccer</b></sub>](https://github.com/gxcsoccer)<br/>|[<img src="https://avatars.githubusercontent.com/u/6897780?v=4" width="100px;"/><br/><sub><b>killagu</b></sub>](https://github.com/killagu)<br/>|[<img src="https://avatars.githubusercontent.com/u/17476119?v=4" width="100px;"/><br/><sub><b>mars-coder</b></sub>](https://github.com/mars-coder)<br/>|[<img src="https://avatars.githubusercontent.com/u/929179?v=4" width="100px;"/><br/><sub><b>rockdai</b></sub>](https://github.com/rockdai)<br/>|
363
+ [<img src="https://avatars.githubusercontent.com/u/2196373?v=4" width="100px;"/><br/><sub><b>dickeylth</b></sub>](https://github.com/dickeylth)<br/>|[<img src="https://avatars.githubusercontent.com/u/13050025?v=4" width="100px;"/><br/><sub><b>aladdin-add</b></sub>](https://github.com/aladdin-add)<br/>
458
364
 
459
- This project follows the git-contributor [spec](https://github.com/xudafeng/git-contributor), auto updated at `Sat Jan 16 2021 23:16:33 GMT+0800`.
365
+ This project follows the git-contributor [spec](https://github.com/xudafeng/git-contributor), auto updated at `Fri Mar 25 2022 00:05:23 GMT+0800`.
460
366
 
461
367
  <!-- GITCONTRIBUTOR_END -->
462
368
 
@@ -464,5 +370,4 @@ This project follows the git-contributor [spec](https://github.com/xudafeng/git-
464
370
 
465
371
  [MIT](LICENSE)
466
372
 
467
-
468
373
  [bluebird]: https://github.com/petkaantonov/bluebird