@wiajs/request 3.0.20 → 3.0.23
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 +80 -33
- package/dist/request.mjs +79 -32
- package/lib/index.js +29 -3
- package/lib/request.js +22 -34
- package/lib/utils.js +12 -4
- package/package.json +4 -1
package/dist/request.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* wia request v3.0.
|
|
2
|
+
* wia request v3.0.23
|
|
3
3
|
* (c) 2022-2024 Sibyl Yu and contributors
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -92,10 +92,10 @@ const preservedUrlFields = [
|
|
|
92
92
|
* @property {string} message - The error message.
|
|
93
93
|
* @property {Error | undefined} cause - The optional error cause.
|
|
94
94
|
*/
|
|
95
|
-
function createErrorType(code, message, baseClass) {
|
|
95
|
+
function createErrorType(code, message, baseClass) {
|
|
96
96
|
/**
|
|
97
97
|
* Create constructor
|
|
98
|
-
* @param {*} properties
|
|
98
|
+
* @param {*} properties
|
|
99
99
|
*/
|
|
100
100
|
function CustomError(properties) {
|
|
101
101
|
// istanbul ignore else
|
|
@@ -120,7 +120,7 @@ function createErrorType(code, message, baseClass) {
|
|
|
120
120
|
enumerable: false,
|
|
121
121
|
},
|
|
122
122
|
});
|
|
123
|
-
|
|
123
|
+
|
|
124
124
|
// @ts-ignore
|
|
125
125
|
return CustomError
|
|
126
126
|
}
|
|
@@ -221,9 +221,9 @@ function isURL(value) {
|
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
/**
|
|
224
|
-
*
|
|
225
|
-
* @param {*} rs
|
|
226
|
-
* @returns
|
|
224
|
+
*
|
|
225
|
+
* @param {*} rs
|
|
226
|
+
* @returns
|
|
227
227
|
*/
|
|
228
228
|
function isReadStream(rs) {
|
|
229
229
|
return rs.readable && rs.path && rs.mode
|
|
@@ -319,6 +319,15 @@ function noBody(method, code) {
|
|
|
319
319
|
)
|
|
320
320
|
}
|
|
321
321
|
|
|
322
|
+
/**
|
|
323
|
+
* Determine if a value is a Stream
|
|
324
|
+
*
|
|
325
|
+
* @param {*} val The value to test
|
|
326
|
+
*
|
|
327
|
+
* @returns {boolean} True if value is a Stream, otherwise false
|
|
328
|
+
*/
|
|
329
|
+
const isStream = val => isObject(val) && isFunction(val.pipe);
|
|
330
|
+
|
|
322
331
|
const utils = {
|
|
323
332
|
createErrorType,
|
|
324
333
|
InvalidUrlError,
|
|
@@ -332,6 +341,7 @@ const utils = {
|
|
|
332
341
|
isObject,
|
|
333
342
|
isURL,
|
|
334
343
|
isReadStream,
|
|
344
|
+
isStream,
|
|
335
345
|
noop,
|
|
336
346
|
parseUrl,
|
|
337
347
|
spreadUrlObject,
|
|
@@ -439,7 +449,7 @@ class Caseless {
|
|
|
439
449
|
* https://github.com/follow-redirects/follow-redirects
|
|
440
450
|
*/
|
|
441
451
|
|
|
442
|
-
const log$1 = log$2.log({env: `wia:req:${log$2.name((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.src || new URL('request.cjs', document.baseURI).href)))}`}); // __filename
|
|
452
|
+
const log$1 = 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
|
|
443
453
|
|
|
444
454
|
/**
|
|
445
455
|
* @typedef {object} Opts
|
|
@@ -509,7 +519,7 @@ const writeProps = [
|
|
|
509
519
|
const writeMethods = ['cork', 'flushHeaders', 'setNoDelay', 'setSocketKeepAlive'];
|
|
510
520
|
|
|
511
521
|
// Create handlers that pass events from native requests
|
|
512
|
-
// 在 clientRequest
|
|
522
|
+
// 在 clientRequest 事件转发写事件
|
|
513
523
|
const writeEvents = [
|
|
514
524
|
// 'abort', // 弃用
|
|
515
525
|
// 'aborted', // 弃用
|
|
@@ -533,7 +543,7 @@ const writeEventEmit = Object.create(null);
|
|
|
533
543
|
for (const ev of writeEvents)
|
|
534
544
|
writeEventEmit[ev] = /** @param {...any} args */ function (...args) {
|
|
535
545
|
const m = this; // 事件回调,this === clientRequest 实例
|
|
536
|
-
log
|
|
546
|
+
// log('req event', {ev})
|
|
537
547
|
m.redirectReq.emit(ev, ...args); // req 事情映射到 redirectReq 上触发
|
|
538
548
|
};
|
|
539
549
|
|
|
@@ -544,7 +554,7 @@ const readEventEmit = Object.create(null);
|
|
|
544
554
|
for (const ev of readEvents)
|
|
545
555
|
readEventEmit[ev] = /** @param {...any} args */ function (...args) {
|
|
546
556
|
const m = this; // 事件回调,this === clientRequest 实例
|
|
547
|
-
log
|
|
557
|
+
// log('res event', {ev})
|
|
548
558
|
m.redirectReq.emit(ev, ...args); // 向上触发事件
|
|
549
559
|
};
|
|
550
560
|
|
|
@@ -664,14 +674,14 @@ class Request extends stream.Duplex {
|
|
|
664
674
|
get() {
|
|
665
675
|
// @ts-ignore
|
|
666
676
|
const val = m._currentRequest?.[property];
|
|
667
|
-
log
|
|
677
|
+
// log('get property', {property})
|
|
668
678
|
return val
|
|
669
679
|
},
|
|
670
680
|
});
|
|
671
681
|
}
|
|
672
682
|
|
|
683
|
+
// 流模式
|
|
673
684
|
if (opts.stream) {
|
|
674
|
-
// 流模式
|
|
675
685
|
// 被 pipe 作为目标时触发,拷贝 src headers
|
|
676
686
|
m.on(
|
|
677
687
|
'pipe',
|
|
@@ -707,7 +717,7 @@ class Request extends stream.Duplex {
|
|
|
707
717
|
}
|
|
708
718
|
|
|
709
719
|
// Perform the first request
|
|
710
|
-
// m.request(); //
|
|
720
|
+
// m.request(); // 创建时不连接,写入数据时连接,否则 pipe 时无法写入header
|
|
711
721
|
}
|
|
712
722
|
|
|
713
723
|
/**
|
|
@@ -739,6 +749,7 @@ class Request extends stream.Duplex {
|
|
|
739
749
|
// 代理以目的网址协议为准
|
|
740
750
|
// If specified, use the agent corresponding to the protocol
|
|
741
751
|
// (HTTP and HTTPS use different types of agents)
|
|
752
|
+
// agents 优于 agent
|
|
742
753
|
if (agents) {
|
|
743
754
|
const scheme = protocol.slice(0, -1);
|
|
744
755
|
opt.agent = agents[scheme];
|
|
@@ -842,13 +853,13 @@ class Request extends stream.Duplex {
|
|
|
842
853
|
* 如 request 不存在,则创建连接,pipe 时可写入 header
|
|
843
854
|
* @override - 重写父类方法
|
|
844
855
|
* @param {*} chunk - The data chunk to write.
|
|
845
|
-
* @param {BufferEncoding | ((error: Error | null) => void)} [
|
|
856
|
+
* @param {BufferEncoding | ((error: Error | null) => void)} [encoding] - Encoding for string data, or the callback if no encoding is provided.
|
|
846
857
|
* @param {(error: Error | null) => void} [cb] - Callback to signal the end of the write operation.
|
|
847
858
|
* @returns {boolean} True if the write was successful, false otherwise.
|
|
848
859
|
*/
|
|
849
|
-
write(chunk,
|
|
860
|
+
write(chunk, encoding, cb) {
|
|
850
861
|
const m = this;
|
|
851
|
-
log
|
|
862
|
+
// log({data: chunk, encoding, cb}, 'write')
|
|
852
863
|
|
|
853
864
|
// Writing is not allowed if end has been called
|
|
854
865
|
if (m._ending) throw new WriteAfterEndError()
|
|
@@ -860,10 +871,10 @@ class Request extends stream.Duplex {
|
|
|
860
871
|
if (!utils.isString(chunk) && !utils.isBuffer(chunk))
|
|
861
872
|
throw new TypeError('data should be a string, Buffer or Uint8Array')
|
|
862
873
|
|
|
863
|
-
if (utils.isFunction(
|
|
874
|
+
if (utils.isFunction(encoding)) {
|
|
864
875
|
// @ts-ignore
|
|
865
|
-
cb =
|
|
866
|
-
|
|
876
|
+
cb = encoding;
|
|
877
|
+
encoding = null;
|
|
867
878
|
}
|
|
868
879
|
|
|
869
880
|
// Ignore empty buffers, since writing them doesn't invoke the callback
|
|
@@ -876,9 +887,9 @@ class Request extends stream.Duplex {
|
|
|
876
887
|
// Only write when we don't exceed the maximum body length
|
|
877
888
|
if (m._requestBodyLength + chunk.length <= m.opt.maxBodyLength) {
|
|
878
889
|
m._requestBodyLength += chunk.length;
|
|
879
|
-
m._requestBodyBuffers.push({data: chunk, encoding
|
|
890
|
+
m._requestBodyBuffers.push({data: chunk, encoding});
|
|
880
891
|
// @ts-ignore
|
|
881
|
-
m._currentRequest.write(chunk,
|
|
892
|
+
m._currentRequest.write(chunk, encoding, cb);
|
|
882
893
|
}
|
|
883
894
|
// Error when we exceed the maximum body length
|
|
884
895
|
else {
|
|
@@ -909,7 +920,7 @@ class Request extends stream.Duplex {
|
|
|
909
920
|
encoding = null;
|
|
910
921
|
}
|
|
911
922
|
|
|
912
|
-
// !
|
|
923
|
+
// ! 创建实例时不连接,数据写入时发起连接,连接后无法设置 header,因此 pipe 时可设置 header
|
|
913
924
|
if (!m._currentRequest) m.request();
|
|
914
925
|
|
|
915
926
|
// Write data if needed and end
|
|
@@ -1109,7 +1120,7 @@ class Request extends stream.Duplex {
|
|
|
1109
1120
|
// If the response is not a redirect; return it as-is
|
|
1110
1121
|
const {location} = response.headers;
|
|
1111
1122
|
|
|
1112
|
-
log
|
|
1123
|
+
// log({statusCode, headers: response.headers}, 'processResponse')
|
|
1113
1124
|
|
|
1114
1125
|
if (!location || opt.followRedirects === false || statusCode < 300 || statusCode >= 400) {
|
|
1115
1126
|
// 非重定向,返回给原始回调处理
|
|
@@ -1245,11 +1256,11 @@ class Request extends stream.Duplex {
|
|
|
1245
1256
|
// 'transfer-encoding': 'chunked'时,无content-length,axios v1.2 不能自动解压
|
|
1246
1257
|
const responseLength = +res.headers['content-length'];
|
|
1247
1258
|
|
|
1248
|
-
log
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
})
|
|
1259
|
+
// log('processStream', {
|
|
1260
|
+
// statusCode: res.statusCode,
|
|
1261
|
+
// responseLength,
|
|
1262
|
+
// headers: res.headers,
|
|
1263
|
+
// })
|
|
1253
1264
|
|
|
1254
1265
|
if (opt.transformStream) {
|
|
1255
1266
|
opt.transformStream.responseLength = responseLength;
|
|
@@ -1521,12 +1532,18 @@ function isSubdomain(subdomain, domain) {
|
|
|
1521
1532
|
|
|
1522
1533
|
/**
|
|
1523
1534
|
* from 'https://github.com/follow-redirects/follow-redirects'
|
|
1535
|
+
* used by axios
|
|
1524
1536
|
* 修改以支持http、https 代理服务器
|
|
1525
1537
|
* 代理模式下,http or https 请求,取决于 proxy 代理服务器,而不是目的服务器。
|
|
1526
1538
|
*/
|
|
1527
1539
|
|
|
1528
1540
|
|
|
1529
|
-
const log = log$2.log({env: `wia:req:${log$2.name((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.src || new URL('request.cjs', document.baseURI).href)))}`}) // __filename
|
|
1541
|
+
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
|
|
1542
|
+
|
|
1543
|
+
const WritebBeenAbortedError = utils.createErrorType(
|
|
1544
|
+
'ERR_STREAM_WRITE_BEEN_ABORTED',
|
|
1545
|
+
'Request stream has been aborted'
|
|
1546
|
+
)
|
|
1530
1547
|
|
|
1531
1548
|
// Preventive platform detection
|
|
1532
1549
|
// istanbul ignore
|
|
@@ -1589,6 +1606,7 @@ function init(uri, options, callback) {
|
|
|
1589
1606
|
/**
|
|
1590
1607
|
* Executes a request, following redirects
|
|
1591
1608
|
* 替换原 http(s).request,参数类似
|
|
1609
|
+
* 需外部调用 end() data.pipe 或stream管道写入数据
|
|
1592
1610
|
* 注意变参 (options[, callback]) or (url[, options][, callback])
|
|
1593
1611
|
maxRedirects: _.maxRedirects,
|
|
1594
1612
|
maxBodyLength: _.maxBodyLength,
|
|
@@ -1612,7 +1630,8 @@ function request(uri, options, callback) {
|
|
|
1612
1630
|
}
|
|
1613
1631
|
|
|
1614
1632
|
/**
|
|
1615
|
-
*
|
|
1633
|
+
* 执行简单的数据(支持strean)请求
|
|
1634
|
+
* 非流模式,直接写入数据流,流模式,由管道触发,或手动调用 end() data.pipe 写入数据
|
|
1616
1635
|
* 复杂数据,请使用 @wiajs/req库(fork from axios),该库封装了当前库,提供了更多功能
|
|
1617
1636
|
* organize params for patch, post, put, head, del
|
|
1618
1637
|
* @param {string} verb
|
|
@@ -1626,7 +1645,35 @@ function fn(verb) {
|
|
|
1626
1645
|
const {opts, cb} = init(uri, options, callback);
|
|
1627
1646
|
opts.method = method;
|
|
1628
1647
|
const req = new Request(opts, cb);
|
|
1629
|
-
|
|
1648
|
+
const {data, stream} = opts;
|
|
1649
|
+
if (!stream) {
|
|
1650
|
+
// 发送数据
|
|
1651
|
+
if (utils.isStream(data)) {
|
|
1652
|
+
// Send the request
|
|
1653
|
+
let ended = false;
|
|
1654
|
+
let errored = false;
|
|
1655
|
+
|
|
1656
|
+
data.on('end', () => {
|
|
1657
|
+
ended = true;
|
|
1658
|
+
});
|
|
1659
|
+
|
|
1660
|
+
data.once(
|
|
1661
|
+
'error',
|
|
1662
|
+
/** @param {*} err */ err => {
|
|
1663
|
+
errored = true;
|
|
1664
|
+
req.destroy(err);
|
|
1665
|
+
}
|
|
1666
|
+
);
|
|
1667
|
+
|
|
1668
|
+
data.on('close', () => {
|
|
1669
|
+
if (!ended && !errored) {
|
|
1670
|
+
throw new WritebBeenAbortedError()
|
|
1671
|
+
}
|
|
1672
|
+
});
|
|
1673
|
+
|
|
1674
|
+
data.pipe(req); // 写入数据流
|
|
1675
|
+
} else req.end(data);
|
|
1676
|
+
}
|
|
1630
1677
|
return req
|
|
1631
1678
|
}
|
|
1632
1679
|
}
|
|
@@ -1639,6 +1686,6 @@ request.post = fn('post');
|
|
|
1639
1686
|
request.put = fn('put');
|
|
1640
1687
|
request.patch = fn('patch');
|
|
1641
1688
|
request.del = fn('delete');
|
|
1642
|
-
request
|
|
1689
|
+
request.delete = fn('delete');
|
|
1643
1690
|
|
|
1644
1691
|
module.exports = request;
|
package/dist/request.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* wia request v3.0.
|
|
2
|
+
* wia request v3.0.23
|
|
3
3
|
* (c) 2022-2024 Sibyl Yu and contributors
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -89,10 +89,10 @@ const preservedUrlFields = [
|
|
|
89
89
|
* @property {string} message - The error message.
|
|
90
90
|
* @property {Error | undefined} cause - The optional error cause.
|
|
91
91
|
*/
|
|
92
|
-
function createErrorType(code, message, baseClass) {
|
|
92
|
+
function createErrorType(code, message, baseClass) {
|
|
93
93
|
/**
|
|
94
94
|
* Create constructor
|
|
95
|
-
* @param {*} properties
|
|
95
|
+
* @param {*} properties
|
|
96
96
|
*/
|
|
97
97
|
function CustomError(properties) {
|
|
98
98
|
// istanbul ignore else
|
|
@@ -117,7 +117,7 @@ function createErrorType(code, message, baseClass) {
|
|
|
117
117
|
enumerable: false,
|
|
118
118
|
},
|
|
119
119
|
});
|
|
120
|
-
|
|
120
|
+
|
|
121
121
|
// @ts-ignore
|
|
122
122
|
return CustomError
|
|
123
123
|
}
|
|
@@ -218,9 +218,9 @@ function isURL(value) {
|
|
|
218
218
|
}
|
|
219
219
|
|
|
220
220
|
/**
|
|
221
|
-
*
|
|
222
|
-
* @param {*} rs
|
|
223
|
-
* @returns
|
|
221
|
+
*
|
|
222
|
+
* @param {*} rs
|
|
223
|
+
* @returns
|
|
224
224
|
*/
|
|
225
225
|
function isReadStream(rs) {
|
|
226
226
|
return rs.readable && rs.path && rs.mode
|
|
@@ -316,6 +316,15 @@ function noBody(method, code) {
|
|
|
316
316
|
)
|
|
317
317
|
}
|
|
318
318
|
|
|
319
|
+
/**
|
|
320
|
+
* Determine if a value is a Stream
|
|
321
|
+
*
|
|
322
|
+
* @param {*} val The value to test
|
|
323
|
+
*
|
|
324
|
+
* @returns {boolean} True if value is a Stream, otherwise false
|
|
325
|
+
*/
|
|
326
|
+
const isStream = val => isObject(val) && isFunction(val.pipe);
|
|
327
|
+
|
|
319
328
|
const utils = {
|
|
320
329
|
createErrorType,
|
|
321
330
|
InvalidUrlError,
|
|
@@ -329,6 +338,7 @@ const utils = {
|
|
|
329
338
|
isObject,
|
|
330
339
|
isURL,
|
|
331
340
|
isReadStream,
|
|
341
|
+
isStream,
|
|
332
342
|
noop,
|
|
333
343
|
parseUrl,
|
|
334
344
|
spreadUrlObject,
|
|
@@ -506,7 +516,7 @@ const writeProps = [
|
|
|
506
516
|
const writeMethods = ['cork', 'flushHeaders', 'setNoDelay', 'setSocketKeepAlive'];
|
|
507
517
|
|
|
508
518
|
// Create handlers that pass events from native requests
|
|
509
|
-
// 在 clientRequest
|
|
519
|
+
// 在 clientRequest 事件转发写事件
|
|
510
520
|
const writeEvents = [
|
|
511
521
|
// 'abort', // 弃用
|
|
512
522
|
// 'aborted', // 弃用
|
|
@@ -530,7 +540,7 @@ const writeEventEmit = Object.create(null);
|
|
|
530
540
|
for (const ev of writeEvents)
|
|
531
541
|
writeEventEmit[ev] = /** @param {...any} args */ function (...args) {
|
|
532
542
|
const m = this; // 事件回调,this === clientRequest 实例
|
|
533
|
-
log
|
|
543
|
+
// log('req event', {ev})
|
|
534
544
|
m.redirectReq.emit(ev, ...args); // req 事情映射到 redirectReq 上触发
|
|
535
545
|
};
|
|
536
546
|
|
|
@@ -541,7 +551,7 @@ const readEventEmit = Object.create(null);
|
|
|
541
551
|
for (const ev of readEvents)
|
|
542
552
|
readEventEmit[ev] = /** @param {...any} args */ function (...args) {
|
|
543
553
|
const m = this; // 事件回调,this === clientRequest 实例
|
|
544
|
-
log
|
|
554
|
+
// log('res event', {ev})
|
|
545
555
|
m.redirectReq.emit(ev, ...args); // 向上触发事件
|
|
546
556
|
};
|
|
547
557
|
|
|
@@ -661,14 +671,14 @@ class Request extends Duplex {
|
|
|
661
671
|
get() {
|
|
662
672
|
// @ts-ignore
|
|
663
673
|
const val = m._currentRequest?.[property];
|
|
664
|
-
log
|
|
674
|
+
// log('get property', {property})
|
|
665
675
|
return val
|
|
666
676
|
},
|
|
667
677
|
});
|
|
668
678
|
}
|
|
669
679
|
|
|
680
|
+
// 流模式
|
|
670
681
|
if (opts.stream) {
|
|
671
|
-
// 流模式
|
|
672
682
|
// 被 pipe 作为目标时触发,拷贝 src headers
|
|
673
683
|
m.on(
|
|
674
684
|
'pipe',
|
|
@@ -704,7 +714,7 @@ class Request extends Duplex {
|
|
|
704
714
|
}
|
|
705
715
|
|
|
706
716
|
// Perform the first request
|
|
707
|
-
// m.request(); //
|
|
717
|
+
// m.request(); // 创建时不连接,写入数据时连接,否则 pipe 时无法写入header
|
|
708
718
|
}
|
|
709
719
|
|
|
710
720
|
/**
|
|
@@ -736,6 +746,7 @@ class Request extends Duplex {
|
|
|
736
746
|
// 代理以目的网址协议为准
|
|
737
747
|
// If specified, use the agent corresponding to the protocol
|
|
738
748
|
// (HTTP and HTTPS use different types of agents)
|
|
749
|
+
// agents 优于 agent
|
|
739
750
|
if (agents) {
|
|
740
751
|
const scheme = protocol.slice(0, -1);
|
|
741
752
|
opt.agent = agents[scheme];
|
|
@@ -839,13 +850,13 @@ class Request extends Duplex {
|
|
|
839
850
|
* 如 request 不存在,则创建连接,pipe 时可写入 header
|
|
840
851
|
* @override - 重写父类方法
|
|
841
852
|
* @param {*} chunk - The data chunk to write.
|
|
842
|
-
* @param {BufferEncoding | ((error: Error | null) => void)} [
|
|
853
|
+
* @param {BufferEncoding | ((error: Error | null) => void)} [encoding] - Encoding for string data, or the callback if no encoding is provided.
|
|
843
854
|
* @param {(error: Error | null) => void} [cb] - Callback to signal the end of the write operation.
|
|
844
855
|
* @returns {boolean} True if the write was successful, false otherwise.
|
|
845
856
|
*/
|
|
846
|
-
write(chunk,
|
|
857
|
+
write(chunk, encoding, cb) {
|
|
847
858
|
const m = this;
|
|
848
|
-
log
|
|
859
|
+
// log({data: chunk, encoding, cb}, 'write')
|
|
849
860
|
|
|
850
861
|
// Writing is not allowed if end has been called
|
|
851
862
|
if (m._ending) throw new WriteAfterEndError()
|
|
@@ -857,10 +868,10 @@ class Request extends Duplex {
|
|
|
857
868
|
if (!utils.isString(chunk) && !utils.isBuffer(chunk))
|
|
858
869
|
throw new TypeError('data should be a string, Buffer or Uint8Array')
|
|
859
870
|
|
|
860
|
-
if (utils.isFunction(
|
|
871
|
+
if (utils.isFunction(encoding)) {
|
|
861
872
|
// @ts-ignore
|
|
862
|
-
cb =
|
|
863
|
-
|
|
873
|
+
cb = encoding;
|
|
874
|
+
encoding = null;
|
|
864
875
|
}
|
|
865
876
|
|
|
866
877
|
// Ignore empty buffers, since writing them doesn't invoke the callback
|
|
@@ -873,9 +884,9 @@ class Request extends Duplex {
|
|
|
873
884
|
// Only write when we don't exceed the maximum body length
|
|
874
885
|
if (m._requestBodyLength + chunk.length <= m.opt.maxBodyLength) {
|
|
875
886
|
m._requestBodyLength += chunk.length;
|
|
876
|
-
m._requestBodyBuffers.push({data: chunk, encoding
|
|
887
|
+
m._requestBodyBuffers.push({data: chunk, encoding});
|
|
877
888
|
// @ts-ignore
|
|
878
|
-
m._currentRequest.write(chunk,
|
|
889
|
+
m._currentRequest.write(chunk, encoding, cb);
|
|
879
890
|
}
|
|
880
891
|
// Error when we exceed the maximum body length
|
|
881
892
|
else {
|
|
@@ -906,7 +917,7 @@ class Request extends Duplex {
|
|
|
906
917
|
encoding = null;
|
|
907
918
|
}
|
|
908
919
|
|
|
909
|
-
// !
|
|
920
|
+
// ! 创建实例时不连接,数据写入时发起连接,连接后无法设置 header,因此 pipe 时可设置 header
|
|
910
921
|
if (!m._currentRequest) m.request();
|
|
911
922
|
|
|
912
923
|
// Write data if needed and end
|
|
@@ -1106,7 +1117,7 @@ class Request extends Duplex {
|
|
|
1106
1117
|
// If the response is not a redirect; return it as-is
|
|
1107
1118
|
const {location} = response.headers;
|
|
1108
1119
|
|
|
1109
|
-
log
|
|
1120
|
+
// log({statusCode, headers: response.headers}, 'processResponse')
|
|
1110
1121
|
|
|
1111
1122
|
if (!location || opt.followRedirects === false || statusCode < 300 || statusCode >= 400) {
|
|
1112
1123
|
// 非重定向,返回给原始回调处理
|
|
@@ -1242,11 +1253,11 @@ class Request extends Duplex {
|
|
|
1242
1253
|
// 'transfer-encoding': 'chunked'时,无content-length,axios v1.2 不能自动解压
|
|
1243
1254
|
const responseLength = +res.headers['content-length'];
|
|
1244
1255
|
|
|
1245
|
-
log
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
})
|
|
1256
|
+
// log('processStream', {
|
|
1257
|
+
// statusCode: res.statusCode,
|
|
1258
|
+
// responseLength,
|
|
1259
|
+
// headers: res.headers,
|
|
1260
|
+
// })
|
|
1250
1261
|
|
|
1251
1262
|
if (opt.transformStream) {
|
|
1252
1263
|
opt.transformStream.responseLength = responseLength;
|
|
@@ -1518,12 +1529,18 @@ function isSubdomain(subdomain, domain) {
|
|
|
1518
1529
|
|
|
1519
1530
|
/**
|
|
1520
1531
|
* from 'https://github.com/follow-redirects/follow-redirects'
|
|
1532
|
+
* used by axios
|
|
1521
1533
|
* 修改以支持http、https 代理服务器
|
|
1522
1534
|
* 代理模式下,http or https 请求,取决于 proxy 代理服务器,而不是目的服务器。
|
|
1523
1535
|
*/
|
|
1524
1536
|
|
|
1525
1537
|
|
|
1526
|
-
const log = log$2({env: `wia:req:${name(import.meta.url)}`}) // __filename
|
|
1538
|
+
const log = log$2({env: `wia:req:${name(import.meta.url)}`}); // __filename
|
|
1539
|
+
|
|
1540
|
+
const WritebBeenAbortedError = utils.createErrorType(
|
|
1541
|
+
'ERR_STREAM_WRITE_BEEN_ABORTED',
|
|
1542
|
+
'Request stream has been aborted'
|
|
1543
|
+
)
|
|
1527
1544
|
|
|
1528
1545
|
// Preventive platform detection
|
|
1529
1546
|
// istanbul ignore
|
|
@@ -1586,6 +1603,7 @@ function init(uri, options, callback) {
|
|
|
1586
1603
|
/**
|
|
1587
1604
|
* Executes a request, following redirects
|
|
1588
1605
|
* 替换原 http(s).request,参数类似
|
|
1606
|
+
* 需外部调用 end() data.pipe 或stream管道写入数据
|
|
1589
1607
|
* 注意变参 (options[, callback]) or (url[, options][, callback])
|
|
1590
1608
|
maxRedirects: _.maxRedirects,
|
|
1591
1609
|
maxBodyLength: _.maxBodyLength,
|
|
@@ -1609,7 +1627,8 @@ function request(uri, options, callback) {
|
|
|
1609
1627
|
}
|
|
1610
1628
|
|
|
1611
1629
|
/**
|
|
1612
|
-
*
|
|
1630
|
+
* 执行简单的数据(支持strean)请求
|
|
1631
|
+
* 非流模式,直接写入数据流,流模式,由管道触发,或手动调用 end() data.pipe 写入数据
|
|
1613
1632
|
* 复杂数据,请使用 @wiajs/req库(fork from axios),该库封装了当前库,提供了更多功能
|
|
1614
1633
|
* organize params for patch, post, put, head, del
|
|
1615
1634
|
* @param {string} verb
|
|
@@ -1623,7 +1642,35 @@ function fn(verb) {
|
|
|
1623
1642
|
const {opts, cb} = init(uri, options, callback);
|
|
1624
1643
|
opts.method = method;
|
|
1625
1644
|
const req = new Request(opts, cb);
|
|
1626
|
-
|
|
1645
|
+
const {data, stream} = opts;
|
|
1646
|
+
if (!stream) {
|
|
1647
|
+
// 发送数据
|
|
1648
|
+
if (utils.isStream(data)) {
|
|
1649
|
+
// Send the request
|
|
1650
|
+
let ended = false;
|
|
1651
|
+
let errored = false;
|
|
1652
|
+
|
|
1653
|
+
data.on('end', () => {
|
|
1654
|
+
ended = true;
|
|
1655
|
+
});
|
|
1656
|
+
|
|
1657
|
+
data.once(
|
|
1658
|
+
'error',
|
|
1659
|
+
/** @param {*} err */ err => {
|
|
1660
|
+
errored = true;
|
|
1661
|
+
req.destroy(err);
|
|
1662
|
+
}
|
|
1663
|
+
);
|
|
1664
|
+
|
|
1665
|
+
data.on('close', () => {
|
|
1666
|
+
if (!ended && !errored) {
|
|
1667
|
+
throw new WritebBeenAbortedError()
|
|
1668
|
+
}
|
|
1669
|
+
});
|
|
1670
|
+
|
|
1671
|
+
data.pipe(req); // 写入数据流
|
|
1672
|
+
} else req.end(data);
|
|
1673
|
+
}
|
|
1627
1674
|
return req
|
|
1628
1675
|
}
|
|
1629
1676
|
}
|
|
@@ -1636,6 +1683,6 @@ request.post = fn('post');
|
|
|
1636
1683
|
request.put = fn('put');
|
|
1637
1684
|
request.patch = fn('patch');
|
|
1638
1685
|
request.del = fn('delete');
|
|
1639
|
-
request
|
|
1686
|
+
request.delete = fn('delete');
|
|
1640
1687
|
|
|
1641
1688
|
export { request as default };
|
package/lib/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* from 'https://github.com/follow-redirects/follow-redirects'
|
|
3
|
+
* used by axios
|
|
3
4
|
* 修改以支持http、https 代理服务器
|
|
4
5
|
* 代理模式下,http or https 请求,取决于 proxy 代理服务器,而不是目的服务器。
|
|
5
6
|
*/ import { log as Log, name } from '@wiajs/log';
|
|
@@ -9,6 +10,7 @@ const log = Log({
|
|
|
9
10
|
env: `wia:req:${name(import.meta.url)}`
|
|
10
11
|
}) // __filename
|
|
11
12
|
;
|
|
13
|
+
const WritebBeenAbortedError = utils.createErrorType('ERR_STREAM_WRITE_BEEN_ABORTED', 'Request stream has been aborted');
|
|
12
14
|
(function detectUnsupportedEnvironment() {
|
|
13
15
|
const looksLikeNode = typeof process !== 'undefined';
|
|
14
16
|
const looksLikeBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
|
|
@@ -61,6 +63,7 @@ const log = Log({
|
|
|
61
63
|
/**
|
|
62
64
|
* Executes a request, following redirects
|
|
63
65
|
* 替换原 http(s).request,参数类似
|
|
66
|
+
* 需外部调用 end() data.pipe 或stream管道写入数据
|
|
64
67
|
* 注意变参 (options[, callback]) or (url[, options][, callback])
|
|
65
68
|
maxRedirects: _.maxRedirects,
|
|
66
69
|
maxBodyLength: _.maxBodyLength,
|
|
@@ -80,7 +83,8 @@ const log = Log({
|
|
|
80
83
|
return R;
|
|
81
84
|
}
|
|
82
85
|
/**
|
|
83
|
-
*
|
|
86
|
+
* 执行简单的数据(支持strean)请求
|
|
87
|
+
* 非流模式,直接写入数据流,流模式,由管道触发,或手动调用 end() data.pipe 写入数据
|
|
84
88
|
* 复杂数据,请使用 @wiajs/req库(fork from axios),该库封装了当前库,提供了更多功能
|
|
85
89
|
* organize params for patch, post, put, head, del
|
|
86
90
|
* @param {string} verb
|
|
@@ -92,7 +96,29 @@ const log = Log({
|
|
|
92
96
|
const { opts, cb } = init(uri, options, callback);
|
|
93
97
|
opts.method = method;
|
|
94
98
|
const req = new Request(opts, cb);
|
|
95
|
-
|
|
99
|
+
const { data, stream } = opts;
|
|
100
|
+
if (!stream) {
|
|
101
|
+
// 发送数据
|
|
102
|
+
if (utils.isStream(data)) {
|
|
103
|
+
// Send the request
|
|
104
|
+
let ended = false;
|
|
105
|
+
let errored = false;
|
|
106
|
+
data.on('end', ()=>{
|
|
107
|
+
ended = true;
|
|
108
|
+
});
|
|
109
|
+
data.once('error', /** @param {*} err */ (err)=>{
|
|
110
|
+
errored = true;
|
|
111
|
+
req.destroy(err);
|
|
112
|
+
});
|
|
113
|
+
data.on('close', ()=>{
|
|
114
|
+
if (!ended && !errored) {
|
|
115
|
+
throw new WritebBeenAbortedError();
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
data.pipe(req) // 写入数据流
|
|
119
|
+
;
|
|
120
|
+
} else req.end(data);
|
|
121
|
+
}
|
|
96
122
|
return req;
|
|
97
123
|
};
|
|
98
124
|
}
|
|
@@ -104,5 +130,5 @@ request.post = fn('post');
|
|
|
104
130
|
request.put = fn('put');
|
|
105
131
|
request.patch = fn('patch');
|
|
106
132
|
request.del = fn('delete');
|
|
107
|
-
request
|
|
133
|
+
request.delete = fn('delete');
|
|
108
134
|
export default request;
|
package/lib/request.js
CHANGED
|
@@ -81,7 +81,7 @@ const writeMethods = [
|
|
|
81
81
|
'setSocketKeepAlive'
|
|
82
82
|
];
|
|
83
83
|
// Create handlers that pass events from native requests
|
|
84
|
-
// 在 clientRequest
|
|
84
|
+
// 在 clientRequest 事件转发写事件
|
|
85
85
|
const writeEvents = [
|
|
86
86
|
// 'abort', // 弃用
|
|
87
87
|
// 'aborted', // 弃用
|
|
@@ -103,9 +103,7 @@ const writeEventEmit = Object.create(null);
|
|
|
103
103
|
for (const ev of writeEvents)writeEventEmit[ev] = /** @param {...any} args */ function(...args) {
|
|
104
104
|
const m = this // 事件回调,this === clientRequest 实例
|
|
105
105
|
;
|
|
106
|
-
log('req event', {
|
|
107
|
-
ev
|
|
108
|
-
});
|
|
106
|
+
// log('req event', {ev})
|
|
109
107
|
m.redirectReq.emit(ev, ...args) // req 事情映射到 redirectReq 上触发
|
|
110
108
|
;
|
|
111
109
|
};
|
|
@@ -123,9 +121,7 @@ const readEventEmit = Object.create(null);
|
|
|
123
121
|
for (const ev of readEvents)readEventEmit[ev] = /** @param {...any} args */ function(...args) {
|
|
124
122
|
const m = this // 事件回调,this === clientRequest 实例
|
|
125
123
|
;
|
|
126
|
-
log('res event', {
|
|
127
|
-
ev
|
|
128
|
-
});
|
|
124
|
+
// log('res event', {ev})
|
|
129
125
|
m.redirectReq.emit(ev, ...args) // 向上触发事件
|
|
130
126
|
;
|
|
131
127
|
};
|
|
@@ -193,15 +189,13 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
|
|
|
193
189
|
get () {
|
|
194
190
|
// @ts-ignore
|
|
195
191
|
const val = m._currentRequest?.[property];
|
|
196
|
-
log('get property', {
|
|
197
|
-
property
|
|
198
|
-
});
|
|
192
|
+
// log('get property', {property})
|
|
199
193
|
return val;
|
|
200
194
|
}
|
|
201
195
|
});
|
|
202
196
|
}
|
|
197
|
+
// 流模式
|
|
203
198
|
if (opts.stream) {
|
|
204
|
-
// 流模式
|
|
205
199
|
// 被 pipe 作为目标时触发,拷贝 src headers
|
|
206
200
|
m.on('pipe', /** @param {stream.Readable & {headers?: Object.<string, string>}} src */ (src)=>{
|
|
207
201
|
// m.ntick &&
|
|
@@ -227,7 +221,7 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
|
|
|
227
221
|
});
|
|
228
222
|
}
|
|
229
223
|
// Perform the first request
|
|
230
|
-
// m.request(); //
|
|
224
|
+
// m.request(); // 创建时不连接,写入数据时连接,否则 pipe 时无法写入header
|
|
231
225
|
}
|
|
232
226
|
/**
|
|
233
227
|
* Executes the next native request (initial or redirect)
|
|
@@ -253,6 +247,7 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
|
|
|
253
247
|
// 代理以目的网址协议为准
|
|
254
248
|
// If specified, use the agent corresponding to the protocol
|
|
255
249
|
// (HTTP and HTTPS use different types of agents)
|
|
250
|
+
// agents 优于 agent
|
|
256
251
|
if (agents) {
|
|
257
252
|
const scheme = protocol.slice(0, -1);
|
|
258
253
|
opt.agent = agents[scheme];
|
|
@@ -336,26 +331,22 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
|
|
|
336
331
|
* 如 request 不存在,则创建连接,pipe 时可写入 header
|
|
337
332
|
* @override - 重写父类方法
|
|
338
333
|
* @param {*} chunk - The data chunk to write.
|
|
339
|
-
* @param {BufferEncoding | ((error: Error | null) => void)} [
|
|
334
|
+
* @param {BufferEncoding | ((error: Error | null) => void)} [encoding] - Encoding for string data, or the callback if no encoding is provided.
|
|
340
335
|
* @param {(error: Error | null) => void} [cb] - Callback to signal the end of the write operation.
|
|
341
336
|
* @returns {boolean} True if the write was successful, false otherwise.
|
|
342
|
-
*/ write(chunk,
|
|
337
|
+
*/ write(chunk, encoding, cb) {
|
|
343
338
|
const m = this;
|
|
344
|
-
log({
|
|
345
|
-
data: chunk,
|
|
346
|
-
encoding: encodingOrCallback,
|
|
347
|
-
callback: cb
|
|
348
|
-
}, 'write');
|
|
339
|
+
// log({data: chunk, encoding, cb}, 'write')
|
|
349
340
|
// Writing is not allowed if end has been called
|
|
350
341
|
if (m._ending) throw new WriteAfterEndError();
|
|
351
342
|
// ! 数据写入时连接,pipe 时可设置 header
|
|
352
343
|
if (!m._currentRequest) m.request();
|
|
353
344
|
// Validate input and shift parameters if necessary
|
|
354
345
|
if (!utils.isString(chunk) && !utils.isBuffer(chunk)) throw new TypeError('data should be a string, Buffer or Uint8Array');
|
|
355
|
-
if (utils.isFunction(
|
|
346
|
+
if (utils.isFunction(encoding)) {
|
|
356
347
|
// @ts-ignore
|
|
357
|
-
cb =
|
|
358
|
-
|
|
348
|
+
cb = encoding;
|
|
349
|
+
encoding = null;
|
|
359
350
|
}
|
|
360
351
|
// Ignore empty buffers, since writing them doesn't invoke the callback
|
|
361
352
|
// https://github.com/nodejs/node/issues/22066
|
|
@@ -368,10 +359,10 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
|
|
|
368
359
|
m._requestBodyLength += chunk.length;
|
|
369
360
|
m._requestBodyBuffers.push({
|
|
370
361
|
data: chunk,
|
|
371
|
-
encoding
|
|
362
|
+
encoding
|
|
372
363
|
});
|
|
373
364
|
// @ts-ignore
|
|
374
|
-
m._currentRequest.write(chunk,
|
|
365
|
+
m._currentRequest.write(chunk, encoding, cb);
|
|
375
366
|
} else {
|
|
376
367
|
m.emit('error', new MaxBodyLengthExceededError());
|
|
377
368
|
m.abort();
|
|
@@ -396,7 +387,7 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
|
|
|
396
387
|
cb = encoding;
|
|
397
388
|
encoding = null;
|
|
398
389
|
}
|
|
399
|
-
// !
|
|
390
|
+
// ! 创建实例时不连接,数据写入时发起连接,连接后无法设置 header,因此 pipe 时可设置 header
|
|
400
391
|
if (!m._currentRequest) m.request();
|
|
401
392
|
// Write data if needed and end
|
|
402
393
|
if (!chunk) {
|
|
@@ -559,10 +550,7 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
|
|
|
559
550
|
// even if the specific status code is not understood.
|
|
560
551
|
// If the response is not a redirect; return it as-is
|
|
561
552
|
const { location } = response.headers;
|
|
562
|
-
log({
|
|
563
|
-
statusCode,
|
|
564
|
-
headers: response.headers
|
|
565
|
-
}, 'processResponse');
|
|
553
|
+
// log({statusCode, headers: response.headers}, 'processResponse')
|
|
566
554
|
if (!location || opt.followRedirects === false || statusCode < 300 || statusCode >= 400) {
|
|
567
555
|
// 非重定向,返回给原始回调处理
|
|
568
556
|
response.responseUrl = m._currentUrl;
|
|
@@ -673,11 +661,11 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
|
|
|
673
661
|
];
|
|
674
662
|
// 'transfer-encoding': 'chunked'时,无content-length,axios v1.2 不能自动解压
|
|
675
663
|
const responseLength = +res.headers['content-length'];
|
|
676
|
-
log('processStream', {
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
})
|
|
664
|
+
// log('processStream', {
|
|
665
|
+
// statusCode: res.statusCode,
|
|
666
|
+
// responseLength,
|
|
667
|
+
// headers: res.headers,
|
|
668
|
+
// })
|
|
681
669
|
if (opt.transformStream) {
|
|
682
670
|
opt.transformStream.responseLength = responseLength;
|
|
683
671
|
streams.push(opt.transformStream);
|
package/lib/utils.js
CHANGED
|
@@ -38,7 +38,7 @@ const preservedUrlFields = [
|
|
|
38
38
|
*/ function createErrorType(code, message, baseClass) {
|
|
39
39
|
/**
|
|
40
40
|
* Create constructor
|
|
41
|
-
* @param {*} properties
|
|
41
|
+
* @param {*} properties
|
|
42
42
|
*/ function CustomError(properties) {
|
|
43
43
|
// istanbul ignore else
|
|
44
44
|
if (isFunction(Error.captureStackTrace)) {
|
|
@@ -132,9 +132,9 @@ const noop = ()=>{};
|
|
|
132
132
|
return URL && value instanceof URL;
|
|
133
133
|
}
|
|
134
134
|
/**
|
|
135
|
-
*
|
|
136
|
-
* @param {*} rs
|
|
137
|
-
* @returns
|
|
135
|
+
*
|
|
136
|
+
* @param {*} rs
|
|
137
|
+
* @returns
|
|
138
138
|
*/ function isReadStream(rs) {
|
|
139
139
|
return rs.readable && rs.path && rs.mode;
|
|
140
140
|
}
|
|
@@ -217,6 +217,13 @@ const noop = ()=>{};
|
|
|
217
217
|
code === 204 || // Not Modified
|
|
218
218
|
code === 304;
|
|
219
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* Determine if a value is a Stream
|
|
222
|
+
*
|
|
223
|
+
* @param {*} val The value to test
|
|
224
|
+
*
|
|
225
|
+
* @returns {boolean} True if value is a Stream, otherwise false
|
|
226
|
+
*/ const isStream = (val)=>isObject(val) && isFunction(val.pipe);
|
|
220
227
|
export default {
|
|
221
228
|
createErrorType,
|
|
222
229
|
InvalidUrlError,
|
|
@@ -230,6 +237,7 @@ export default {
|
|
|
230
237
|
isObject,
|
|
231
238
|
isURL,
|
|
232
239
|
isReadStream,
|
|
240
|
+
isStream,
|
|
233
241
|
noop,
|
|
234
242
|
parseUrl,
|
|
235
243
|
spreadUrlObject,
|
package/package.json
CHANGED
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
"name": "@wiajs/request",
|
|
3
3
|
"description": "Stream HTTP request client.",
|
|
4
4
|
"keywords": ["http", "simple", "util", "utility"],
|
|
5
|
-
"version": "3.0.
|
|
5
|
+
"version": "3.0.23",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "index.js",
|
|
8
8
|
"types": "types/index.d.ts",
|
|
9
9
|
"exports": {
|
|
10
10
|
".": {
|
|
11
|
+
"types": {
|
|
12
|
+
"default": "./types/index.d.ts"
|
|
13
|
+
},
|
|
11
14
|
"node": {
|
|
12
15
|
"import": "./index.js",
|
|
13
16
|
"require": "./dist/request.cjs",
|