@wiajs/request 3.0.18 → 3.0.19

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,5 +1,5 @@
1
1
  /*!
2
- * wia request v3.0.18
2
+ * wia request v3.0.19
3
3
  * (c) 2022-2024 Sibyl Yu and contributors
4
4
  * Released under the MIT License.
5
5
  */
@@ -13,11 +13,23 @@ import zlib from 'node:zlib';
13
13
  import mime from 'mime-types';
14
14
 
15
15
  class ZlibTransform extends stream.Transform {
16
+ /**
17
+ *
18
+ * @param {*} chunk
19
+ * @param {*} encoding
20
+ * @param {*} callback
21
+ */
16
22
  __transform(chunk, encoding, callback) {
17
23
  this.push(chunk);
18
24
  callback();
19
25
  }
20
26
 
27
+ /**
28
+ *
29
+ * @param {*} chunk
30
+ * @param {*} encoding
31
+ * @param {*} callback
32
+ */
21
33
  _transform(chunk, encoding, callback) {
22
34
  if (chunk.length !== 0) {
23
35
  this._transform = this.__transform;
@@ -66,14 +78,22 @@ const preservedUrlFields = [
66
78
  ];
67
79
 
68
80
  /**
69
- *
70
- * @param {*} code
71
- * @param {*} message
72
- * @param {*} baseClass
73
- * @returns
81
+ * Create a custom error type.
82
+ * @param {string} code - The error code.
83
+ * @param {string} message - The error message.
84
+ * @param {typeof Error} [baseClass] - The base error class to extend from. Defaults to `Error`.
85
+ * @returns {typeof Error & { new(properties?: object): CustomErrorInstance }} A custom error constructor.
86
+ * new(properties?: object) 为构造函数语法,返回 CustomErrorInstance 类型
87
+ * @typedef {object} CustomErrorInstance
88
+ * @property {string} code - The error code.
89
+ * @property {string} message - The error message.
90
+ * @property {Error | undefined} cause - The optional error cause.
74
91
  */
75
- function createErrorType(code, message, baseClass) {
76
- // Create constructor
92
+ function createErrorType(code, message, baseClass) {
93
+ /**
94
+ * Create constructor
95
+ * @param {*} properties
96
+ */
77
97
  function CustomError(properties) {
78
98
  // istanbul ignore else
79
99
  if (isFunction(Error.captureStackTrace)) {
@@ -81,6 +101,7 @@ function createErrorType(code, message, baseClass) {
81
101
  }
82
102
  Object.assign(this, properties || {});
83
103
  this.code = code;
104
+ // @ts-ignore
84
105
  this.message = this.cause ? `${message}: ${this.cause.message}` : message;
85
106
  }
86
107
 
@@ -96,6 +117,8 @@ function createErrorType(code, message, baseClass) {
96
117
  enumerable: false,
97
118
  },
98
119
  });
120
+
121
+ // @ts-ignore
99
122
  return CustomError
100
123
  }
101
124
 
@@ -194,6 +217,11 @@ function isURL(value) {
194
217
  return URL && value instanceof URL
195
218
  }
196
219
 
220
+ /**
221
+ *
222
+ * @param {*} rs
223
+ * @returns
224
+ */
197
225
  function isReadStream(rs) {
198
226
  return rs.readable && rs.path && rs.mode
199
227
  }
@@ -383,6 +411,11 @@ class Caseless {
383
411
  delete this.dict[has];
384
412
  }
385
413
 
414
+ /**
415
+ *
416
+ * @param {string} name
417
+ * @returns
418
+ */
386
419
  del(name) {
387
420
  name = String(name).toLowerCase();
388
421
  let deleted = false;
@@ -405,6 +438,34 @@ class Caseless {
405
438
 
406
439
  const log$1 = log$2({env: `wia:req:${name(import.meta.url)}`}); // __filename
407
440
 
441
+ /**
442
+ * @typedef {object} Opts
443
+ * @prop {Object.<string,string>} headers
444
+ * @prop {string} host
445
+ * @prop {string} method
446
+ * @prop {string} family
447
+ * @prop {string} path
448
+ * @prop {'http:' | 'https:'} protocol
449
+ * @prop {*} agent
450
+ * @prop {*} agents
451
+ * @prop {boolean} [stream]
452
+ * @prop {boolean} [decompress=true]
453
+ * @prop {*} [transformStream]
454
+ * @prop {*} [beforeRedirect]
455
+ * @prop {boolean} [followRedirects]
456
+ * @prop {number} [maxRedirects=21]
457
+ * @prop {number} [maxBodyLength = 0]
458
+ * @prop {*} [trackRedirects]
459
+ */
460
+
461
+ /** @typedef {object} ResponseExt
462
+ * @prop {*[]} [redirects]
463
+ * @prop {string} [responseUrl]
464
+ * @prop {number} [responseStartTime]
465
+ */
466
+
467
+ /** @typedef { http.IncomingMessage & ResponseExt} Response*/
468
+
408
469
  const httpModules = {'http:': http, 'https:': https};
409
470
 
410
471
  const zlibOptions = {
@@ -465,8 +526,9 @@ const writeEvents = [
465
526
  ];
466
527
 
467
528
  const writeEventEmit = Object.create(null);
529
+
468
530
  for (const ev of writeEvents)
469
- writeEventEmit[ev] = function (...args) {
531
+ writeEventEmit[ev] = /** @param {...any} args */ function (...args) {
470
532
  const m = this; // 事件回调,this === clientRequest 实例
471
533
  log$1('req event', {ev});
472
534
  m.redirectReq.emit(ev, ...args); // req 事情映射到 redirectReq 上触发
@@ -477,14 +539,17 @@ for (const ev of writeEvents)
477
539
  const readEvents = ['close', 'end', 'error', 'pause', 'readable', 'resume'];
478
540
  const readEventEmit = Object.create(null);
479
541
  for (const ev of readEvents)
480
- readEventEmit[ev] = function (...args) {
542
+ readEventEmit[ev] = /** @param {...any} args */ function (...args) {
481
543
  const m = this; // 事件回调,this === clientRequest 实例
482
544
  log$1('res event', {ev});
483
545
  m.redirectReq.emit(ev, ...args); // 向上触发事件
484
546
  };
485
547
 
486
548
  // Error types with codes
487
- const RedirectionError = utils.createErrorType('ERR_FR_REDIRECTION_FAILURE', 'Redirected request failed');
549
+ const RedirectionError = utils.createErrorType(
550
+ 'ERR_FR_REDIRECTION_FAILURE',
551
+ 'Redirected request failed'
552
+ );
488
553
 
489
554
  const TooManyRedirectsError = utils.createErrorType(
490
555
  'ERR_FR_TOO_MANY_REDIRECTS',
@@ -504,12 +569,13 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
504
569
  * wrap http.ClientRequest
505
570
  */
506
571
  class Request extends Duplex {
507
- _timeout = 0
572
+ /** @type {NodeJS.Timeout} */
573
+ _timeout = null
508
574
  /** @type {*} */
509
575
  socket = null
510
576
  /** @type {http.ClientRequest} */
511
577
  _currentRequest = null
512
- /** @type {stream.Readable} */
578
+ /** @type {Response} */
513
579
  response = null
514
580
  /** @type {stream.Readable} */
515
581
  responseStream = null
@@ -525,10 +591,16 @@ class Request extends Duplex {
525
591
  pipedests = [] // pipe dest
526
592
  /** @type {*} */
527
593
  startTimer = null
594
+ /** @type {Opts} */
595
+ opt
596
+ /** @type {*} */
597
+ pipefilter
598
+ /** @type {string} */
599
+ _currentUrl
528
600
 
529
601
  /**
530
602
  * responseCallback 原消息处理回调
531
- * @param {*} opts
603
+ * @param {Opts} opts
532
604
  * @param {*} resCallback
533
605
  */
534
606
  constructor(opts, resCallback) {
@@ -555,13 +627,20 @@ class Request extends Duplex {
555
627
 
556
628
  // save the callback if passed
557
629
  m.resCallback = resCallback;
558
- // React to responses of native requests
559
- // 接管 response 事件,非重定向,触发 response 事件
630
+
631
+ /**
632
+ * React to responses of native requests
633
+ * 接管 response 事件,非重定向,触发 response 事件
634
+ * @param {Response} res
635
+ */
560
636
  m._onResponse = res => {
561
637
  try {
562
638
  m.processResponse(res);
563
639
  } catch (cause) {
564
- m.emit('error', cause instanceof RedirectionError ? cause : new RedirectionError({cause: cause}));
640
+ m.emit(
641
+ 'error',
642
+ cause instanceof RedirectionError ? cause : new RedirectionError({cause: cause})
643
+ );
565
644
  }
566
645
  };
567
646
 
@@ -593,27 +672,31 @@ class Request extends Duplex {
593
672
  // 被 pipe 作为目标时触发,拷贝 src headers
594
673
  m.on(
595
674
  'pipe',
596
- /** @type {stream.Readable} */ src => {
675
+ /** @param {stream.Readable & {headers?: Object.<string, string>}} src */ src => {
597
676
  // m.ntick &&
598
677
  if (m._currentRequest) {
599
- m.emit('error', new Error('You cannot pipe to this stream after the outbound request has started.'));
678
+ m.emit(
679
+ 'error',
680
+ new Error('You cannot pipe to this stream after the outbound request has started.')
681
+ );
600
682
  }
601
683
 
602
684
  m.pipesrc = src;
603
685
 
604
686
  if (utils.isReadStream(src)) {
605
- if (!m.hasHeader('content-type')) {
606
- m.setHeader('content-type', mime.lookup(src.path));
607
- }
687
+ // @ts-ignore
688
+ if (!m.hasHeader('content-type')) m.setHeader('content-type', mime.lookup(src.path));
608
689
  } else {
690
+ // 拷贝请求头
609
691
  if (src.headers) {
610
- for (const h of src.headers) {
611
- if (!m.hasHeader(h)) {
612
- m.setHeader(h, src.headers[h]);
692
+ for (const k of Object.keys(src.headers)) {
693
+ if (!m.hasHeader(k)) {
694
+ m.setHeader(k, src.headers[k]);
613
695
  }
614
696
  }
615
697
  }
616
698
 
699
+ // @ts-ignore
617
700
  if (src.opt.method && !m.opt.method) m.opt.method = src.opt.method;
618
701
  }
619
702
  }
@@ -660,7 +743,8 @@ class Request extends Duplex {
660
743
  // http 非隧道代理模式,模块以代理主机为准,其他以目的网址为准
661
744
  // 代理内部会根据代理协议选择 http(s) 发起请求创建连接
662
745
  if (protocol === 'http:' && agents.http) {
663
- protocol = agents.http.proxy && !agents.http.tunnel ? agents.http.proxy.protocol : protocol;
746
+ protocol =
747
+ agents.http.proxy && !agents.http.tunnel ? agents.http.proxy.protocol : protocol;
664
748
  }
665
749
  }
666
750
 
@@ -669,8 +753,10 @@ class Request extends Duplex {
669
753
 
670
754
  log$1({opt, protocol}, 'request');
671
755
  // Create the native request and set up its event handlers
756
+ // @ts-ignore
672
757
  const req = httpModule.request(opt, m._onResponse);
673
758
  m._currentRequest = req;
759
+ // @ts-ignore
674
760
  req.redirectReq = m;
675
761
 
676
762
  // 启动 startTimer
@@ -690,8 +776,13 @@ class Request extends Duplex {
690
776
  if (m._isRedirect) {
691
777
  // Write the request entity and end
692
778
  let i = 0;
693
- const buffers = m._requestBodyBuffers
694
- ;(function writeNext(error) {
779
+ const buffers = m._requestBodyBuffers;
780
+
781
+ /**
782
+ *
783
+ * @param {*} error
784
+ */
785
+ function writeNext(error) {
695
786
  // Only write if this request has not been redirected yet
696
787
  /* istanbul ignore else */
697
788
  if (req === m._currentRequest) {
@@ -707,7 +798,8 @@ class Request extends Duplex {
707
798
  // End the request if `end` has been called on us
708
799
  else if (m._ended) req.end();
709
800
  }
710
- })();
801
+ }
802
+ writeNext();
711
803
  }
712
804
 
713
805
  R = req;
@@ -745,15 +837,15 @@ class Request extends Duplex {
745
837
  /**
746
838
  * Writes buffered data to the current native request
747
839
  * 如 request 不存在,则创建连接,pipe 时可写入 header
748
- * @param {*} chunk
749
- * @param {BufferEncoding=} encoding
750
- * @param {(error: Error) => void} [cb]
751
- * @returns {boolean}
840
+ * @override - 重写父类方法
841
+ * @param {*} chunk - The data chunk to write.
842
+ * @param {BufferEncoding | ((error: Error | null) => void)} [encodingOrCallback] - Encoding for string data, or the callback if no encoding is provided.
843
+ * @param {(error: Error | null) => void} [cb] - Callback to signal the end of the write operation.
844
+ * @returns {boolean} True if the write was successful, false otherwise.
752
845
  */
753
- write(chunk, encoding, cb) {
846
+ write(chunk, encodingOrCallback, cb) {
754
847
  const m = this;
755
-
756
- log$1({data: chunk, encoding, callback: cb}, 'write');
848
+ log$1({data: chunk, encoding: encodingOrCallback, callback: cb}, 'write');
757
849
 
758
850
  // Writing is not allowed if end has been called
759
851
  if (m._ending) throw new WriteAfterEndError()
@@ -765,23 +857,25 @@ class Request extends Duplex {
765
857
  if (!utils.isString(chunk) && !utils.isBuffer(chunk))
766
858
  throw new TypeError('data should be a string, Buffer or Uint8Array')
767
859
 
768
- if (utils.isFunction(encoding)) {
769
- cb = encoding;
770
- encoding = null;
860
+ if (utils.isFunction(encodingOrCallback)) {
861
+ // @ts-ignore
862
+ cb = encodingOrCallback;
863
+ encodingOrCallback = null;
771
864
  }
772
865
 
773
866
  // Ignore empty buffers, since writing them doesn't invoke the callback
774
867
  // https://github.com/nodejs/node/issues/22066
775
868
  if (chunk.length === 0) {
776
- if (cb) cb();
869
+ if (cb) cb(null);
777
870
  return
778
871
  }
779
872
 
780
873
  // Only write when we don't exceed the maximum body length
781
874
  if (m._requestBodyLength + chunk.length <= m.opt.maxBodyLength) {
782
875
  m._requestBodyLength += chunk.length;
783
- m._requestBodyBuffers.push({data: chunk, encoding});
784
- m._currentRequest.write(chunk, encoding, cb);
876
+ m._requestBodyBuffers.push({data: chunk, encoding: encodingOrCallback});
877
+ // @ts-ignore
878
+ m._currentRequest.write(chunk, encodingOrCallback, cb);
785
879
  }
786
880
  // Error when we exceed the maximum body length
787
881
  else {
@@ -792,20 +886,23 @@ class Request extends Duplex {
792
886
 
793
887
  /**
794
888
  * Ends the current native request
795
- * @param {*} data
796
- * @param {*} encoding
797
- * @param {*} callback
889
+ * @override - 重写父类方法
890
+ * @param {*} [chunk] - Optional data to write before ending the stream.
891
+ * @param {BufferEncoding | (() => void)} [encoding] - Encoding for string data, or the callback if no encoding is provided.
892
+ * @param {() => void} [cb] - Optional callback to signal completion.
893
+ * @returns {this} The current stream instance, to allow chaining.
798
894
  */
799
- end(data, encoding, callback) {
895
+ end(chunk, encoding, cb) {
800
896
  const m = this;
801
897
 
802
898
  // Shift parameters if necessary
803
- if (utils.isFunction(data)) {
804
- callback = data;
805
- data = null;
899
+ if (utils.isFunction(chunk)) {
900
+ cb = chunk;
901
+ chunk = null;
806
902
  encoding = null;
807
903
  } else if (utils.isFunction(encoding)) {
808
- callback = encoding;
904
+ // @ts-ignore
905
+ cb = encoding;
809
906
  encoding = null;
810
907
  }
811
908
 
@@ -813,19 +910,21 @@ class Request extends Duplex {
813
910
  if (!m._currentRequest) m.request();
814
911
 
815
912
  // Write data if needed and end
816
- if (!data) {
913
+ if (!chunk) {
817
914
  m._ended = true;
818
915
  m._ending = true;
819
- m._currentRequest.end(null, null, callback);
916
+ m._currentRequest.end(null, null, cb);
820
917
  } else {
821
918
  const currentRequest = m._currentRequest;
822
- m.write(data, encoding, () => {
919
+ m.write(chunk, encoding, () => {
823
920
  m._ended = true;
824
- currentRequest.end(null, null, callback);
921
+ currentRequest.end(null, null, cb);
825
922
  });
826
923
 
827
924
  m._ending = true;
828
925
  }
926
+
927
+ return m
829
928
  }
830
929
 
831
930
  /**
@@ -834,7 +933,7 @@ class Request extends Duplex {
834
933
  * @returns
835
934
  */
836
935
  hasHeader(name) {
837
- return this.opt.headers.includes(name)
936
+ return Object.keys(this.opt.headers).includes(name)
838
937
  }
839
938
 
840
939
  /**
@@ -849,6 +948,7 @@ class Request extends Duplex {
849
948
  /**
850
949
  * Sets a header value on the current native request
851
950
  * @param {string} name
951
+ * @param {string} value
852
952
  */
853
953
  setHeader(name, value) {
854
954
  this.opt.headers[name] = value;
@@ -946,6 +1046,10 @@ class Request extends Duplex {
946
1046
  return m
947
1047
  }
948
1048
 
1049
+ /**
1050
+ *
1051
+ * @param {*} options
1052
+ */
949
1053
  sanitizeOptions(options) {
950
1054
  // Ensure headers are always present
951
1055
  if (!options.headers) options.headers = {};
@@ -975,7 +1079,7 @@ class Request extends Duplex {
975
1079
 
976
1080
  /**
977
1081
  * Processes a response from the current native request
978
- * @param {*} response
1082
+ * @param {Response} response
979
1083
  * @returns
980
1084
  */
981
1085
  processResponse(response) {
@@ -984,7 +1088,7 @@ class Request extends Duplex {
984
1088
 
985
1089
  // Store the redirected response
986
1090
  const {statusCode} = response;
987
- if (m.opt.trackRedirects) {
1091
+ if (opt.trackRedirects) {
988
1092
  m._redirects.push({
989
1093
  url: m._currentUrl,
990
1094
  headers: response.headers,
@@ -1004,7 +1108,7 @@ class Request extends Duplex {
1004
1108
 
1005
1109
  log$1({statusCode, headers: response.headers}, 'processResponse');
1006
1110
 
1007
- if (!location || m.opt.followRedirects === false || statusCode < 300 || statusCode >= 400) {
1111
+ if (!location || opt.followRedirects === false || statusCode < 300 || statusCode >= 400) {
1008
1112
  // 非重定向,返回给原始回调处理
1009
1113
  response.responseUrl = m._currentUrl;
1010
1114
  response.redirects = m._redirects;
@@ -1035,7 +1139,7 @@ class Request extends Duplex {
1035
1139
 
1036
1140
  // Clean up
1037
1141
  m._requestBodyBuffers = [];
1038
- return
1142
+ return // 退出,不继续处理
1039
1143
  }
1040
1144
 
1041
1145
  // The response is a redirect, so abort the current request
@@ -1045,16 +1149,17 @@ class Request extends Duplex {
1045
1149
 
1046
1150
  // RFC7231§6.4: A client SHOULD detect and intervene
1047
1151
  // in cyclical redirections (i.e., "infinite" redirection loops).
1048
- if (++m._redirectCount > m.opt.maxRedirects) throw new TooManyRedirectsError()
1152
+ if (++m._redirectCount > opt.maxRedirects) throw new TooManyRedirectsError()
1049
1153
 
1050
1154
  // Store the request headers if applicable
1051
1155
  let requestHeaders;
1052
- const {beforeRedirect} = m.opt;
1156
+ const {beforeRedirect} = opt;
1053
1157
  if (beforeRedirect) {
1054
1158
  requestHeaders = {
1055
1159
  // The Host header was set by nativeProtocol.request
1160
+ // @ts-ignore
1056
1161
  Host: response.req.getHeader('host'),
1057
- ...m.opt.headers,
1162
+ ...opt.headers,
1058
1163
  };
1059
1164
  }
1060
1165
 
@@ -1062,23 +1167,23 @@ class Request extends Duplex {
1062
1167
  // care for methods not known to be safe, […]
1063
1168
  // RFC7231§6.4.2–3: For historical reasons, a user agent MAY change
1064
1169
  // the request method from POST to GET for the subsequent request.
1065
- const {method} = m.opt;
1170
+ const {method} = opt;
1066
1171
  if (
1067
- ((statusCode === 301 || statusCode === 302) && m.opt.method === 'POST') ||
1172
+ ((statusCode === 301 || statusCode === 302) && opt.method === 'POST') ||
1068
1173
  // RFC7231§6.4.4: The 303 (See Other) status code indicates that
1069
1174
  // the server is redirecting the user agent to a different resource […]
1070
1175
  // A user agent can perform a retrieval request targeting that URI
1071
1176
  // (a GET or HEAD request if using HTTP) […]
1072
- (statusCode === 303 && !/^(?:GET|HEAD)$/.test(m.opt.method))
1177
+ (statusCode === 303 && !/^(?:GET|HEAD)$/.test(opt.method))
1073
1178
  ) {
1074
1179
  m.opt.method = 'GET';
1075
1180
  // Drop a possible entity and headers related to it
1076
1181
  m._requestBodyBuffers = [];
1077
- removeMatchingHeaders(/^content-/i, m.opt.headers);
1182
+ removeMatchingHeaders(/^content-/i, opt.headers);
1078
1183
  }
1079
1184
 
1080
1185
  // Drop the Host header, as the redirect might lead to a different host
1081
- const currentHostHeader = removeMatchingHeaders(/^host$/i, m.opt.headers);
1186
+ const currentHostHeader = removeMatchingHeaders(/^host$/i, opt.headers);
1082
1187
 
1083
1188
  // If the redirect is relative, carry over the host of the last request
1084
1189
  const currentUrlParts = utils.parseUrl(m._currentUrl);
@@ -1115,8 +1220,8 @@ class Request extends Duplex {
1115
1220
  headers: requestHeaders,
1116
1221
  };
1117
1222
 
1118
- beforeRedirect(m.opt, responseDetails, requestDetails);
1119
- m.sanitizeOptions(m.opt);
1223
+ beforeRedirect(opt, responseDetails, requestDetails);
1224
+ m.sanitizeOptions(opt);
1120
1225
  }
1121
1226
 
1122
1227
  // Perform the redirected request
@@ -1125,12 +1230,12 @@ class Request extends Duplex {
1125
1230
 
1126
1231
  /**
1127
1232
  * 处理响应stream
1128
- * 如:解压,透传流,需设置 decompress = false,避免解压数据
1233
+ * 自动解压,透传流,需设置 decompress = false,避免解压数据
1129
1234
  * @param {*} res
1130
1235
  */
1131
1236
  processStream(res) {
1132
1237
  const m = this;
1133
- const {opt: opts} = m;
1238
+ const {opt} = m;
1134
1239
 
1135
1240
  const streams = [res];
1136
1241
 
@@ -1143,14 +1248,14 @@ class Request extends Duplex {
1143
1248
  headers: res.headers,
1144
1249
  });
1145
1250
 
1146
- if (opts.transformStream) {
1147
- opts.transformStream.responseLength = responseLength;
1148
- streams.push(opts.transformStream);
1251
+ if (opt.transformStream) {
1252
+ opt.transformStream.responseLength = responseLength;
1253
+ streams.push(opt.transformStream);
1149
1254
  }
1150
1255
 
1151
- const empty = utils.noBody(opts.method, res.statusCode);
1256
+ const empty = utils.noBody(opt.method, res.statusCode);
1152
1257
  // decompress the response body transparently if required
1153
- if (opts.decompress !== false && res.headers['content-encoding']) {
1258
+ if (opt.decompress !== false && res.headers['content-encoding']) {
1154
1259
  // if decompress disabled we should not decompress
1155
1260
  // 压缩内容,加入 解压 stream,自动解压,axios v1.2 存在bug,不能自动解压
1156
1261
  // if no content, but headers still say that it is encoded,
@@ -1191,6 +1296,7 @@ class Request extends Duplex {
1191
1296
  }
1192
1297
  }
1193
1298
 
1299
+ // 响应流,用于读
1194
1300
  const responseStream = streams.length > 1 ? stream.pipeline(streams, utils.noop) : streams[0];
1195
1301
  // 将内部 responseStream 可读流 映射到 redirectReq
1196
1302
 
@@ -1198,7 +1304,7 @@ class Request extends Duplex {
1198
1304
  responseStream.redirectReq = m; // 事情触发时引用
1199
1305
 
1200
1306
  // stream 模式,事件透传到 请求类
1201
- if (opts.stream) {
1307
+ if (opt.stream) {
1202
1308
  if (m._paused) responseStream.pause();
1203
1309
  // 写入目的流
1204
1310
  for (const dest of m.pipedests) m.pipeDest(dest);
@@ -1229,20 +1335,26 @@ class Request extends Duplex {
1229
1335
  // Read Stream API
1230
1336
 
1231
1337
  /**
1338
+ * 建立读取流管道
1232
1339
  * read stream to write stream
1233
1340
  * pipe 只是建立连接管道,后续自动传输数据
1234
- * @param {stream.Writable} dest
1235
- * @param {*} opts
1236
- * @returns {stream.Writable}
1341
+ * @override - 重写父类方法
1342
+ * @template T - 需要模板
1343
+ * @param {T & stream.Writable} dest - The writable stream to which data is written.
1344
+ * @param {Object} [opts] - Optional configuration object.
1345
+ * @param {boolean} [opts.end=true] - Whether to end the writable stream when the readable stream ends.
1346
+ * @returns {T} The destination stream.
1237
1347
  */
1238
- pipe(dest, opts) {
1348
+ pipe(dest, opts = {}) {
1239
1349
  const m = this;
1240
-
1350
+ // m.pipe()
1241
1351
  // 请求已响应
1242
1352
  if (m.responseStream) {
1243
1353
  // 已有数据,不可pipe
1244
- if (m._destdata) m.emit('error', new Error('You cannot pipe after data has been emitted from the response.'));
1245
- else if (m._respended) m.emit('error', new Error('You cannot pipe after the response has been ended.'));
1354
+ if (m._destdata)
1355
+ m.emit('error', new Error('You cannot pipe after data has been emitted from the response.'));
1356
+ else if (m._respended)
1357
+ m.emit('error', new Error('You cannot pipe after the response has been ended.'));
1246
1358
  else {
1247
1359
  // stream.Stream.prototype.pipe.call(self, dest, opts);
1248
1360
  super.pipe(dest, opts); // 建立连接管道,自动传输数据
@@ -1269,8 +1381,13 @@ class Request extends Duplex {
1269
1381
  // 请求已响应
1270
1382
  if (m.responseStream) {
1271
1383
  // 已有数据,不可 unpipe
1272
- if (m._destdata) m.emit('error', new Error('You cannot unpipe after data has been emitted from the response.'));
1273
- else if (m._respended) m.emit('error', new Error('You cannot unpipe after the response has been ended.'));
1384
+ if (m._destdata)
1385
+ m.emit(
1386
+ 'error',
1387
+ new Error('You cannot unpipe after data has been emitted from the response.')
1388
+ );
1389
+ else if (m._respended)
1390
+ m.emit('error', new Error('You cannot unpipe after the response has been ended.'));
1274
1391
  else {
1275
1392
  // stream.Stream.prototype.pipe.call(self, dest, opts);
1276
1393
  super.unpipe(dest); // 建立连接管道,自动传输数据
@@ -1301,7 +1418,7 @@ class Request extends Duplex {
1301
1418
  if (response?.headers && dest.headers && !dest.headersSent) {
1302
1419
  const caseless = new Caseless(response.headers);
1303
1420
  if (caseless.has('content-type')) {
1304
- const ctname = caseless.has('content-type');
1421
+ const ctname = /** @type {string} */ (caseless.has('content-type'));
1305
1422
  if (dest.setHeader) {
1306
1423
  dest.setHeader(ctname, response.headers[ctname]);
1307
1424
  } else {
@@ -1310,7 +1427,7 @@ class Request extends Duplex {
1310
1427
  }
1311
1428
 
1312
1429
  if (caseless.has('content-length')) {
1313
- const clname = caseless.has('content-length');
1430
+ const clname = /** @type {string} */ (caseless.has('content-length'));
1314
1431
  if (dest.setHeader) {
1315
1432
  dest.setHeader(clname, response.headers[clname]);
1316
1433
  } else {
@@ -1320,37 +1437,32 @@ class Request extends Duplex {
1320
1437
  }
1321
1438
 
1322
1439
  if (response?.headers && dest.setHeader && !dest.headersSent) {
1323
- for (const h of response.headers) {
1324
- dest.setHeader(h, response.headers[h]);
1325
- }
1440
+ for (const k of Object.keys(response.headers)) dest.setHeader(k, response.headers[k]);
1441
+
1326
1442
  dest.statusCode = response.statusCode;
1327
1443
  }
1328
1444
 
1329
- if (m.pipefilter) {
1330
- m.pipefilter(response, dest);
1331
- }
1445
+ if (m.pipefilter) m.pipefilter(response, dest);
1332
1446
  }
1333
1447
 
1334
1448
  /**
1335
1449
  * 暂停read流
1336
- * @param {...any} args
1337
1450
  */
1338
- pause(...args) {
1451
+ pause() {
1339
1452
  const m = this;
1340
1453
  // 没有流
1341
1454
  if (!m.responseStream) m._paused = true;
1342
- else m.responseStream.pause(...args);
1455
+ else m.responseStream.pause();
1343
1456
  return m
1344
1457
  }
1345
1458
 
1346
1459
  /**
1347
- * 继续read
1348
- * @param {...any} args
1460
+ * 继续read响应流
1349
1461
  */
1350
- resume(...args) {
1462
+ resume() {
1351
1463
  const m = this;
1352
1464
  if (!m.responseStream) m._paused = false;
1353
- else m.responseStream.resume(...args);
1465
+ else m.responseStream.resume();
1354
1466
  return m
1355
1467
  }
1356
1468
 
@@ -1372,18 +1484,32 @@ function destroyRequest(request, error) {
1372
1484
  request.destroy(error);
1373
1485
  }
1374
1486
 
1487
+ /**
1488
+ *
1489
+ * @param {RegExp} regex
1490
+ * @param {Object.<string, string>} headers
1491
+ * @returns
1492
+ */
1375
1493
  function removeMatchingHeaders(regex, headers) {
1376
1494
  let lastValue;
1377
- Object.keys(headers).forEach(k => {
1495
+ for (const k of Object.keys(headers)) {
1378
1496
  if (regex.test(k)) {
1379
1497
  lastValue = headers[k];
1380
1498
  delete headers[k];
1381
1499
  }
1382
- });
1500
+ }
1383
1501
 
1384
- return lastValue === null || typeof lastValue === 'undefined' ? undefined : String(lastValue).trim()
1502
+ return lastValue === null || typeof lastValue === 'undefined'
1503
+ ? undefined
1504
+ : String(lastValue).trim()
1385
1505
  }
1386
1506
 
1507
+ /**
1508
+ *
1509
+ * @param {string} subdomain
1510
+ * @param {string} domain
1511
+ * @returns
1512
+ */
1387
1513
  function isSubdomain(subdomain, domain) {
1388
1514
  assert(utils.isString(subdomain) && utils.isString(domain));
1389
1515
  const dot = subdomain.length - domain.length - 1;