@wiajs/request 3.0.29 → 3.0.31
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.cjs +166 -60
- package/dist/request.mjs +166 -60
- package/lib/index.js +81 -49
- package/lib/request.js +66 -12
- package/package.json +1 -1
- package/types/index.d.ts +35 -9
- package/types/request.d.ts +4 -2
- package/types/utils.d.ts +2 -0
package/dist/request.cjs
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* wia request v3.0.
|
|
2
|
+
* wia request v3.0.31
|
|
3
3
|
* (c) 2022-2024 Sibyl Yu and contributors
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
|
+
const stream = require('node:stream');
|
|
8
9
|
const log$2 = require('@wiajs/log');
|
|
9
10
|
const http = require('node:http');
|
|
10
11
|
const https = require('node:https');
|
|
11
12
|
const assert = require('node:assert');
|
|
12
13
|
const url = require('node:url');
|
|
13
|
-
const stream = require('node:stream');
|
|
14
14
|
const zlib = require('node:zlib');
|
|
15
15
|
const mime = require('mime-types');
|
|
16
16
|
|
|
@@ -467,7 +467,7 @@ const log$1 = log$2.log({env: `wia:req:${log$2.name((typeof document === 'undefi
|
|
|
467
467
|
* @prop {*} [beforeRedirect]
|
|
468
468
|
* @prop {boolean} [followRedirects]
|
|
469
469
|
* @prop {number} [maxRedirects=21]
|
|
470
|
-
* @prop {number} [maxBodyLength =
|
|
470
|
+
* @prop {number} [maxBodyLength = -1]
|
|
471
471
|
* @prop {*} [trackRedirects]
|
|
472
472
|
* @prop {*} [data]
|
|
473
473
|
*/
|
|
@@ -478,7 +478,7 @@ const log$1 = log$2.log({env: `wia:req:${log$2.name((typeof document === 'undefi
|
|
|
478
478
|
* @prop {number} [responseStartTime]
|
|
479
479
|
*/
|
|
480
480
|
|
|
481
|
-
/** @typedef { http.IncomingMessage & ResponseExt} Response*/
|
|
481
|
+
/** @typedef { http.IncomingMessage & ResponseExt} Response */
|
|
482
482
|
|
|
483
483
|
const httpModules = {'http:': http, 'https:': https};
|
|
484
484
|
|
|
@@ -528,12 +528,12 @@ const writeEvents = [
|
|
|
528
528
|
'connect',
|
|
529
529
|
'continue',
|
|
530
530
|
'drain',
|
|
531
|
-
'error',
|
|
531
|
+
// 'error', // 单独处理,未注册 'error' 事件处理程序,错误将冒泡到全局导致程序崩溃
|
|
532
532
|
'finish',
|
|
533
533
|
'information',
|
|
534
534
|
'pipe',
|
|
535
535
|
// 'response', 由 processResponse 触发
|
|
536
|
-
'socket',
|
|
536
|
+
'socket', // 建立连接时触发
|
|
537
537
|
'timeout',
|
|
538
538
|
'unpipe',
|
|
539
539
|
'upgrade',
|
|
@@ -545,7 +545,7 @@ for (const ev of writeEvents)
|
|
|
545
545
|
writeEventEmit[ev] = /** @param {...any} args */ function (...args) {
|
|
546
546
|
const m = this; // 事件回调,this === clientRequest 实例
|
|
547
547
|
// log('req event', {ev})
|
|
548
|
-
m.redirectReq.emit(ev, ...args); // req
|
|
548
|
+
m.redirectReq.emit(ev, ...args); // 内部请求req 事情转发到 Request
|
|
549
549
|
};
|
|
550
550
|
|
|
551
551
|
// stream.Readable,在响应流上转发读流取事件
|
|
@@ -578,6 +578,21 @@ const MaxBodyLengthExceededError = utils.createErrorType(
|
|
|
578
578
|
|
|
579
579
|
const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', 'write after end');
|
|
580
580
|
|
|
581
|
+
// request err
|
|
582
|
+
const HostNotfoundError = utils.createErrorType('ERR_HOSTNOTFOUND', 'DNS 解析失败,主机名可能无效');
|
|
583
|
+
const ConnRefusedError = utils.createErrorType(
|
|
584
|
+
'ERR_CONNREFUSED',
|
|
585
|
+
'连接被拒绝,目标服务器可能不可用'
|
|
586
|
+
);
|
|
587
|
+
const ConnTimedoutError = utils.createErrorType(
|
|
588
|
+
'ERR_CONNTIMEDOUT',
|
|
589
|
+
'请求超时,请检查网络连接或服务器负载'
|
|
590
|
+
);
|
|
591
|
+
const ConnResetError = utils.createErrorType(
|
|
592
|
+
'ERR_CONNRESET',
|
|
593
|
+
'连接被重置,可能是网络问题或服务器关闭了连接'
|
|
594
|
+
);
|
|
595
|
+
|
|
581
596
|
/**
|
|
582
597
|
* An HTTP(S) request that can be redirected
|
|
583
598
|
* wrap http.ClientRequest
|
|
@@ -777,7 +792,41 @@ class Request extends stream.Duplex {
|
|
|
777
792
|
// 启动 startTimer
|
|
778
793
|
if (m.startTimer) m._currentRequest.once('socket', m.startTimer);
|
|
779
794
|
|
|
780
|
-
//
|
|
795
|
+
// set tcp keep alive to prevent drop connection by peer
|
|
796
|
+
req.on(
|
|
797
|
+
'socket',
|
|
798
|
+
/** @param {*} socket */ socket => {
|
|
799
|
+
// default interval of sending ack packet is 1 minute
|
|
800
|
+
socket.setKeepAlive(true, 1000 * 60);
|
|
801
|
+
}
|
|
802
|
+
);
|
|
803
|
+
|
|
804
|
+
// 请求error单独处理
|
|
805
|
+
// 'error' 事件处理,避免错误将冒泡到全局导致程序崩溃
|
|
806
|
+
req.on('error', err => {
|
|
807
|
+
destroyRequest(req); // 释放资源
|
|
808
|
+
// @ts-ignore
|
|
809
|
+
log$1.error({errcode: err?.code}, 'request');
|
|
810
|
+
// @ts-ignore
|
|
811
|
+
switch (err?.code) {
|
|
812
|
+
case 'ENOTFOUND':
|
|
813
|
+
m.emit('error', new HostNotfoundError());
|
|
814
|
+
break
|
|
815
|
+
case 'ECONNREFUSED':
|
|
816
|
+
m.emit('error', new ConnRefusedError());
|
|
817
|
+
break
|
|
818
|
+
case 'ETIMEDOUT':
|
|
819
|
+
m.emit('error', new ConnTimedoutError());
|
|
820
|
+
break
|
|
821
|
+
case 'ECONNRESET':
|
|
822
|
+
m.emit('error', new ConnResetError());
|
|
823
|
+
break
|
|
824
|
+
default:
|
|
825
|
+
m.emit('error', utils.createErrorType('ERR_CONNOTHER', `网络错误: ${err.message}`));
|
|
826
|
+
}
|
|
827
|
+
});
|
|
828
|
+
|
|
829
|
+
// 接收req事件,转发 到 request 上发射,网络关闭事件,触发 error
|
|
781
830
|
for (const ev of writeEvents) req.on(ev, writeEventEmit[ev]);
|
|
782
831
|
|
|
783
832
|
// RFC7230§5.3.1: When making a request directly to an origin server, […]
|
|
@@ -826,9 +875,11 @@ class Request extends stream.Duplex {
|
|
|
826
875
|
return R
|
|
827
876
|
}
|
|
828
877
|
|
|
878
|
+
/**
|
|
879
|
+
* 写入错误,释放请求,触发 abort 终止事件
|
|
880
|
+
*/
|
|
829
881
|
abort() {
|
|
830
882
|
destroyRequest(this._currentRequest);
|
|
831
|
-
this._currentRequest.abort();
|
|
832
883
|
this.emit('abort');
|
|
833
884
|
}
|
|
834
885
|
|
|
@@ -892,7 +943,11 @@ class Request extends stream.Duplex {
|
|
|
892
943
|
// log({data: chunk, encoding, cb}, 'write')
|
|
893
944
|
|
|
894
945
|
// Writing is not allowed if end has been called
|
|
895
|
-
if (m._ending)
|
|
946
|
+
if (m._ending) {
|
|
947
|
+
// throw new WriteAfterEndError()
|
|
948
|
+
m.emit('error', new WriteAfterEndError());
|
|
949
|
+
return
|
|
950
|
+
}
|
|
896
951
|
|
|
897
952
|
// ! 数据写入时连接,pipe 时可设置 header
|
|
898
953
|
if (!m._currentRequest) m.request();
|
|
@@ -1087,6 +1142,7 @@ class Request extends stream.Duplex {
|
|
|
1087
1142
|
m.on('error', clearTimer);
|
|
1088
1143
|
m.on('response', clearTimer);
|
|
1089
1144
|
m.on('close', clearTimer);
|
|
1145
|
+
|
|
1090
1146
|
return m
|
|
1091
1147
|
}
|
|
1092
1148
|
|
|
@@ -1277,14 +1333,15 @@ class Request extends stream.Duplex {
|
|
|
1277
1333
|
/**
|
|
1278
1334
|
* 处理响应stream
|
|
1279
1335
|
* 自动解压,透传流,需设置 decompress = false,避免解压数据
|
|
1280
|
-
* @param {
|
|
1336
|
+
* @param {Response} res
|
|
1337
|
+
* @returns {Response | stream.Readable}
|
|
1281
1338
|
*/
|
|
1282
1339
|
processStream(res) {
|
|
1283
1340
|
const m = this;
|
|
1284
1341
|
const {opt} = m;
|
|
1285
1342
|
|
|
1286
1343
|
const streams = [res];
|
|
1287
|
-
|
|
1344
|
+
let responseStream = res;
|
|
1288
1345
|
// 'transfer-encoding': 'chunked'时,无content-length,axios v1.2 不能自动解压
|
|
1289
1346
|
const responseLength = +res.headers['content-length'];
|
|
1290
1347
|
|
|
@@ -1317,6 +1374,7 @@ class Request extends stream.Duplex {
|
|
|
1317
1374
|
case 'compress':
|
|
1318
1375
|
case 'x-compress':
|
|
1319
1376
|
// add the unzipper to the body stream processing pipeline
|
|
1377
|
+
// @ts-ignore
|
|
1320
1378
|
streams.push(zlib.createUnzip(zlibOptions));
|
|
1321
1379
|
|
|
1322
1380
|
// remove the content-encoding in order to not confuse downstream operations
|
|
@@ -1324,9 +1382,11 @@ class Request extends stream.Duplex {
|
|
|
1324
1382
|
break
|
|
1325
1383
|
|
|
1326
1384
|
case 'deflate':
|
|
1385
|
+
// @ts-ignore
|
|
1327
1386
|
streams.push(new ZlibTransform());
|
|
1328
1387
|
|
|
1329
1388
|
// add the unzipper to the body stream processing pipeline
|
|
1389
|
+
// @ts-ignore
|
|
1330
1390
|
streams.push(zlib.createUnzip(zlibOptions));
|
|
1331
1391
|
|
|
1332
1392
|
// remove the content-encoding in order to not confuse downstream operations
|
|
@@ -1335,6 +1395,7 @@ class Request extends stream.Duplex {
|
|
|
1335
1395
|
|
|
1336
1396
|
case 'br':
|
|
1337
1397
|
if (isBrotliSupported) {
|
|
1398
|
+
// @ts-ignore
|
|
1338
1399
|
streams.push(zlib.createBrotliDecompress(brotliOptions));
|
|
1339
1400
|
res.headers['content-encoding'] = undefined;
|
|
1340
1401
|
}
|
|
@@ -1343,10 +1404,13 @@ class Request extends stream.Duplex {
|
|
|
1343
1404
|
}
|
|
1344
1405
|
|
|
1345
1406
|
// 响应流,用于读
|
|
1346
|
-
|
|
1407
|
+
// @ts-ignore
|
|
1408
|
+
responseStream = streams.length > 1 ? stream.pipeline(streams, utils.noop) : streams[0];
|
|
1347
1409
|
// 将内部 responseStream 可读流 映射到 redirectReq
|
|
1348
1410
|
|
|
1411
|
+
// @ts-ignore
|
|
1349
1412
|
m.responseStream = responseStream;
|
|
1413
|
+
// @ts-ignore
|
|
1350
1414
|
responseStream.redirectReq = m; // 事情触发时引用
|
|
1351
1415
|
|
|
1352
1416
|
// stream 模式,事件透传到 请求类
|
|
@@ -1518,7 +1582,9 @@ class Request extends stream.Duplex {
|
|
|
1518
1582
|
}
|
|
1519
1583
|
|
|
1520
1584
|
/**
|
|
1521
|
-
*
|
|
1585
|
+
* 释放请求,触发error事件
|
|
1586
|
+
* 'error' event, and emit a 'close' event.
|
|
1587
|
+
* Calling this will cause remaining data in the response to be dropped and the socket to be destroyed.
|
|
1522
1588
|
* @param {*} request
|
|
1523
1589
|
* @param {*} error
|
|
1524
1590
|
*/
|
|
@@ -1527,7 +1593,7 @@ function destroyRequest(request, error) {
|
|
|
1527
1593
|
request.removeListener(ev, writeEventEmit[ev]);
|
|
1528
1594
|
}
|
|
1529
1595
|
request.on('error', utils.noop);
|
|
1530
|
-
request.destroy(error);
|
|
1596
|
+
request.destroy(error); // 触发 error 事件
|
|
1531
1597
|
}
|
|
1532
1598
|
|
|
1533
1599
|
/**
|
|
@@ -1569,9 +1635,35 @@ function isSubdomain(subdomain, domain) {
|
|
|
1569
1635
|
* 代理模式下,http or https 请求,取决于 proxy 代理服务器,而不是目的服务器。
|
|
1570
1636
|
*/
|
|
1571
1637
|
|
|
1572
|
-
|
|
1573
1638
|
const log = log$2.log({env: `wia:req:${log$2.name((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('request.cjs', document.baseURI).href)))}`}); // __filename
|
|
1574
1639
|
|
|
1640
|
+
/** @typedef { import('./request').Response} Response */
|
|
1641
|
+
|
|
1642
|
+
/**
|
|
1643
|
+
* @typedef {object} Opts
|
|
1644
|
+
* @prop {Object.<string,string>} [headers]
|
|
1645
|
+
* @prop {string} [url]
|
|
1646
|
+
* @prop {'http:' | 'https:'} [protocol]
|
|
1647
|
+
* @prop {string} [host]
|
|
1648
|
+
* @prop {string} [family]
|
|
1649
|
+
* @prop {string} [path]
|
|
1650
|
+
* @prop {string} [method]
|
|
1651
|
+
* @prop {*} [agent] - 发送请求的agent
|
|
1652
|
+
* @prop {*} [agents] - http、https agent,根据协议自动选择
|
|
1653
|
+
* @prop {*} [body] - body 数据,优先body,其次data
|
|
1654
|
+
* @prop {*} [data] - body 数据
|
|
1655
|
+
* @prop {boolean} [stream] - 以流的方式工作
|
|
1656
|
+
* @prop {boolean} [decompress=true] - 自动解压
|
|
1657
|
+
* @prop {*} [transformStream]
|
|
1658
|
+
* @prop {*} [beforeRedirect]
|
|
1659
|
+
* @prop {boolean} [followRedirects] - 自动完成重定向
|
|
1660
|
+
* @prop {number} [maxRedirects=21] - 最大重定向次数
|
|
1661
|
+
* @prop {number} [maxBodyLength = 0] - body限制,缺省不限
|
|
1662
|
+
* @prop {*} [trackRedirects]
|
|
1663
|
+
*/
|
|
1664
|
+
|
|
1665
|
+
/** @typedef {(res: Response, stream?: stream.Readable) => void} Cb*/
|
|
1666
|
+
|
|
1575
1667
|
utils.createErrorType(
|
|
1576
1668
|
'ERR_STREAM_WRITE_BEEN_ABORTED',
|
|
1577
1669
|
'Request stream has been aborted'
|
|
@@ -1584,7 +1676,7 @@ utils.createErrorType(
|
|
|
1584
1676
|
const looksLikeBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
|
|
1585
1677
|
const looksLikeV8 = utils.isFunction(Error.captureStackTrace);
|
|
1586
1678
|
if (!looksLikeNode && (looksLikeBrowser || !looksLikeV8)) {
|
|
1587
|
-
|
|
1679
|
+
log.warn('The follow-redirects package should be excluded from browser builds.');
|
|
1588
1680
|
}
|
|
1589
1681
|
})();
|
|
1590
1682
|
|
|
@@ -1596,10 +1688,10 @@ utils.createErrorType(
|
|
|
1596
1688
|
|
|
1597
1689
|
/**
|
|
1598
1690
|
* 初始化参数
|
|
1599
|
-
* @param {
|
|
1600
|
-
* @param {
|
|
1601
|
-
* @param {
|
|
1602
|
-
* @returns
|
|
1691
|
+
* @param {string | Opts} uri/opts
|
|
1692
|
+
* @param {Opts | Cb} [opts] /cb
|
|
1693
|
+
* @param {Cb} [cb]
|
|
1694
|
+
* @returns {{opts: Opts, cb: Cb}}
|
|
1603
1695
|
*/
|
|
1604
1696
|
function init(uri, opts, cb) {
|
|
1605
1697
|
let R;
|
|
@@ -1608,39 +1700,59 @@ function init(uri, opts, cb) {
|
|
|
1608
1700
|
if (utils.isURL(uri)) uri = utils.spreadUrlObject(uri);
|
|
1609
1701
|
else if (utils.isString(uri)) uri = utils.spreadUrlObject(utils.parseUrl(uri));
|
|
1610
1702
|
else {
|
|
1703
|
+
// @ts-ignore
|
|
1611
1704
|
cb = opts;
|
|
1705
|
+
// @ts-ignore
|
|
1612
1706
|
opts = uri;
|
|
1707
|
+
// @ts-ignore
|
|
1613
1708
|
const {url} = opts;
|
|
1709
|
+
// 有url,解析
|
|
1614
1710
|
if (url) {
|
|
1711
|
+
// @ts-ignore
|
|
1712
|
+
// biome-ignore lint/performance/noDelete: <explanation>
|
|
1615
1713
|
delete opts.url;
|
|
1616
1714
|
if (utils.isURL(url)) uri = utils.spreadUrlObject(url);
|
|
1617
1715
|
else if (utils.isString(url)) uri = utils.spreadUrlObject(utils.parseUrl(url));
|
|
1618
1716
|
} else {
|
|
1619
|
-
|
|
1717
|
+
// @ts-ignore
|
|
1718
|
+
opts = uri; // 不判断 utils.validateUrl(uri)
|
|
1620
1719
|
uri = {};
|
|
1621
1720
|
}
|
|
1622
1721
|
}
|
|
1623
1722
|
|
|
1624
1723
|
if (utils.isFunction(opts)) {
|
|
1724
|
+
// @ts-ignore
|
|
1625
1725
|
cb = opts;
|
|
1626
|
-
opts =
|
|
1726
|
+
opts = {};
|
|
1627
1727
|
}
|
|
1628
1728
|
|
|
1629
1729
|
// copy options
|
|
1630
1730
|
opts = {
|
|
1731
|
+
// @ts-ignore
|
|
1631
1732
|
...uri,
|
|
1632
1733
|
...opts,
|
|
1633
1734
|
};
|
|
1634
1735
|
|
|
1736
|
+
// @ts-ignore
|
|
1635
1737
|
if (!utils.isString(opts.host) && !utils.isString(opts.hostname)) opts.hostname = '::1';
|
|
1738
|
+
// @ts-ignore
|
|
1636
1739
|
if (opts.method) opts.method = opts.method.toUpperCase();
|
|
1637
1740
|
|
|
1638
|
-
|
|
1741
|
+
// @ts-ignore
|
|
1742
|
+
// follow-redirects does not skip comparison, so it should always succeed for axios -1 unlimited
|
|
1743
|
+
opts.maxBodyLength = opts.maxBodyLength ?? Number.POSITIVE_INFINITY;
|
|
1744
|
+
// @ts-ignore
|
|
1745
|
+
opts.maxRedirects = opts.maxRedirects ?? 21;
|
|
1746
|
+
// @ts-ignore
|
|
1747
|
+
if (opts.maxRedirects === 0) opts.followRedirects = false;
|
|
1748
|
+
|
|
1749
|
+
R = {opts, cb};
|
|
1639
1750
|
// log({R}, 'init')
|
|
1640
1751
|
} catch (e) {
|
|
1641
1752
|
log.err(e, 'init');
|
|
1642
1753
|
}
|
|
1643
1754
|
|
|
1755
|
+
// @ts-ignore
|
|
1644
1756
|
return R
|
|
1645
1757
|
}
|
|
1646
1758
|
|
|
@@ -1651,19 +1763,26 @@ function init(uri, opts, cb) {
|
|
|
1651
1763
|
* 注意变参 (options[, callback]) or (url[, options][, callback])
|
|
1652
1764
|
maxRedirects: _.maxRedirects,
|
|
1653
1765
|
maxBodyLength: _.maxBodyLength,
|
|
1654
|
-
* @param {
|
|
1655
|
-
* @param {
|
|
1656
|
-
* @param {
|
|
1657
|
-
* @returns
|
|
1766
|
+
* @param {string | Opts} uri /options
|
|
1767
|
+
* @param {Opts | Cb} [options] /callback
|
|
1768
|
+
* @param {Cb} [callback] /null
|
|
1769
|
+
* @returns {Request}
|
|
1658
1770
|
*/
|
|
1659
1771
|
function request(uri, options, callback) {
|
|
1660
1772
|
let R = null;
|
|
1661
1773
|
|
|
1662
1774
|
try {
|
|
1775
|
+
// @ts-ignore
|
|
1663
1776
|
const {opts, cb} = init(uri, options, callback);
|
|
1664
|
-
// log({uri, options, opts}, 'request')
|
|
1665
|
-
|
|
1777
|
+
// log.error({uri, options, opts}, 'request')
|
|
1778
|
+
|
|
1666
1779
|
const {data, stream} = opts;
|
|
1780
|
+
// data 在本函数完成处理,不传递到 request
|
|
1781
|
+
opts.data = undefined;
|
|
1782
|
+
|
|
1783
|
+
// @ts-ignore
|
|
1784
|
+
const req = new Request(opts, cb);
|
|
1785
|
+
|
|
1667
1786
|
// 非流模式,自动发送请求,流模式通过流写入发送
|
|
1668
1787
|
if (!stream) {
|
|
1669
1788
|
// 发送数据
|
|
@@ -1690,8 +1809,12 @@ function request(uri, options, callback) {
|
|
|
1690
1809
|
}
|
|
1691
1810
|
});
|
|
1692
1811
|
|
|
1812
|
+
// log.error({data}, 'request data.pipe')
|
|
1693
1813
|
data.pipe(req); // 写入数据流
|
|
1694
|
-
} else
|
|
1814
|
+
} else {
|
|
1815
|
+
// log.error({data}, 'request req.end')
|
|
1816
|
+
req.end(data); // 写入数据
|
|
1817
|
+
}
|
|
1695
1818
|
}
|
|
1696
1819
|
|
|
1697
1820
|
R = req;
|
|
@@ -1708,40 +1831,23 @@ function request(uri, options, callback) {
|
|
|
1708
1831
|
* 复杂数据,请使用 @wiajs/req库(fork from axios),该库封装了当前库,提供了更多功能
|
|
1709
1832
|
* organize params for patch, post, put, head, del
|
|
1710
1833
|
* @param {string} verb
|
|
1711
|
-
* @returns {
|
|
1834
|
+
* @returns {(url: string | Opts, opts?: Opts | Cb, cb?: Cb) => void}}
|
|
1712
1835
|
*/
|
|
1713
1836
|
function fn(verb) {
|
|
1714
1837
|
const method = verb.toUpperCase();
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1838
|
+
/**
|
|
1839
|
+
*
|
|
1840
|
+
* @param {string | Opts} uri /options
|
|
1841
|
+
* @param {Opts | Cb} [opts] /callback
|
|
1842
|
+
* @param {Cb} [cb] /null
|
|
1843
|
+
* @returns
|
|
1844
|
+
*/
|
|
1845
|
+
function fn(uri, opts, cb) {
|
|
1846
|
+
// @ts-ignore
|
|
1719
1847
|
opts.method = method;
|
|
1720
|
-
|
|
1721
|
-
const {data, stream} = opts;
|
|
1722
|
-
// 非流模式,自动发送请求,流模式通过流写入发送
|
|
1723
|
-
if (!stream) {
|
|
1724
|
-
// 发送数据
|
|
1725
|
-
if (utils.isStream(data)) {
|
|
1726
|
-
|
|
1727
|
-
data.on('end', () => {
|
|
1728
|
-
});
|
|
1729
|
-
|
|
1730
|
-
data.once(
|
|
1731
|
-
'error',
|
|
1732
|
-
/** @param {*} err */ err => {
|
|
1733
|
-
// req.destroy(err)
|
|
1734
|
-
}
|
|
1735
|
-
);
|
|
1736
|
-
|
|
1737
|
-
data.on('close', () => {
|
|
1738
|
-
});
|
|
1739
|
-
|
|
1740
|
-
data.pipe(req); // 写入数据流
|
|
1741
|
-
} else req.end(data);
|
|
1742
|
-
}
|
|
1743
|
-
return req
|
|
1848
|
+
return request(uri, opts, cb)
|
|
1744
1849
|
}
|
|
1850
|
+
return fn
|
|
1745
1851
|
}
|
|
1746
1852
|
|
|
1747
1853
|
// define like this to please codeintel/intellisense IDEs
|