@wiajs/request 3.0.28 → 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.cjs +160 -59
- package/dist/request.mjs +160 -59
- package/lib/index.js +77 -48
- package/lib/request.js +64 -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.30
|
|
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,39 @@ 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
|
+
log$1.error({errcode: err.code}, 'request');
|
|
809
|
+
switch (err.code) {
|
|
810
|
+
case 'ENOTFOUND':
|
|
811
|
+
m.emit('error', new HostNotfoundError());
|
|
812
|
+
break
|
|
813
|
+
case 'ECONNREFUSED':
|
|
814
|
+
m.emit('error', new ConnRefusedError());
|
|
815
|
+
break
|
|
816
|
+
case 'ETIMEDOUT':
|
|
817
|
+
m.emit('error', new ConnTimedoutError());
|
|
818
|
+
break
|
|
819
|
+
case 'ECONNRESET':
|
|
820
|
+
m.emit('error', new ConnResetError());
|
|
821
|
+
break
|
|
822
|
+
default:
|
|
823
|
+
m.emit('error', utils.createErrorType('ERR_CONNOTHER', `网络错误: ${err.message}`));
|
|
824
|
+
}
|
|
825
|
+
});
|
|
826
|
+
|
|
827
|
+
// 接收req事件,转发 到 request 上发射,网络关闭事件,触发 error
|
|
781
828
|
for (const ev of writeEvents) req.on(ev, writeEventEmit[ev]);
|
|
782
829
|
|
|
783
830
|
// RFC7230§5.3.1: When making a request directly to an origin server, […]
|
|
@@ -826,9 +873,11 @@ class Request extends stream.Duplex {
|
|
|
826
873
|
return R
|
|
827
874
|
}
|
|
828
875
|
|
|
876
|
+
/**
|
|
877
|
+
* 写入错误,释放请求,触发 abort 终止事件
|
|
878
|
+
*/
|
|
829
879
|
abort() {
|
|
830
880
|
destroyRequest(this._currentRequest);
|
|
831
|
-
this._currentRequest.abort();
|
|
832
881
|
this.emit('abort');
|
|
833
882
|
}
|
|
834
883
|
|
|
@@ -892,7 +941,11 @@ class Request extends stream.Duplex {
|
|
|
892
941
|
// log({data: chunk, encoding, cb}, 'write')
|
|
893
942
|
|
|
894
943
|
// Writing is not allowed if end has been called
|
|
895
|
-
if (m._ending)
|
|
944
|
+
if (m._ending) {
|
|
945
|
+
// throw new WriteAfterEndError()
|
|
946
|
+
m.emit('error', new WriteAfterEndError());
|
|
947
|
+
return
|
|
948
|
+
}
|
|
896
949
|
|
|
897
950
|
// ! 数据写入时连接,pipe 时可设置 header
|
|
898
951
|
if (!m._currentRequest) m.request();
|
|
@@ -1087,6 +1140,7 @@ class Request extends stream.Duplex {
|
|
|
1087
1140
|
m.on('error', clearTimer);
|
|
1088
1141
|
m.on('response', clearTimer);
|
|
1089
1142
|
m.on('close', clearTimer);
|
|
1143
|
+
|
|
1090
1144
|
return m
|
|
1091
1145
|
}
|
|
1092
1146
|
|
|
@@ -1277,14 +1331,15 @@ class Request extends stream.Duplex {
|
|
|
1277
1331
|
/**
|
|
1278
1332
|
* 处理响应stream
|
|
1279
1333
|
* 自动解压,透传流,需设置 decompress = false,避免解压数据
|
|
1280
|
-
* @param {
|
|
1334
|
+
* @param {Response} res
|
|
1335
|
+
* @returns {Response | stream.Readable}
|
|
1281
1336
|
*/
|
|
1282
1337
|
processStream(res) {
|
|
1283
1338
|
const m = this;
|
|
1284
1339
|
const {opt} = m;
|
|
1285
1340
|
|
|
1286
1341
|
const streams = [res];
|
|
1287
|
-
|
|
1342
|
+
let responseStream = res;
|
|
1288
1343
|
// 'transfer-encoding': 'chunked'时,无content-length,axios v1.2 不能自动解压
|
|
1289
1344
|
const responseLength = +res.headers['content-length'];
|
|
1290
1345
|
|
|
@@ -1317,6 +1372,7 @@ class Request extends stream.Duplex {
|
|
|
1317
1372
|
case 'compress':
|
|
1318
1373
|
case 'x-compress':
|
|
1319
1374
|
// add the unzipper to the body stream processing pipeline
|
|
1375
|
+
// @ts-ignore
|
|
1320
1376
|
streams.push(zlib.createUnzip(zlibOptions));
|
|
1321
1377
|
|
|
1322
1378
|
// remove the content-encoding in order to not confuse downstream operations
|
|
@@ -1324,9 +1380,11 @@ class Request extends stream.Duplex {
|
|
|
1324
1380
|
break
|
|
1325
1381
|
|
|
1326
1382
|
case 'deflate':
|
|
1383
|
+
// @ts-ignore
|
|
1327
1384
|
streams.push(new ZlibTransform());
|
|
1328
1385
|
|
|
1329
1386
|
// add the unzipper to the body stream processing pipeline
|
|
1387
|
+
// @ts-ignore
|
|
1330
1388
|
streams.push(zlib.createUnzip(zlibOptions));
|
|
1331
1389
|
|
|
1332
1390
|
// remove the content-encoding in order to not confuse downstream operations
|
|
@@ -1335,6 +1393,7 @@ class Request extends stream.Duplex {
|
|
|
1335
1393
|
|
|
1336
1394
|
case 'br':
|
|
1337
1395
|
if (isBrotliSupported) {
|
|
1396
|
+
// @ts-ignore
|
|
1338
1397
|
streams.push(zlib.createBrotliDecompress(brotliOptions));
|
|
1339
1398
|
res.headers['content-encoding'] = undefined;
|
|
1340
1399
|
}
|
|
@@ -1343,10 +1402,13 @@ class Request extends stream.Duplex {
|
|
|
1343
1402
|
}
|
|
1344
1403
|
|
|
1345
1404
|
// 响应流,用于读
|
|
1346
|
-
|
|
1405
|
+
// @ts-ignore
|
|
1406
|
+
responseStream = streams.length > 1 ? stream.pipeline(streams, utils.noop) : streams[0];
|
|
1347
1407
|
// 将内部 responseStream 可读流 映射到 redirectReq
|
|
1348
1408
|
|
|
1409
|
+
// @ts-ignore
|
|
1349
1410
|
m.responseStream = responseStream;
|
|
1411
|
+
// @ts-ignore
|
|
1350
1412
|
responseStream.redirectReq = m; // 事情触发时引用
|
|
1351
1413
|
|
|
1352
1414
|
// stream 模式,事件透传到 请求类
|
|
@@ -1518,7 +1580,9 @@ class Request extends stream.Duplex {
|
|
|
1518
1580
|
}
|
|
1519
1581
|
|
|
1520
1582
|
/**
|
|
1521
|
-
*
|
|
1583
|
+
* 释放请求,触发error事件
|
|
1584
|
+
* 'error' event, and emit a 'close' event.
|
|
1585
|
+
* Calling this will cause remaining data in the response to be dropped and the socket to be destroyed.
|
|
1522
1586
|
* @param {*} request
|
|
1523
1587
|
* @param {*} error
|
|
1524
1588
|
*/
|
|
@@ -1527,7 +1591,7 @@ function destroyRequest(request, error) {
|
|
|
1527
1591
|
request.removeListener(ev, writeEventEmit[ev]);
|
|
1528
1592
|
}
|
|
1529
1593
|
request.on('error', utils.noop);
|
|
1530
|
-
request.destroy(error);
|
|
1594
|
+
request.destroy(error); // 触发 error 事件
|
|
1531
1595
|
}
|
|
1532
1596
|
|
|
1533
1597
|
/**
|
|
@@ -1569,9 +1633,35 @@ function isSubdomain(subdomain, domain) {
|
|
|
1569
1633
|
* 代理模式下,http or https 请求,取决于 proxy 代理服务器,而不是目的服务器。
|
|
1570
1634
|
*/
|
|
1571
1635
|
|
|
1572
|
-
|
|
1573
1636
|
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
1637
|
|
|
1638
|
+
/** @typedef { import('./request').Response} Response */
|
|
1639
|
+
|
|
1640
|
+
/**
|
|
1641
|
+
* @typedef {object} Opts
|
|
1642
|
+
* @prop {Object.<string,string>} [headers]
|
|
1643
|
+
* @prop {string} [url]
|
|
1644
|
+
* @prop {'http:' | 'https:'} [protocol]
|
|
1645
|
+
* @prop {string} [host]
|
|
1646
|
+
* @prop {string} [family]
|
|
1647
|
+
* @prop {string} [path]
|
|
1648
|
+
* @prop {string} [method]
|
|
1649
|
+
* @prop {*} [agent] - 发送请求的agent
|
|
1650
|
+
* @prop {*} [agents] - http、https agent,根据协议自动选择
|
|
1651
|
+
* @prop {*} [body] - body 数据,优先body,其次data
|
|
1652
|
+
* @prop {*} [data] - body 数据
|
|
1653
|
+
* @prop {boolean} [stream] - 以流的方式工作
|
|
1654
|
+
* @prop {boolean} [decompress=true] - 自动解压
|
|
1655
|
+
* @prop {*} [transformStream]
|
|
1656
|
+
* @prop {*} [beforeRedirect]
|
|
1657
|
+
* @prop {boolean} [followRedirects] - 自动完成重定向
|
|
1658
|
+
* @prop {number} [maxRedirects=21] - 最大重定向次数
|
|
1659
|
+
* @prop {number} [maxBodyLength = 0] - body限制,缺省不限
|
|
1660
|
+
* @prop {*} [trackRedirects]
|
|
1661
|
+
*/
|
|
1662
|
+
|
|
1663
|
+
/** @typedef {(res: Response, stream?: stream.Readable) => void} Cb*/
|
|
1664
|
+
|
|
1575
1665
|
utils.createErrorType(
|
|
1576
1666
|
'ERR_STREAM_WRITE_BEEN_ABORTED',
|
|
1577
1667
|
'Request stream has been aborted'
|
|
@@ -1596,10 +1686,10 @@ utils.createErrorType(
|
|
|
1596
1686
|
|
|
1597
1687
|
/**
|
|
1598
1688
|
* 初始化参数
|
|
1599
|
-
* @param {
|
|
1600
|
-
* @param {
|
|
1601
|
-
* @param {
|
|
1602
|
-
* @returns
|
|
1689
|
+
* @param {string | Opts} uri/opts
|
|
1690
|
+
* @param {Opts | Cb} [opts] /cb
|
|
1691
|
+
* @param {Cb} [cb]
|
|
1692
|
+
* @returns {{opts: Opts, cb: Cb}}
|
|
1603
1693
|
*/
|
|
1604
1694
|
function init(uri, opts, cb) {
|
|
1605
1695
|
let R;
|
|
@@ -1608,38 +1698,55 @@ function init(uri, opts, cb) {
|
|
|
1608
1698
|
if (utils.isURL(uri)) uri = utils.spreadUrlObject(uri);
|
|
1609
1699
|
else if (utils.isString(uri)) uri = utils.spreadUrlObject(utils.parseUrl(uri));
|
|
1610
1700
|
else {
|
|
1701
|
+
// @ts-ignore
|
|
1611
1702
|
cb = opts;
|
|
1703
|
+
// @ts-ignore
|
|
1612
1704
|
opts = uri;
|
|
1705
|
+
// @ts-ignore
|
|
1613
1706
|
const {url} = opts;
|
|
1707
|
+
// 有url,解析
|
|
1614
1708
|
if (url) {
|
|
1709
|
+
// @ts-ignore
|
|
1710
|
+
// biome-ignore lint/performance/noDelete: <explanation>
|
|
1615
1711
|
delete opts.url;
|
|
1616
1712
|
if (utils.isURL(url)) uri = utils.spreadUrlObject(url);
|
|
1617
1713
|
else if (utils.isString(url)) uri = utils.spreadUrlObject(utils.parseUrl(url));
|
|
1618
1714
|
} else {
|
|
1619
|
-
|
|
1715
|
+
// @ts-ignore
|
|
1716
|
+
opts = uri; // 不判断 utils.validateUrl(uri)
|
|
1620
1717
|
uri = {};
|
|
1621
1718
|
}
|
|
1622
1719
|
}
|
|
1623
1720
|
|
|
1624
1721
|
if (utils.isFunction(opts)) {
|
|
1722
|
+
// @ts-ignore
|
|
1625
1723
|
cb = opts;
|
|
1626
|
-
opts =
|
|
1724
|
+
opts = {};
|
|
1627
1725
|
}
|
|
1628
1726
|
|
|
1629
1727
|
// copy options
|
|
1630
1728
|
opts = {
|
|
1729
|
+
// @ts-ignore
|
|
1631
1730
|
...uri,
|
|
1632
1731
|
...opts,
|
|
1633
1732
|
};
|
|
1634
1733
|
|
|
1734
|
+
// @ts-ignore
|
|
1635
1735
|
if (!utils.isString(opts.host) && !utils.isString(opts.hostname)) opts.hostname = '::1';
|
|
1736
|
+
// @ts-ignore
|
|
1737
|
+
if (opts.method) opts.method = opts.method.toUpperCase();
|
|
1738
|
+
|
|
1739
|
+
// @ts-ignore
|
|
1740
|
+
// follow-redirects does not skip comparison, so it should always succeed for axios -1 unlimited
|
|
1741
|
+
opts.maxBodyLength = opts.maxBodyLength ?? Number.POSITIVE_INFINITY;
|
|
1636
1742
|
|
|
1637
|
-
R = {opts
|
|
1743
|
+
R = {opts, cb};
|
|
1638
1744
|
// log({R}, 'init')
|
|
1639
1745
|
} catch (e) {
|
|
1640
1746
|
log.err(e, 'init');
|
|
1641
1747
|
}
|
|
1642
1748
|
|
|
1749
|
+
// @ts-ignore
|
|
1643
1750
|
return R
|
|
1644
1751
|
}
|
|
1645
1752
|
|
|
@@ -1650,19 +1757,26 @@ function init(uri, opts, cb) {
|
|
|
1650
1757
|
* 注意变参 (options[, callback]) or (url[, options][, callback])
|
|
1651
1758
|
maxRedirects: _.maxRedirects,
|
|
1652
1759
|
maxBodyLength: _.maxBodyLength,
|
|
1653
|
-
* @param {
|
|
1654
|
-
* @param {
|
|
1655
|
-
* @param {
|
|
1656
|
-
* @returns
|
|
1760
|
+
* @param {string | Opts} uri /options
|
|
1761
|
+
* @param {Opts | Cb} [options] /callback
|
|
1762
|
+
* @param {Cb} [callback] /null
|
|
1763
|
+
* @returns {Request}
|
|
1657
1764
|
*/
|
|
1658
1765
|
function request(uri, options, callback) {
|
|
1659
1766
|
let R = null;
|
|
1660
1767
|
|
|
1661
1768
|
try {
|
|
1769
|
+
// @ts-ignore
|
|
1662
1770
|
const {opts, cb} = init(uri, options, callback);
|
|
1663
|
-
// log({uri, options, opts}, 'request')
|
|
1664
|
-
|
|
1771
|
+
// log.error({uri, options, opts}, 'request')
|
|
1772
|
+
|
|
1665
1773
|
const {data, stream} = opts;
|
|
1774
|
+
// data 在本函数完成处理,不传递到 request
|
|
1775
|
+
opts.data = undefined;
|
|
1776
|
+
|
|
1777
|
+
// @ts-ignore
|
|
1778
|
+
const req = new Request(opts, cb);
|
|
1779
|
+
|
|
1666
1780
|
// 非流模式,自动发送请求,流模式通过流写入发送
|
|
1667
1781
|
if (!stream) {
|
|
1668
1782
|
// 发送数据
|
|
@@ -1689,8 +1803,12 @@ function request(uri, options, callback) {
|
|
|
1689
1803
|
}
|
|
1690
1804
|
});
|
|
1691
1805
|
|
|
1806
|
+
// log.error({data}, 'request data.pipe')
|
|
1692
1807
|
data.pipe(req); // 写入数据流
|
|
1693
|
-
} else
|
|
1808
|
+
} else {
|
|
1809
|
+
// log.error({data}, 'request req.end')
|
|
1810
|
+
req.end(data); // 写入数据
|
|
1811
|
+
}
|
|
1694
1812
|
}
|
|
1695
1813
|
|
|
1696
1814
|
R = req;
|
|
@@ -1707,40 +1825,23 @@ function request(uri, options, callback) {
|
|
|
1707
1825
|
* 复杂数据,请使用 @wiajs/req库(fork from axios),该库封装了当前库,提供了更多功能
|
|
1708
1826
|
* organize params for patch, post, put, head, del
|
|
1709
1827
|
* @param {string} verb
|
|
1710
|
-
* @returns {
|
|
1828
|
+
* @returns {(url: string | Opts, opts?: Opts | Cb, cb?: Cb) => void}}
|
|
1711
1829
|
*/
|
|
1712
1830
|
function fn(verb) {
|
|
1713
1831
|
const method = verb.toUpperCase();
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1832
|
+
/**
|
|
1833
|
+
*
|
|
1834
|
+
* @param {string | Opts} uri /options
|
|
1835
|
+
* @param {Opts | Cb} [opts] /callback
|
|
1836
|
+
* @param {Cb} [cb] /null
|
|
1837
|
+
* @returns
|
|
1838
|
+
*/
|
|
1839
|
+
function fn(uri, opts, cb) {
|
|
1840
|
+
// @ts-ignore
|
|
1718
1841
|
opts.method = method;
|
|
1719
|
-
|
|
1720
|
-
const {data, stream} = opts;
|
|
1721
|
-
// 非流模式,自动发送请求,流模式通过流写入发送
|
|
1722
|
-
if (!stream) {
|
|
1723
|
-
// 发送数据
|
|
1724
|
-
if (utils.isStream(data)) {
|
|
1725
|
-
|
|
1726
|
-
data.on('end', () => {
|
|
1727
|
-
});
|
|
1728
|
-
|
|
1729
|
-
data.once(
|
|
1730
|
-
'error',
|
|
1731
|
-
/** @param {*} err */ err => {
|
|
1732
|
-
// req.destroy(err)
|
|
1733
|
-
}
|
|
1734
|
-
);
|
|
1735
|
-
|
|
1736
|
-
data.on('close', () => {
|
|
1737
|
-
});
|
|
1738
|
-
|
|
1739
|
-
data.pipe(req); // 写入数据流
|
|
1740
|
-
} else req.end(data);
|
|
1741
|
-
}
|
|
1742
|
-
return req
|
|
1842
|
+
return request(uri, opts, cb)
|
|
1743
1843
|
}
|
|
1844
|
+
return fn
|
|
1744
1845
|
}
|
|
1745
1846
|
|
|
1746
1847
|
// define like this to please codeintel/intellisense IDEs
|