@wiajs/request 3.0.29 → 3.0.30

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/dist/request.mjs CHANGED
@@ -1,14 +1,14 @@
1
1
  /*!
2
- * wia request v3.0.29
2
+ * wia request v3.0.30
3
3
  * (c) 2022-2024 Sibyl Yu and contributors
4
4
  * Released under the MIT License.
5
5
  */
6
+ import stream, { Duplex } from 'node:stream';
6
7
  import { log as log$2, name } from '@wiajs/log';
7
8
  import http from 'node:http';
8
9
  import https from 'node:https';
9
10
  import assert from 'node:assert';
10
11
  import url from 'node:url';
11
- import stream, { Duplex } from 'node:stream';
12
12
  import zlib from 'node:zlib';
13
13
  import mime from 'mime-types';
14
14
 
@@ -464,7 +464,7 @@ const log$1 = log$2({env: `wia:req:${name(import.meta.url)}`}); // __filename
464
464
  * @prop {*} [beforeRedirect]
465
465
  * @prop {boolean} [followRedirects]
466
466
  * @prop {number} [maxRedirects=21]
467
- * @prop {number} [maxBodyLength = 0]
467
+ * @prop {number} [maxBodyLength = -1]
468
468
  * @prop {*} [trackRedirects]
469
469
  * @prop {*} [data]
470
470
  */
@@ -475,7 +475,7 @@ const log$1 = log$2({env: `wia:req:${name(import.meta.url)}`}); // __filename
475
475
  * @prop {number} [responseStartTime]
476
476
  */
477
477
 
478
- /** @typedef { http.IncomingMessage & ResponseExt} Response*/
478
+ /** @typedef { http.IncomingMessage & ResponseExt} Response */
479
479
 
480
480
  const httpModules = {'http:': http, 'https:': https};
481
481
 
