@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.
@@ -1,10 +1,20 @@
1
1
  import stream from 'node:stream';
2
2
  let ZlibTransform = class ZlibTransform extends stream.Transform {
3
- __transform(chunk, encoding, callback) {
3
+ /**
4
+ *
5
+ * @param {*} chunk
6
+ * @param {*} encoding
7
+ * @param {*} callback
8
+ */ __transform(chunk, encoding, callback) {
4
9
  this.push(chunk);
5
10
  callback();
6
11
  }
7
- _transform(chunk, encoding, callback) {
12
+ /**
13
+ *
14
+ * @param {*} chunk
15
+ * @param {*} encoding
16
+ * @param {*} callback
17
+ */ _transform(chunk, encoding, callback) {
8
18
  if (chunk.length !== 0) {
9
19
  this._transform = this.__transform;
10
20
  // Add Default Compression headers if no zlib headers are present
package/lib/caseless.js CHANGED
@@ -61,7 +61,11 @@ export default class Caseless {
61
61
  this.dict[name] = this.dict[has];
62
62
  delete this.dict[has];
63
63
  }
64
- del(name) {
64
+ /**
65
+ *
66
+ * @param {string} name
67
+ * @returns
68
+ */ del(name) {
65
69
  name = String(name).toLowerCase();
66
70
  let deleted = false;
67
71
  let changed = 0;
@@ -82,17 +86,35 @@ export default class Caseless {
82
86
  * @returns
83
87
  */ export function httpify(resp, headers) {
84
88
  const c = new Caseless(headers);
85
- resp.setHeader = (key, value, clobber)=>{
89
+ /**
90
+ *
91
+ * @param {string} key
92
+ * @param {*} value
93
+ * @param {*} clobber
94
+ * @returns
95
+ */ resp.setHeader = (key, value, clobber)=>{
86
96
  if (typeof value === 'undefined') return;
87
97
  return c.set(key, value, clobber);
88
98
  };
89
- resp.hasHeader = (key)=>{
99
+ /**
100
+ *
101
+ * @param {string} key
102
+ * @returns {boolean|string}
103
+ */ resp.hasHeader = (key)=>{
90
104
  return c.has(key);
91
105
  };
92
- resp.getHeader = (key)=>{
106
+ /**
107
+ *
108
+ * @param {string} key
109
+ * @returns {*}
110
+ */ resp.getHeader = (key)=>{
93
111
  return c.get(key);
94
112
  };
95
- resp.removeHeader = (key)=>{
113
+ /**
114
+ *
115
+ * @param {string} key
116
+ * @returns {boolean}
117
+ */ resp.removeHeader = (key)=>{
96
118
  return c.del(key);
97
119
  };
98
120
  resp.headers = c.dict;
package/lib/request.js CHANGED
@@ -17,7 +17,29 @@ const log = Log({
17
17
  env: `wia:req:${name(import.meta.url)}`
18
18
  }) // __filename
19
19
  ;
20
- const httpModules = {
20
+ /**
21
+ * @typedef {object} Opts
22
+ * @prop {Object.<string,string>} headers
23
+ * @prop {string} host
24
+ * @prop {string} method
25
+ * @prop {string} family
26
+ * @prop {string} path
27
+ * @prop {'http:' | 'https:'} protocol
28
+ * @prop {*} agent
29
+ * @prop {*} agents
30
+ * @prop {boolean} [stream]
31
+ * @prop {boolean} [decompress=true]
32
+ * @prop {*} [transformStream]
33
+ * @prop {*} [beforeRedirect]
34
+ * @prop {boolean} [followRedirects]
35
+ * @prop {number} [maxRedirects=21]
36
+ * @prop {number} [maxBodyLength = 0]
37
+ * @prop {*} [trackRedirects]
38
+ */ /** @typedef {object} ResponseExt
39
+ * @prop {*[]} [redirects]
40
+ * @prop {string} [responseUrl]
41
+ * @prop {number} [responseStartTime]
42
+ */ /** @typedef { http.IncomingMessage & ResponseExt} Response*/ const httpModules = {
21
43
  'http:': http,
22
44
  'https:': https
23
45
  };
@@ -78,7 +100,7 @@ const writeEvents = [
78
100
  'upgrade'
79
101
  ];
80
102
  const writeEventEmit = Object.create(null);
81
- for (const ev of writeEvents)writeEventEmit[ev] = function(...args) {
103
+ for (const ev of writeEvents)writeEventEmit[ev] = /** @param {...any} args */ function(...args) {
82
104
  const m = this // 事件回调,this === clientRequest 实例
83
105
  ;
84
106
  log('req event', {
@@ -98,7 +120,7 @@ const readEvents = [
98
120
  'resume'
99
121
  ];
100
122
  const readEventEmit = Object.create(null);
101
- for (const ev of readEvents)readEventEmit[ev] = function(...args) {
123
+ for (const ev of readEvents)readEventEmit[ev] = /** @param {...any} args */ function(...args) {
102
124
  const m = this // 事件回调,this === clientRequest 实例
103
125
  ;
104
126
  log('res event', {
@@ -118,10 +140,10 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
118
140
  */ export default class Request extends Duplex {
119
141
  /**
120
142
  * responseCallback 原消息处理回调
121
- * @param {*} opts
143
+ * @param {Opts} opts
122
144
  * @param {*} resCallback
123
145
  */ constructor(opts, resCallback){
124
- super(), this._timeout = 0, /** @type {*} */ this.socket = null, /** @type {http.ClientRequest} */ this._currentRequest = null, /** @type {stream.Readable} */ this.response = null, /** @type {stream.Readable} */ this.responseStream = null, this.timing = false, this.responseStarted = false, this.responseStartTime = 0, this._destdata = false, this._paused = false, this._respended = false, /** @type {stream.Readable} */ this.pipesrc = null // 被 pipe 时的 src stream
146
+ super(), /** @type {NodeJS.Timeout} */ this._timeout = null, /** @type {*} */ this.socket = null, /** @type {http.ClientRequest} */ this._currentRequest = null, /** @type {Response} */ this.response = null, /** @type {stream.Readable} */ this.responseStream = null, this.timing = false, this.responseStarted = false, this.responseStartTime = 0, this._destdata = false, this._paused = false, this._respended = false, /** @type {stream.Readable} */ this.pipesrc = null // 被 pipe 时的 src stream
125
147
  , /** @type {stream.Writable[]} */ this.pipedests = [] // pipe dest
126
148
  , /** @type {*} */ this.startTimer = null;
127
149
  const m = this;
@@ -139,9 +161,11 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
139
161
  /** @type {any[]} */ m._requestBodyBuffers = [];
140
162
  // save the callback if passed
141
163
  m.resCallback = resCallback;
142
- // React to responses of native requests
143
- // 接管 response 事件,非重定向,触发 response 事件
144
- m._onResponse = (res)=>{
164
+ /**
165
+ * React to responses of native requests
166
+ * 接管 response 事件,非重定向,触发 response 事件
167
+ * @param {Response} res
168
+ */ m._onResponse = (res)=>{
145
169
  try {
146
170
  m.processResponse(res);
147
171
  } catch (cause) {
@@ -179,24 +203,25 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
179
203
  if (opts.stream) {
180
204
  // 流模式
181
205
  // 被 pipe 作为目标时触发,拷贝 src headers
182
- m.on('pipe', /** @type {stream.Readable} */ (src)=>{
206
+ m.on('pipe', /** @param {stream.Readable & {headers?: Object.<string, string>}} src */ (src)=>{
183
207
  // m.ntick &&
184
208
  if (m._currentRequest) {
185
209
  m.emit('error', new Error('You cannot pipe to this stream after the outbound request has started.'));
186
210
  }
187
211
  m.pipesrc = src;
188
212
  if (utils.isReadStream(src)) {
189
- if (!m.hasHeader('content-type')) {
190
- m.setHeader('content-type', mime.lookup(src.path));
191
- }
213
+ // @ts-ignore
214
+ if (!m.hasHeader('content-type')) m.setHeader('content-type', mime.lookup(src.path));
192
215
  } else {
216
+ // 拷贝请求头
193
217
  if (src.headers) {
194
- for (const h of src.headers){
195
- if (!m.hasHeader(h)) {
196
- m.setHeader(h, src.headers[h]);
218
+ for (const k of Object.keys(src.headers)){
219
+ if (!m.hasHeader(k)) {
220
+ m.setHeader(k, src.headers[k]);
197
221
  }
198
222
  }
199
223
  }
224
+ // @ts-ignore
200
225
  if (src.opt.method && !m.opt.method) m.opt.method = src.opt.method;
201
226
  }
202
227
  });
@@ -244,8 +269,10 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
244
269
  protocol
245
270
  }, 'request');
246
271
  // Create the native request and set up its event handlers
272
+ // @ts-ignore
247
273
  const req = httpModule.request(opt, m._onResponse);
248
274
  m._currentRequest = req;
275
+ // @ts-ignore
249
276
  req.redirectReq = m;
250
277
  // 启动 startTimer
251
278
  if (m.startTimer) m._currentRequest.once('socket', m.startTimer);
@@ -262,7 +289,10 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
262
289
  // Write the request entity and end
263
290
  let i = 0;
264
291
  const buffers = m._requestBodyBuffers;
265
- (function writeNext(error) {
292
+ /**
293
+ *
294
+ * @param {*} error
295
+ */ function writeNext(error) {
266
296
  // Only write if this request has not been redirected yet
267
297
  /* istanbul ignore else */ if (req === m._currentRequest) {
268
298
  // Report any write errors
@@ -272,7 +302,8 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
272
302
  /* istanbul ignore else */ if (!req.finished) req.write(buf.data, buf.encoding, writeNext);
273
303
  } else if (m._ended) req.end();
274
304
  }
275
- })();
305
+ }
306
+ writeNext();
276
307
  }
277
308
  R = req;
278
309
  } catch (e) {
@@ -303,15 +334,16 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
303
334
  /**
304
335
  * Writes buffered data to the current native request
305
336
  * 如 request 不存在,则创建连接,pipe 时可写入 header
306
- * @param {*} chunk
307
- * @param {BufferEncoding=} encoding
308
- * @param {(error: Error) => void} [cb]
309
- * @returns {boolean}
310
- */ write(chunk, encoding, cb) {
337
+ * @override - 重写父类方法
338
+ * @param {*} chunk - The data chunk to write.
339
+ * @param {BufferEncoding | ((error: Error | null) => void)} [encodingOrCallback] - Encoding for string data, or the callback if no encoding is provided.
340
+ * @param {(error: Error | null) => void} [cb] - Callback to signal the end of the write operation.
341
+ * @returns {boolean} True if the write was successful, false otherwise.
342
+ */ write(chunk, encodingOrCallback, cb) {
311
343
  const m = this;
312
344
  log({
313
345
  data: chunk,
314
- encoding,
346
+ encoding: encodingOrCallback,
315
347
  callback: cb
316
348
  }, 'write');
317
349
  // Writing is not allowed if end has been called
@@ -320,14 +352,15 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
320
352
  if (!m._currentRequest) m.request();
321
353
  // Validate input and shift parameters if necessary
322
354
  if (!utils.isString(chunk) && !utils.isBuffer(chunk)) throw new TypeError('data should be a string, Buffer or Uint8Array');
323
- if (utils.isFunction(encoding)) {
324
- cb = encoding;
325
- encoding = null;
355
+ if (utils.isFunction(encodingOrCallback)) {
356
+ // @ts-ignore
357
+ cb = encodingOrCallback;
358
+ encodingOrCallback = null;
326
359
  }
327
360
  // Ignore empty buffers, since writing them doesn't invoke the callback
328
361
  // https://github.com/nodejs/node/issues/22066
329
362
  if (chunk.length === 0) {
330
- if (cb) cb();
363
+ if (cb) cb(null);
331
364
  return;
332
365
  }
333
366
  // Only write when we don't exceed the maximum body length
@@ -335,9 +368,10 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
335
368
  m._requestBodyLength += chunk.length;
336
369
  m._requestBodyBuffers.push({
337
370
  data: chunk,
338
- encoding
371
+ encoding: encodingOrCallback
339
372
  });
340
- m._currentRequest.write(chunk, encoding, cb);
373
+ // @ts-ignore
374
+ m._currentRequest.write(chunk, encodingOrCallback, cb);
341
375
  } else {
342
376
  m.emit('error', new MaxBodyLengthExceededError());
343
377
  m.abort();
@@ -345,42 +379,46 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
345
379
  }
346
380
  /**
347
381
  * Ends the current native request
348
- * @param {*} data
349
- * @param {*} encoding
350
- * @param {*} callback
351
- */ end(data, encoding, callback) {
382
+ * @override - 重写父类方法
383
+ * @param {*} [chunk] - Optional data to write before ending the stream.
384
+ * @param {BufferEncoding | (() => void)} [encoding] - Encoding for string data, or the callback if no encoding is provided.
385
+ * @param {() => void} [cb] - Optional callback to signal completion.
386
+ * @returns {this} The current stream instance, to allow chaining.
387
+ */ end(chunk, encoding, cb) {
352
388
  const m = this;
353
389
  // Shift parameters if necessary
354
- if (utils.isFunction(data)) {
355
- callback = data;
356
- data = null;
390
+ if (utils.isFunction(chunk)) {
391
+ cb = chunk;
392
+ chunk = null;
357
393
  encoding = null;
358
394
  } else if (utils.isFunction(encoding)) {
359
- callback = encoding;
395
+ // @ts-ignore
396
+ cb = encoding;
360
397
  encoding = null;
361
398
  }
362
399
  // ! 数据写入时连接,pipe 时可设置 header
363
400
  if (!m._currentRequest) m.request();
364
401
  // Write data if needed and end
365
- if (!data) {
402
+ if (!chunk) {
366
403
  m._ended = true;
367
404
  m._ending = true;
368
- m._currentRequest.end(null, null, callback);
405
+ m._currentRequest.end(null, null, cb);
369
406
  } else {
370
407
  const currentRequest = m._currentRequest;
371
- m.write(data, encoding, ()=>{
408
+ m.write(chunk, encoding, ()=>{
372
409
  m._ended = true;
373
- currentRequest.end(null, null, callback);
410
+ currentRequest.end(null, null, cb);
374
411
  });
375
412
  m._ending = true;
376
413
  }
414
+ return m;
377
415
  }
378
416
  /**
379
417
  *
380
418
  * @param {string} name
381
419
  * @returns
382
420
  */ hasHeader(name) {
383
- return this.opt.headers.includes(name);
421
+ return Object.keys(this.opt.headers).includes(name);
384
422
  }
385
423
  /**
386
424
  *
@@ -392,6 +430,7 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
392
430
  /**
393
431
  * Sets a header value on the current native request
394
432
  * @param {string} name
433
+ * @param {string} value
395
434
  */ setHeader(name, value) {
396
435
  this.opt.headers[name] = value;
397
436
  this._currentRequest?.setHeader(name, value);
@@ -469,7 +508,10 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
469
508
  m.on('close', clearTimer);
470
509
  return m;
471
510
  }
472
- sanitizeOptions(options) {
511
+ /**
512
+ *
513
+ * @param {*} options
514
+ */ sanitizeOptions(options) {
473
515
  // Ensure headers are always present
474
516
  if (!options.headers) options.headers = {};
475
517
  // Since http.request treats host as an alias of hostname,
@@ -495,14 +537,14 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
495
537
  }
496
538
  /**
497
539
  * Processes a response from the current native request
498
- * @param {*} response
540
+ * @param {Response} response
499
541
  * @returns
500
542
  */ processResponse(response) {
501
543
  const m = this;
502
544
  const { opt } = m;
503
545
  // Store the redirected response
504
546
  const { statusCode } = response;
505
- if (m.opt.trackRedirects) {
547
+ if (opt.trackRedirects) {
506
548
  m._redirects.push({
507
549
  url: m._currentUrl,
508
550
  headers: response.headers,
@@ -521,7 +563,7 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
521
563
  statusCode,
522
564
  headers: response.headers
523
565
  }, 'processResponse');
524
- if (!location || m.opt.followRedirects === false || statusCode < 300 || statusCode >= 400) {
566
+ if (!location || opt.followRedirects === false || statusCode < 300 || statusCode >= 400) {
525
567
  // 非重定向,返回给原始回调处理
526
568
  response.responseUrl = m._currentUrl;
527
569
  response.redirects = m._redirects;
@@ -545,7 +587,7 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
545
587
  m.emit('response', response, responseStream);
546
588
  // Clean up
547
589
  m._requestBodyBuffers = [];
548
- return;
590
+ return; // 退出,不继续处理
549
591
  }
550
592
  // The response is a redirect, so abort the current request
551
593
  destroyRequest(m._currentRequest);
@@ -553,34 +595,35 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
553
595
  response.destroy();
554
596
  // RFC7231§6.4: A client SHOULD detect and intervene
555
597
  // in cyclical redirections (i.e., "infinite" redirection loops).
556
- if (++m._redirectCount > m.opt.maxRedirects) throw new TooManyRedirectsError();
598
+ if (++m._redirectCount > opt.maxRedirects) throw new TooManyRedirectsError();
557
599
  // Store the request headers if applicable
558
600
  let requestHeaders;
559
- const { beforeRedirect } = m.opt;
601
+ const { beforeRedirect } = opt;
560
602
  if (beforeRedirect) {
561
603
  requestHeaders = {
562
604
  // The Host header was set by nativeProtocol.request
605
+ // @ts-ignore
563
606
  Host: response.req.getHeader('host'),
564
- ...m.opt.headers
607
+ ...opt.headers
565
608
  };
566
609
  }
567
610
  // RFC7231§6.4: Automatic redirection needs to done with
568
611
  // care for methods not known to be safe, […]
569
612
  // RFC7231§6.4.2–3: For historical reasons, a user agent MAY change
570
613
  // the request method from POST to GET for the subsequent request.
571
- const { method } = m.opt;
572
- if ((statusCode === 301 || statusCode === 302) && m.opt.method === 'POST' || // RFC7231§6.4.4: The 303 (See Other) status code indicates that
614
+ const { method } = opt;
615
+ if ((statusCode === 301 || statusCode === 302) && opt.method === 'POST' || // RFC7231§6.4.4: The 303 (See Other) status code indicates that
573
616
  // the server is redirecting the user agent to a different resource […]
574
617
  // A user agent can perform a retrieval request targeting that URI
575
618
  // (a GET or HEAD request if using HTTP) […]
576
- statusCode === 303 && !/^(?:GET|HEAD)$/.test(m.opt.method)) {
619
+ statusCode === 303 && !/^(?:GET|HEAD)$/.test(opt.method)) {
577
620
  m.opt.method = 'GET';
578
621
  // Drop a possible entity and headers related to it
579
622
  m._requestBodyBuffers = [];
580
- removeMatchingHeaders(/^content-/i, m.opt.headers);
623
+ removeMatchingHeaders(/^content-/i, opt.headers);
581
624
  }
582
625
  // Drop the Host header, as the redirect might lead to a different host
583
- const currentHostHeader = removeMatchingHeaders(/^host$/i, m.opt.headers);
626
+ const currentHostHeader = removeMatchingHeaders(/^host$/i, opt.headers);
584
627
  // If the redirect is relative, carry over the host of the last request
585
628
  const currentUrlParts = utils.parseUrl(m._currentUrl);
586
629
  const currentHost = currentHostHeader || currentUrlParts.host;
@@ -611,8 +654,8 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
611
654
  method,
612
655
  headers: requestHeaders
613
656
  };
614
- beforeRedirect(m.opt, responseDetails, requestDetails);
615
- m.sanitizeOptions(m.opt);
657
+ beforeRedirect(opt, responseDetails, requestDetails);
658
+ m.sanitizeOptions(opt);
616
659
  }
617
660
  // Perform the redirected request
618
661
  m.request() // 重新执行请求
@@ -620,11 +663,11 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
620
663
  }
621
664
  /**
622
665
  * 处理响应stream
623
- * 如:解压,透传流,需设置 decompress = false,避免解压数据
666
+ * 自动解压,透传流,需设置 decompress = false,避免解压数据
624
667
  * @param {*} res
625
668
  */ processStream(res) {
626
669
  const m = this;
627
- const { opt: opts } = m;
670
+ const { opt } = m;
628
671
  const streams = [
629
672
  res
630
673
  ];
@@ -635,13 +678,13 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
635
678
  responseLength,
636
679
  headers: res.headers
637
680
  });
638
- if (opts.transformStream) {
639
- opts.transformStream.responseLength = responseLength;
640
- streams.push(opts.transformStream);
681
+ if (opt.transformStream) {
682
+ opt.transformStream.responseLength = responseLength;
683
+ streams.push(opt.transformStream);
641
684
  }
642
- const empty = utils.noBody(opts.method, res.statusCode);
685
+ const empty = utils.noBody(opt.method, res.statusCode);
643
686
  // decompress the response body transparently if required
644
- if (opts.decompress !== false && res.headers['content-encoding']) {
687
+ if (opt.decompress !== false && res.headers['content-encoding']) {
645
688
  // if decompress disabled we should not decompress
646
689
  // 压缩内容,加入 解压 stream,自动解压,axios v1.2 存在bug,不能自动解压
647
690
  // if no content, but headers still say that it is encoded,
@@ -675,13 +718,14 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
675
718
  default:
676
719
  }
677
720
  }
721
+ // 响应流,用于读
678
722
  const responseStream = streams.length > 1 ? stream.pipeline(streams, utils.noop) : streams[0];
679
723
  // 将内部 responseStream 可读流 映射到 redirectReq
680
724
  m.responseStream = responseStream;
681
725
  responseStream.redirectReq = m // 事情触发时引用
682
726
  ;
683
727
  // stream 模式,事件透传到 请求类
684
- if (opts.stream) {
728
+ if (opt.stream) {
685
729
  if (m._paused) responseStream.pause();
686
730
  // 写入目的流
687
731
  for (const dest of m.pipedests)m.pipeDest(dest);
@@ -708,13 +752,18 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
708
752
  }
709
753
  // Read Stream API
710
754
  /**
755
+ * 建立读取流管道
711
756
  * read stream to write stream
712
757
  * pipe 只是建立连接管道,后续自动传输数据
713
- * @param {stream.Writable} dest
714
- * @param {*} opts
715
- * @returns {stream.Writable}
716
- */ pipe(dest, opts) {
758
+ * @override - 重写父类方法
759
+ * @template T - 需要模板
760
+ * @param {T & stream.Writable} dest - The writable stream to which data is written.
761
+ * @param {Object} [opts] - Optional configuration object.
762
+ * @param {boolean} [opts.end=true] - Whether to end the writable stream when the readable stream ends.
763
+ * @returns {T} The destination stream.
764
+ */ pipe(dest, opts = {}) {
717
765
  const m = this;
766
+ // m.pipe()
718
767
  // 请求已响应
719
768
  if (m.responseStream) {
720
769
  // 已有数据,不可pipe
@@ -778,7 +827,7 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
778
827
  if (response?.headers && dest.headers && !dest.headersSent) {
779
828
  const caseless = new Caseless(response.headers);
780
829
  if (caseless.has('content-type')) {
781
- const ctname = caseless.has('content-type');
830
+ const ctname = /** @type {string} */ caseless.has('content-type');
782
831
  if (dest.setHeader) {
783
832
  dest.setHeader(ctname, response.headers[ctname]);
784
833
  } else {
@@ -786,7 +835,7 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
786
835
  }
787
836
  }
788
837
  if (caseless.has('content-length')) {
789
- const clname = caseless.has('content-length');
838
+ const clname = /** @type {string} */ caseless.has('content-length');
790
839
  if (dest.setHeader) {
791
840
  dest.setHeader(clname, response.headers[clname]);
792
841
  } else {
@@ -795,32 +844,26 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
795
844
  }
796
845
  }
797
846
  if (response?.headers && dest.setHeader && !dest.headersSent) {
798
- for (const h of response.headers){
799
- dest.setHeader(h, response.headers[h]);
800
- }
847
+ for (const k of Object.keys(response.headers))dest.setHeader(k, response.headers[k]);
801
848
  dest.statusCode = response.statusCode;
802
849
  }
803
- if (m.pipefilter) {
804
- m.pipefilter(response, dest);
805
- }
850
+ if (m.pipefilter) m.pipefilter(response, dest);
806
851
  }
807
852
  /**
808
853
  * 暂停read流
809
- * @param {...any} args
810
- */ pause(...args) {
854
+ */ pause() {
811
855
  const m = this;
812
856
  // 没有流
813
857
  if (!m.responseStream) m._paused = true;
814
- else m.responseStream.pause(...args);
858
+ else m.responseStream.pause();
815
859
  return m;
816
860
  }
817
861
  /**
818
- * 继续read
819
- * @param {...any} args
820
- */ resume(...args) {
862
+ * 继续read响应流
863
+ */ resume() {
821
864
  const m = this;
822
865
  if (!m.responseStream) m._paused = false;
823
- else m.responseStream.resume(...args);
866
+ else m.responseStream.resume();
824
867
  return m;
825
868
  }
826
869
  isPaused() {
@@ -838,17 +881,27 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
838
881
  request.on('error', utils.noop);
839
882
  request.destroy(error);
840
883
  }
841
- function removeMatchingHeaders(regex, headers) {
884
+ /**
885
+ *
886
+ * @param {RegExp} regex
887
+ * @param {Object.<string, string>} headers
888
+ * @returns
889
+ */ function removeMatchingHeaders(regex, headers) {
842
890
  let lastValue;
843
- Object.keys(headers).forEach((k)=>{
891
+ for (const k of Object.keys(headers)){
844
892
  if (regex.test(k)) {
845
893
  lastValue = headers[k];
846
894
  delete headers[k];
847
895
  }
848
- });
896
+ }
849
897
  return lastValue === null || typeof lastValue === 'undefined' ? undefined : String(lastValue).trim();
850
898
  }
851
- function isSubdomain(subdomain, domain) {
899
+ /**
900
+ *
901
+ * @param {string} subdomain
902
+ * @param {string} domain
903
+ * @returns
904
+ */ function isSubdomain(subdomain, domain) {
852
905
  assert(utils.isString(subdomain) && utils.isString(domain));
853
906
  const dot = subdomain.length - domain.length - 1;
854
907
  return dot > 0 && subdomain[dot] === '.' && subdomain.endsWith(domain);
package/lib/utils.js CHANGED
@@ -25,20 +25,28 @@ const preservedUrlFields = [
25
25
  'hash'
26
26
  ];
27
27
  /**
28
- *
29
- * @param {*} code
30
- * @param {*} message
31
- * @param {*} baseClass
32
- * @returns
28
+ * Create a custom error type.
29
+ * @param {string} code - The error code.
30
+ * @param {string} message - The error message.
31
+ * @param {typeof Error} [baseClass] - The base error class to extend from. Defaults to `Error`.
32
+ * @returns {typeof Error & { new(properties?: object): CustomErrorInstance }} A custom error constructor.
33
+ * new(properties?: object) 为构造函数语法,返回 CustomErrorInstance 类型
34
+ * @typedef {object} CustomErrorInstance
35
+ * @property {string} code - The error code.
36
+ * @property {string} message - The error message.
37
+ * @property {Error | undefined} cause - The optional error cause.
33
38
  */ function createErrorType(code, message, baseClass) {
34
- // Create constructor
35
- function CustomError(properties) {
39
+ /**
40
+ * Create constructor
41
+ * @param {*} properties
42
+ */ function CustomError(properties) {
36
43
  // istanbul ignore else
37
44
  if (isFunction(Error.captureStackTrace)) {
38
45
  Error.captureStackTrace(this, this.constructor);
39
46
  }
40
47
  Object.assign(this, properties || {});
41
48
  this.code = code;
49
+ // @ts-ignore
42
50
  this.message = this.cause ? `${message}: ${this.cause.message}` : message;
43
51
  }
44
52
  // Attach constructor and set default properties
@@ -53,6 +61,7 @@ const preservedUrlFields = [
53
61
  enumerable: false
54
62
  }
55
63
  });
64
+ // @ts-ignore
56
65
  return CustomError;
57
66
  }
58
67
  const InvalidUrlError = createErrorType('ERR_INVALID_URL', 'Invalid URL', TypeError);
@@ -122,7 +131,11 @@ const noop = ()=>{};
122
131
  */ function isURL(value) {
123
132
  return URL && value instanceof URL;
124
133
  }
125
- function isReadStream(rs) {
134
+ /**
135
+ *
136
+ * @param {*} rs
137
+ * @returns
138
+ */ function isReadStream(rs) {
126
139
  return rs.readable && rs.path && rs.mode;
127
140
  }
128
141
  /**