@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.cjs +159 -59
- package/dist/request.mjs +159 -59
- package/lib/index.js +76 -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,39 +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
|
|
1636
1737
|
if (opts.method) opts.method = opts.method.toUpperCase();
|
|
1637
1738
|
|
|
1638
|
-
|
|
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;
|
|
1742
|
+
|
|
1743
|
+
R = {opts, cb};
|
|
1639
1744
|
// log({R}, 'init')
|
|
1640
1745
|
} catch (e) {
|
|
1641
1746
|
log.err(e, 'init');
|
|
1642
1747
|
}
|
|
1643
1748
|
|
|
1749
|
+
// @ts-ignore
|
|
1644
1750
|
return R
|
|
1645
1751
|
}
|
|
1646
1752
|
|
|
@@ -1651,19 +1757,26 @@ function init(uri, opts, cb) {
|
|
|
1651
1757
|
* 注意变参 (options[, callback]) or (url[, options][, callback])
|
|
1652
1758
|
maxRedirects: _.maxRedirects,
|
|
1653
1759
|
maxBodyLength: _.maxBodyLength,
|
|
1654
|
-
* @param {
|
|
1655
|
-
* @param {
|
|
1656
|
-
* @param {
|
|
1657
|
-
* @returns
|
|
1760
|
+
* @param {string | Opts} uri /options
|
|
1761
|
+
* @param {Opts | Cb} [options] /callback
|
|
1762
|
+
* @param {Cb} [callback] /null
|
|
1763
|
+
* @returns {Request}
|
|
1658
1764
|
*/
|
|
1659
1765
|
function request(uri, options, callback) {
|
|
1660
1766
|
let R = null;
|
|
1661
1767
|
|
|
1662
1768
|
try {
|
|
1769
|
+
// @ts-ignore
|
|
1663
1770
|
const {opts, cb} = init(uri, options, callback);
|
|
1664
|
-
// log({uri, options, opts}, 'request')
|
|
1665
|
-
|
|
1771
|
+
// log.error({uri, options, opts}, 'request')
|
|
1772
|
+
|
|
1666
1773
|
const {data, stream} = opts;
|
|
1774
|
+
// data 在本函数完成处理,不传递到 request
|
|
1775
|
+
opts.data = undefined;
|
|
1776
|
+
|
|
1777
|
+
// @ts-ignore
|
|
1778
|
+
const req = new Request(opts, cb);
|
|
1779
|
+
|
|
1667
1780
|
// 非流模式,自动发送请求,流模式通过流写入发送
|
|
1668
1781
|
if (!stream) {
|
|
1669
1782
|
// 发送数据
|
|
@@ -1690,8 +1803,12 @@ function request(uri, options, callback) {
|
|
|
1690
1803
|
}
|
|
1691
1804
|
});
|
|
1692
1805
|
|
|
1806
|
+
// log.error({data}, 'request data.pipe')
|
|
1693
1807
|
data.pipe(req); // 写入数据流
|
|
1694
|
-
} else
|
|
1808
|
+
} else {
|
|
1809
|
+
// log.error({data}, 'request req.end')
|
|
1810
|
+
req.end(data); // 写入数据
|
|
1811
|
+
}
|
|
1695
1812
|
}
|
|
1696
1813
|
|
|
1697
1814
|
R = req;
|
|
@@ -1708,40 +1825,23 @@ function request(uri, options, callback) {
|
|
|
1708
1825
|
* 复杂数据,请使用 @wiajs/req库(fork from axios),该库封装了当前库,提供了更多功能
|
|
1709
1826
|
* organize params for patch, post, put, head, del
|
|
1710
1827
|
* @param {string} verb
|
|
1711
|
-
* @returns {
|
|
1828
|
+
* @returns {(url: string | Opts, opts?: Opts | Cb, cb?: Cb) => void}}
|
|
1712
1829
|
*/
|
|
1713
1830
|
function fn(verb) {
|
|
1714
1831
|
const method = verb.toUpperCase();
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
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
|
|
1719
1841
|
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
|
|
1842
|
+
return request(uri, opts, cb)
|
|
1744
1843
|
}
|
|
1844
|
+
return fn
|
|
1745
1845
|
}
|
|
1746
1846
|
|
|
1747
1847
|
// define like this to please codeintel/intellisense IDEs
|