@@ -525,12 +525,12 @@ const writeEvents = [
525
525
  'connect',
526
526
  'continue',
527
527
  'drain',
528
- 'error',
528
+ // 'error', // 单独处理,未注册 'error' 事件处理程序,错误将冒泡到全局导致程序崩溃
529
529
  'finish',
530
530
  'information',
531
531
  'pipe',
532
532
  // 'response', 由 processResponse 触发
533
- 'socket',
533
+ 'socket', // 建立连接时触发
534
534
  'timeout',
535
535
  'unpipe',
536
536
  'upgrade',
@@ -542,7 +542,7 @@ for (const ev of writeEvents)
542
542
  writeEventEmit[ev] = /** @param {...any} args */ function (...args) {
543
543
  const m = this; // 事件回调,this === clientRequest 实例
544
544
  // log('req event', {ev})
545
- m.redirectReq.emit(ev, ...args); // req 事情映射到 redirectReq 上触发
545
+ m.redirectReq.emit(ev, ...args); // 内部请求req 事情转发到 Request
546
546
  };
547
547
 
548
548
  // stream.Readable,在响应流上转发读流取事件
@@ -575,6 +575,21 @@ const MaxBodyLengthExceededError = utils.createErrorType(
575
575
 
576
576
  const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', 'write after end');
577
577
 
578
+ // request err
579
+ const HostNotfoundError = utils.createErrorType('ERR_HOSTNOTFOUND', 'DNS 解析失败,主机名可能无效');
580
+ const ConnRefusedError = utils.createErrorType(
581
+ 'ERR_CONNREFUSED',
582
+ '连接被拒绝,目标服务器可能不可用'
583
+ );
584
+ const ConnTimedoutError = utils.createErrorType(
585
+ 'ERR_CONNTIMEDOUT',
586
+ '请求超时,请检查网络连接或服务器负载'
587
+ );
588
+ const ConnResetError = utils.createErrorType(
589
+ 'ERR_CONNRESET',
590
+ '连接被重置,可能是网络问题或服务器关闭了连接'
591
+ );
592
+
578
593
  /**
579
594
  * An HTTP(S) request that can be redirected
580
595
  * wrap http.ClientRequest
@@ -774,7 +789,39 @@ class Request extends Duplex {
774
789
  // 启动 startTimer
775
790
  if (m.startTimer) m._currentRequest.once('socket', m.startTimer);
776
791
 
777
- // 接收req事件,转发 redirectReq 发射
792
+ // set tcp keep alive to prevent drop connection by peer
793
+ req.on(
794
+ 'socket',
795
+ /** @param {*} socket */ socket => {
796
+ // default interval of sending ack packet is 1 minute
797
+ socket.setKeepAlive(true, 1000 * 60);
798
+ }
799
+ );
800
+
801
+ // 请求error单独处理
802
+ // 'error' 事件处理,避免错误将冒泡到全局导致程序崩溃
803
+ req.on('error', err => {
804
+ destroyRequest(req); // 释放资源
805
+ log$1.error({errcode: err.code}, 'request');
806
+ switch (err.code) {
807
+ case 'ENOTFOUND':
808
+ m.emit('error', new HostNotfoundError());
809
+ break
810
+ case 'ECONNREFUSED':
811
+ m.emit('error', new ConnRefusedError());
812
+ break
813
+ case 'ETIMEDOUT':
814
+ m.emit('error', new ConnTimedoutError());
815
+ break
816
+ case 'ECONNRESET':
817
+ m.emit('error', new ConnResetError());
818
+ break
819
+ default:
820
+ m.emit('error', utils.createErrorType('ERR_CONNOTHER', `网络错误: ${err.message}`));
821
+ }
822
+ });
823
+
824
+ // 接收req事件,转发 到 request 上发射,网络关闭事件,触发 error
778
825
  for (const ev of writeEvents) req.on(ev, writeEventEmit[ev]);
779
826
 
780
827
  // RFC7230§5.3.1: When making a request directly to an origin server, […]
@@ -823,9 +870,11 @@ class Request extends Duplex {
823
870
  return R
824
871
  }
825
872
 
873
+ /**
874
+ * 写入错误,释放请求,触发 abort 终止事件
875
+ */
826
876
  abort() {
827
877
  destroyRequest(this._currentRequest);
828
- this._currentRequest.abort();
829
878
  this.emit('abort');
830
879
  }
831
880
 
@@ -889,7 +938,11 @@ class Request extends Duplex {
889
938
  // log({data: chunk, encoding, cb}, 'write')
890
939
 
891
940
  // Writing is not allowed if end has been called
892
- if (m._ending) throw new WriteAfterEndError()
941
+ if (m._ending) {
942
+ // throw new WriteAfterEndError()
943
+ m.emit('error', new WriteAfterEndError());
944
+ return
945
+ }
893
946
 
894
947
  // ! 数据写入时连接,pipe 时可设置 header
895
948
  if (!m._currentRequest) m.request();
@@ -1084,6 +1137,7 @@ class Request extends Duplex {
1084
1137
  m.on('error', clearTimer);
1085
1138
  m.on('response', clearTimer);
1086
1139
  m.on('close', clearTimer);
1140
+
1087
1141
  return m
1088
1142
  }
1089
1143
 
@@ -1274,14 +1328,15 @@ class Request extends Duplex {
1274
1328
  /**
1275
1329
  * 处理响应stream
1276
1330
  * 自动解压,透传流,需设置 decompress = false,避免解压数据
1277
- * @param {*} res
1331
+ * @param {Response} res
1332
+ * @returns {Response | stream.Readable}
1278
1333
  */
1279
1334
  processStream(res) {
1280
1335
  const m = this;
1281
1336
  const {opt} = m;
1282
1337
 
1283
1338
  const streams = [res];
1284
-
1339
+ let responseStream = res;
1285
1340
  // 'transfer-encoding': 'chunked'时,无content-length,axios v1.2 不能自动解压
1286
1341
  const responseLength = +res.headers['content-length'];
1287
1342
 
@@ -1314,6 +1369,7 @@ class Request extends Duplex {
1314
1369
  case 'compress':
1315
1370
  case 'x-compress':
1316
1371
  // add the unzipper to the body stream processing pipeline
1372
+ // @ts-ignore
1317
1373
  streams.push(zlib.createUnzip(zlibOptions));
1318
1374
 
1319
1375
  // remove the content-encoding in order to not confuse downstream operations
@@ -1321,9 +1377,11 @@ class Request extends Duplex {
1321
1377
  break
1322
1378
 
1323
1379
  case 'deflate':
1380
+ // @ts-ignore
1324
1381
  streams.push(new ZlibTransform());
1325
1382
 
1326
1383
  // add the unzipper to the body stream processing pipeline
1384
+ // @ts-ignore
1327
1385
  streams.push(zlib.createUnzip(zlibOptions));
1328
1386
 
1329
1387
  // remove the content-encoding in order to not confuse downstream operations
@@ -1332,6 +1390,7 @@ class Request extends Duplex {
1332
1390
 
1333
1391
  case 'br':
1334
1392
  if (isBrotliSupported) {
1393
+ // @ts-ignore
1335
1394
  streams.push(zlib.createBrotliDecompress(brotliOptions));
1336
1395
  res.headers['content-encoding'] = undefined;
1337
1396
  }
@@ -1340,10 +1399,13 @@ class Request extends Duplex {
1340
1399
  }
1341
1400
 
1342
1401
  // 响应流,用于读
1343
- const responseStream = streams.length > 1 ? stream.pipeline(streams, utils.noop) : streams[0];
1402
+ // @ts-ignore
1403
+ responseStream = streams.length > 1 ? stream.pipeline(streams, utils.noop) : streams[0];
1344
1404
  // 将内部 responseStream 可读流 映射到 redirectReq
1345
1405
 
1406
+ // @ts-ignore
1346
1407
  m.responseStream = responseStream;
1408
+ // @ts-ignore
1347
1409
  responseStream.redirectReq = m; // 事情触发时引用
1348
1410
 
1349
1411
  // stream 模式,事件透传到 请求类
@@ -1515,7 +1577,9 @@ class Request extends Duplex {
1515
1577
  }
1516
1578
 
1517
1579
  /**
1518
- *
1580
+ * 释放请求,触发error事件
1581
+ * 'error' event, and emit a 'close' event.
1582
+ * Calling this will cause remaining data in the response to be dropped and the socket to be destroyed.
1519
1583
  * @param {*} request
1520
1584
  * @param {*} error
1521
1585
  */
@@ -1524,7 +1588,7 @@ function destroyRequest(request, error) {
1524
1588
  request.removeListener(ev, writeEventEmit[ev]);
1525
1589
  }
1526
1590
  request.on('error', utils.noop);
1527
- request.destroy(error);
1591
+ request.destroy(error); // 触发 error 事件
1528
1592
  }
1529
1593
 
1530
1594
  /**
@@ -1566,9 +1630,35 @@ function isSubdomain(subdomain, domain) {
1566
1630
  * 代理模式下,http or https 请求,取决于 proxy 代理服务器,而不是目的服务器。
1567
1631
  */
1568
1632
 
1569
-
1570
1633
  const log = log$2({env: `wia:req:${name(import.meta.url)}`}); // __filename
1571
1634
 
1635
+ /** @typedef { import('./request').Response} Response */
1636
+
1637
+ /**
1638
+ * @typedef {object} Opts
1639
+ * @prop {Object.<string,string>} [headers]
1640
+ * @prop {string} [url]
1641
+ * @prop {'http:' | 'https:'} [protocol]
1642
+ * @prop {string} [host]
1643
+ * @prop {string} [family]
1644
+ * @prop {string} [path]
1645
+ * @prop {string} [method]
1646
+ * @prop {*} [agent] - 发送请求的agent
1647
+ * @prop {*} [agents] - http、https agent,根据协议自动选择
1648
+ * @prop {*} [body] - body 数据,优先body,其次data
1649
+ * @prop {*} [data] - body 数据
1650
+ * @prop {boolean} [stream] - 以流的方式工作
1651
+ * @prop {boolean} [decompress=true] - 自动解压
1652
+ * @prop {*} [transformStream]
1653
+ * @prop {*} [beforeRedirect]
1654
+ * @prop {boolean} [followRedirects] - 自动完成重定向
1655
+ * @prop {number} [maxRedirects=21] - 最大重定向次数
1656
+ * @prop {number} [maxBodyLength = 0] - body限制,缺省不限
1657
+ * @prop {*} [trackRedirects]
1658
+ */
1659
+
1660
+ /** @typedef {(res: Response, stream?: stream.Readable) => void} Cb*/
1661
+
1572
1662
  utils.createErrorType(
1573
1663
  'ERR_STREAM_WRITE_BEEN_ABORTED',
1574
1664
  'Request stream has been aborted'
@@ -1593,10 +1683,10 @@ utils.createErrorType(
1593
1683
 
1594
1684
  /**
1595
1685
  * 初始化参数
1596
- * @param {*} uri/opts
1597
- * @param {*} opts/cb
1598
- * @param {*} cb/null
1599
- * @returns
1686
+ * @param {string | Opts} uri/opts
1687
+ * @param {Opts | Cb} [opts] /cb
1688
+ * @param {Cb} [cb]
1689
+ * @returns {{opts: Opts, cb: Cb}}
1600
1690
  */
1601
1691
  function init(uri, opts, cb) {
1602
1692
  let R;
@@ -1605,39 +1695,55 @@ function init(uri, opts, cb) {
1605
1695
  if (utils.isURL(uri)) uri = utils.spreadUrlObject(uri);
1606
1696
  else if (utils.isString(uri)) uri = utils.spreadUrlObject(utils.parseUrl(uri));
1607
1697
  else {
1698
+ // @ts-ignore
1608
1699
  cb = opts;
1700
+ // @ts-ignore
1609
1701
  opts = uri;
1702
+ // @ts-ignore
1610
1703
  const {url} = opts;
1704
+ // 有url,解析
1611
1705
  if (url) {
1706
+ // @ts-ignore
1707
+ // biome-ignore lint/performance/noDelete: <explanation>
1612
1708
  delete opts.url;
1613
1709
  if (utils.isURL(url)) uri = utils.spreadUrlObject(url);
1614
1710
  else if (utils.isString(url)) uri = utils.spreadUrlObject(utils.parseUrl(url));
1615
1711
  } else {
1616
- opts = utils.validateUrl(uri);
1712
+ // @ts-ignore
1713
+ opts = uri; // 不判断 utils.validateUrl(uri)
1617
1714
  uri = {};
1618
1715
  }
1619
1716
  }
1620
1717
 
1621
1718
  if (utils.isFunction(opts)) {
1719
+ // @ts-ignore
1622
1720
  cb = opts;
1623
- opts = null;
1721
+ opts = {};
1624
1722
  }
1625
1723
 
1626
1724
  // copy options
1627
1725
  opts = {
1726
+ // @ts-ignore
1628
1727
  ...uri,
1629
1728
  ...opts,
1630
1729
  };
1631
1730
 
1731
+ // @ts-ignore
1632
1732
  if (!utils.isString(opts.host) && !utils.isString(opts.hostname)) opts.hostname = '::1';
1733
+ // @ts-ignore
1633
1734
  if (opts.method) opts.method = opts.method.toUpperCase();
1634
1735
 
1635
- R = {opts: opts, cb: cb};
1736
+ // @ts-ignore
1737
+ // follow-redirects does not skip comparison, so it should always succeed for axios -1 unlimited
1738
+ opts.maxBodyLength = opts.maxBodyLength ?? Number.POSITIVE_INFINITY;
1739
+
1740
+ R = {opts, cb};
1636
1741
  // log({R}, 'init')
1637
1742
  } catch (e) {
1638
1743
  log.err(e, 'init');
1639
1744
  }
1640
1745
 
1746
+ // @ts-ignore
1641
1747
  return R
1642
1748
  }
1643
1749
 
@@ -1648,19 +1754,26 @@ function init(uri, opts, cb) {
1648
1754
  * 注意变参 (options[, callback]) or (url[, options][, callback])
1649
1755
  maxRedirects: _.maxRedirects,
1650
1756
  maxBodyLength: _.maxBodyLength,
1651
- * @param {*} uri/options
1652
- * @param {*} options/callback
1653
- * @param {*} callback/null
1654
- * @returns
1757
+ * @param {string | Opts} uri /options
1758
+ * @param {Opts | Cb} [options] /callback
1759
+ * @param {Cb} [callback] /null
1760
+ * @returns {Request}
1655
1761
  */
1656
1762
  function request(uri, options, callback) {
1657
1763
  let R = null;
1658
1764
 
1659
1765
  try {
1766
+ // @ts-ignore
1660
1767
  const {opts, cb} = init(uri, options, callback);
1661
- // log({uri, options, opts}, 'request')
1662
- const req = new Request(opts, cb);
1768
+ // log.error({uri, options, opts}, 'request')
1769
+
1663
1770
  const {data, stream} = opts;
1771
+ // data 在本函数完成处理,不传递到 request
1772
+ opts.data = undefined;
1773
+
1774
+ // @ts-ignore
1775
+ const req = new Request(opts, cb);
1776
+
1664
1777
  // 非流模式,自动发送请求,流模式通过流写入发送
1665
1778
  if (!stream) {
1666
1779
  // 发送数据
@@ -1687,8 +1800,12 @@ function request(uri, options, callback) {
1687
1800
  }
1688
1801
  });
1689
1802
 
1803
+ // log.error({data}, 'request data.pipe')
1690
1804
  data.pipe(req); // 写入数据流
1691
- } else req.end(data);
1805
+ } else {
1806
+ // log.error({data}, 'request req.end')
1807
+ req.end(data); // 写入数据
1808
+ }
1692
1809
  }
1693
1810
 
1694
1811
  R = req;
@@ -1705,40 +1822,23 @@ function request(uri, options, callback) {
1705
1822
  * 复杂数据,请使用 @wiajs/req库(fork from axios),该库封装了当前库,提供了更多功能
1706
1823
  * organize params for patch, post, put, head, del
1707
1824
  * @param {string} verb
1708
- * @returns {Request} Duplex
1825
+ * @returns {(url: string | Opts, opts?: Opts | Cb, cb?: Cb) => void}}
1709
1826
  */
1710
1827
  function fn(verb) {
1711
1828
  const method = verb.toUpperCase();
1712
-
1713
- // @ts-ignore
1714
- return (uri, options, callback) => {
1715
- const {opts, cb} = init(uri, options, callback);
1829
+ /**
1830
+ *
1831
+ * @param {string | Opts} uri /options
1832
+ * @param {Opts | Cb} [opts] /callback
1833
+ * @param {Cb} [cb] /null
1834
+ * @returns
1835
+ */
1836
+ function fn(uri, opts, cb) {
1837
+ // @ts-ignore
1716
1838
  opts.method = method;
1717
- const req = new Request(opts, cb);
1718
- const {data, stream} = opts;
1719
- // 非流模式,自动发送请求,流模式通过流写入发送
1720
- if (!stream) {
1721
- // 发送数据
1722
- if (utils.isStream(data)) {
1723
-
1724
- data.on('end', () => {
1725
- });
1726
-
1727
- data.once(
1728
- 'error',
1729
- /** @param {*} err */ err => {
1730
- // req.destroy(err)
1731
- }
1732
- );
1733
-
1734
- data.on('close', () => {
1735
- });
1736
-
1737
- data.pipe(req); // 写入数据流
1738
- } else req.end(data);
1739
- }
1740
- return req
1839
+ return request(uri, opts, cb)
1741
1840
  }
1841
+ return fn
1742
1842
  }
1743
1843
 
1744
1844
  // define like this to please codeintel/intellisense IDEs
package/lib/index.js CHANGED
@@ -3,14 +3,36 @@
3
3
  * used by axios
4
4
  * 修改以支持http、https 代理服务器
5
5
  * 代理模式下,http or https 请求,取决于 proxy 代理服务器,而不是目的服务器。
6
- */ import { log as Log, name } from '@wiajs/log';
6
+ */ import stream from 'node:stream';
7
+ import { log as Log, name } from '@wiajs/log';
7
8
  import Request from './request.js';
8
9
  import utils from './utils.js';
9
10
  const log = Log({
10
11
  env: `wia:req:${name(import.meta.url)}`
11
12
  }) // __filename
12
13
  ;
13
- const WritebBeenAbortedError = utils.createErrorType('ERR_STREAM_WRITE_BEEN_ABORTED', 'Request stream has been aborted');
14
+ /** @typedef { import('./request').Response} Response */ /**
15
+ * @typedef {object} Opts
16
+ * @prop {Object.<string,string>} [headers]
17
+ * @prop {string} [url]
18
+ * @prop {'http:' | 'https:'} [protocol]
19
+ * @prop {string} [host]
20
+ * @prop {string} [family]
21
+ * @prop {string} [path]
22
+ * @prop {string} [method]
23
+ * @prop {*} [agent] - 发送请求的agent
24
+ * @prop {*} [agents] - http、https agent,根据协议自动选择
25
+ * @prop {*} [body] - body 数据,优先body,其次data
26
+ * @prop {*} [data] - body 数据
27
+ * @prop {boolean} [stream] - 以流的方式工作
28
+ * @prop {boolean} [decompress=true] - 自动解压
29
+ * @prop {*} [transformStream]
30
+ * @prop {*} [beforeRedirect]
31
+ * @prop {boolean} [followRedirects] - 自动完成重定向
32
+ * @prop {number} [maxRedirects=21] - 最大重定向次数
33
+ * @prop {number} [maxBodyLength = 0] - body限制,缺省不限
34
+ * @prop {*} [trackRedirects]
35
+ */ /** @typedef {(res: Response, stream?: stream.Readable) => void} Cb*/ const WritebBeenAbortedError = utils.createErrorType('ERR_STREAM_WRITE_BEEN_ABORTED', 'Request stream has been aborted');
14
36
  (function detectUnsupportedEnvironment() {
15
37
  const looksLikeNode = typeof process !== 'undefined';
16
38
  const looksLikeBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
@@ -25,10 +47,10 @@ const WritebBeenAbortedError = utils.createErrorType('ERR_STREAM_WRITE_BEEN_ABOR
25
47
  * 支持隧道及非隧道、http(s)代理
26
48
  */ /**
27
49
  * 初始化参数
28
- * @param {*} uri/opts
29
- * @param {*} opts/cb
30
- * @param {*} cb/null
31
- * @returns
50
+ * @param {string | Opts} uri/opts
51
+ * @param {Opts | Cb} [opts] /cb
52
+ * @param {Cb} [cb]
53
+ * @returns {{opts: Opts, cb: Cb}}
32
54
  */ function init(uri, opts, cb) {
33
55
  let R;
34
56
  try {
@@ -36,37 +58,53 @@ const WritebBeenAbortedError = utils.createErrorType('ERR_STREAM_WRITE_BEEN_ABOR
36
58
  if (utils.isURL(uri)) uri = utils.spreadUrlObject(uri);
37
59
  else if (utils.isString(uri)) uri = utils.spreadUrlObject(utils.parseUrl(uri));
38
60
  else {
61
+ // @ts-ignore
39
62
  cb = opts;
63
+ // @ts-ignore
40
64
  opts = uri;
65
+ // @ts-ignore
41
66
  const { url } = opts;
67
+ // 有url,解析
42
68
  if (url) {
69
+ // @ts-ignore
70
+ // biome-ignore lint/performance/noDelete: <explanation>
43
71
  delete opts.url;
44
72
  if (utils.isURL(url)) uri = utils.spreadUrlObject(url);
45
73
  else if (utils.isString(url)) uri = utils.spreadUrlObject(utils.parseUrl(url));
46
74
  } else {
47
- opts = utils.validateUrl(uri);
75
+ // @ts-ignore
76
+ opts = uri // 不判断 utils.validateUrl(uri)
77
+ ;
48
78
  uri = {};
49
79
  }
50
80
  }
51
81
  if (utils.isFunction(opts)) {
82
+ // @ts-ignore
52
83
  cb = opts;
53
- opts = null;
84
+ opts = {};
54
85
  }
55
86
  // copy options
56
87
  opts = {
88
+ // @ts-ignore
57
89
  ...uri,
58
90
  ...opts
59
91
  };
92
+ // @ts-ignore
60
93
  if (!utils.isString(opts.host) && !utils.isString(opts.hostname)) opts.hostname = '::1';
94
+ // @ts-ignore
61
95
  if (opts.method) opts.method = opts.method.toUpperCase();
96
+ // @ts-ignore
97
+ // follow-redirects does not skip comparison, so it should always succeed for axios -1 unlimited
98
+ opts.maxBodyLength = opts.maxBodyLength ?? Number.POSITIVE_INFINITY;
62
99
  R = {
63
- opts: opts,
64
- cb: cb
100
+ opts,
101
+ cb
65
102
  };
66
103
  // log({R}, 'init')
67
104
  } catch (e) {
68
105
  log.err(e, 'init');
69
106
  }
107
+ // @ts-ignore
70
108
  return R;
71
109
  }
72
110
  /**
@@ -76,17 +114,21 @@ const WritebBeenAbortedError = utils.createErrorType('ERR_STREAM_WRITE_BEEN_ABOR
76
114
  * 注意变参 (options[, callback]) or (url[, options][, callback])
77
115
  maxRedirects: _.maxRedirects,
78
116
  maxBodyLength: _.maxBodyLength,
79
- * @param {*} uri/options
80
- * @param {*} options/callback
81
- * @param {*} callback/null
82
- * @returns
117
+ * @param {string | Opts} uri /options
118
+ * @param {Opts | Cb} [options] /callback
119
+ * @param {Cb} [callback] /null
120
+ * @returns {Request}
83
121
  */ function request(uri, options, callback) {
84
122
  let R = null;
85
123
  try {
124
+ // @ts-ignore
86
125
  const { opts, cb } = init(uri, options, callback);
87
- // log({uri, options, opts}, 'request')
88
- const req = new Request(opts, cb);
126
+ // log.error({uri, options, opts}, 'request')
89
127
  const { data, stream } = opts;
128
+ // data 在本函数完成处理,不传递到 request
129
+ opts.data = undefined;
130
+ // @ts-ignore
131
+ const req = new Request(opts, cb);
90
132
  // 非流模式,自动发送请求,流模式通过流写入发送
91
133
  if (!stream) {
92
134
  // 发送数据
@@ -106,9 +148,14 @@ const WritebBeenAbortedError = utils.createErrorType('ERR_STREAM_WRITE_BEEN_ABOR
106
148
  // throw new WritebBeenAbortedError()
107
149
  }
108
150
  });
151
+ // log.error({data}, 'request data.pipe')
109
152
  data.pipe(req) // 写入数据流
110
153
  ;
111
- } else req.end(data);
154
+ } else {
155
+ // log.error({data}, 'request req.end')
156
+ req.end(data) // 写入数据
157
+ ;
158
+ }
112
159
  }
113
160
  R = req;
114
161
  } catch (e) {
@@ -122,40 +169,21 @@ const WritebBeenAbortedError = utils.createErrorType('ERR_STREAM_WRITE_BEEN_ABOR
122
169
  * 复杂数据,请使用 @wiajs/req库(fork from axios),该库封装了当前库,提供了更多功能
123
170
  * organize params for patch, post, put, head, del
124
171
  * @param {string} verb
125
- * @returns {Request} Duplex
172
+ * @returns {(url: string | Opts, opts?: Opts | Cb, cb?: Cb) => void}}
126
173
  */ function fn(verb) {
127
174
  const method = verb.toUpperCase();
128
- // @ts-ignore
129
- return (uri, options, callback)=>{
130
- const { opts, cb } = init(uri, options, callback);
175
+ /**
176
+ *
177
+ * @param {string | Opts} uri /options
178
+ * @param {Opts | Cb} [opts] /callback
179
+ * @param {Cb} [cb] /null
180
+ * @returns
181
+ */ function fn(uri, opts, cb) {
182
+ // @ts-ignore
131
183
  opts.method = method;
132
- const req = new Request(opts, cb);
133
- const { data, stream } = opts;
134
- // 非流模式,自动发送请求,流模式通过流写入发送
135
- if (!stream) {
136
- // 发送数据
137
- if (utils.isStream(data)) {
138
- // Send the request
139
- let ended = false;
140
- let errored = false;
141
- data.on('end', ()=>{
142
- ended = true;
143
- });
144
- data.once('error', /** @param {*} err */ (err)=>{
145
- errored = true;
146
- // req.destroy(err)
147
- });
148
- data.on('close', ()=>{
149
- if (!ended && !errored) {
150
- // throw new WritebBeenAbortedError()
151
- }
152
- });
153
- data.pipe(req) // 写入数据流
154
- ;
155
- } else req.end(data);
156
- }
157
- return req;
158
- };
184
+ return request(uri, opts, cb);
185
+ }
186
+ return fn;
159
187
  }
160
188
  // define like this to please codeintel/intellisense IDEs
161
189
  request.get = fn('get');