@wiajs/request 3.0.29 → 3.0.31
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 +166 -60
- package/dist/request.mjs +166 -60
- package/lib/index.js +81 -49
- package/lib/request.js +66 -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/lib/request.js
CHANGED
|
@@ -33,14 +33,14 @@ const log = Log({
|
|
|
33
33
|
* @prop {*} [beforeRedirect]
|
|
34
34
|
* @prop {boolean} [followRedirects]
|
|
35
35
|
* @prop {number} [maxRedirects=21]
|
|
36
|
-
* @prop {number} [maxBodyLength =
|
|
36
|
+
* @prop {number} [maxBodyLength = -1]
|
|
37
37
|
* @prop {*} [trackRedirects]
|
|
38
38
|
* @prop {*} [data]
|
|
39
39
|
*/ /** @typedef {object} ResponseExt
|
|
40
40
|
* @prop {*[]} [redirects]
|
|
41
41
|
* @prop {string} [responseUrl]
|
|
42
42
|
* @prop {number} [responseStartTime]
|
|
43
|
-
*/ /** @typedef { http.IncomingMessage & ResponseExt} Response*/ const httpModules = {
|
|
43
|
+
*/ /** @typedef { http.IncomingMessage & ResponseExt} Response */ const httpModules = {
|
|
44
44
|
'http:': http,
|
|
45
45
|
'https:': https
|
|
46
46
|
};
|
|
@@ -90,7 +90,7 @@ const writeEvents = [
|
|
|
90
90
|
'connect',
|
|
91
91
|
'continue',
|
|
92
92
|
'drain',
|
|
93
|
-
'error',
|
|
93
|
+
// 'error', // 单独处理,未注册 'error' 事件处理程序,错误将冒泡到全局导致程序崩溃
|
|
94
94
|
'finish',
|
|
95
95
|
'information',
|
|
96
96
|
'pipe',
|
|
@@ -105,7 +105,7 @@ for (const ev of writeEvents)writeEventEmit[ev] = /** @param {...any} args */ f
|
|
|
105
105
|
const m = this // 事件回调,this === clientRequest 实例
|
|
106
106
|
;
|
|
107
107
|
// log('req event', {ev})
|
|
108
|
-
m.redirectReq.emit(ev, ...args) // req
|
|
108
|
+
m.redirectReq.emit(ev, ...args) // 内部请求req 事情转发到 Request
|
|
109
109
|
;
|
|
110
110
|
};
|
|
111
111
|
// stream.Readable,在响应流上转发读流取事件
|
|
@@ -131,6 +131,11 @@ const RedirectionError = utils.createErrorType('ERR_FR_REDIRECTION_FAILURE', 'Re
|
|
|
131
131
|
const TooManyRedirectsError = utils.createErrorType('ERR_FR_TOO_MANY_REDIRECTS', 'Maximum number of redirects exceeded', RedirectionError);
|
|
132
132
|
const MaxBodyLengthExceededError = utils.createErrorType('ERR_FR_MAX_BODY_LENGTH_EXCEEDED', 'Request body larger than maxBodyLength limit');
|
|
133
133
|
const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', 'write after end');
|
|
134
|
+
// request err
|
|
135
|
+
const HostNotfoundError = utils.createErrorType('ERR_HOSTNOTFOUND', 'DNS 解析失败,主机名可能无效');
|
|
136
|
+
const ConnRefusedError = utils.createErrorType('ERR_CONNREFUSED', '连接被拒绝,目标服务器可能不可用');
|
|
137
|
+
const ConnTimedoutError = utils.createErrorType('ERR_CONNTIMEDOUT', '请求超时,请检查网络连接或服务器负载');
|
|
138
|
+
const ConnResetError = utils.createErrorType('ERR_CONNRESET', '连接被重置,可能是网络问题或服务器关闭了连接');
|
|
134
139
|
/**
|
|
135
140
|
* An HTTP(S) request that can be redirected
|
|
136
141
|
* wrap http.ClientRequest
|
|
@@ -266,7 +271,39 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
|
|
|
266
271
|
req.redirectReq = m;
|
|
267
272
|
// 启动 startTimer
|
|
268
273
|
if (m.startTimer) m._currentRequest.once('socket', m.startTimer);
|
|
269
|
-
//
|
|
274
|
+
// set tcp keep alive to prevent drop connection by peer
|
|
275
|
+
req.on('socket', /** @param {*} socket */ (socket)=>{
|
|
276
|
+
// default interval of sending ack packet is 1 minute
|
|
277
|
+
socket.setKeepAlive(true, 1000 * 60);
|
|
278
|
+
});
|
|
279
|
+
// 请求error单独处理
|
|
280
|
+
// 'error' 事件处理,避免错误将冒泡到全局导致程序崩溃
|
|
281
|
+
req.on('error', (err)=>{
|
|
282
|
+
destroyRequest(req) // 释放资源
|
|
283
|
+
;
|
|
284
|
+
// @ts-ignore
|
|
285
|
+
log.error({
|
|
286
|
+
errcode: err?.code
|
|
287
|
+
}, 'request');
|
|
288
|
+
// @ts-ignore
|
|
289
|
+
switch(err?.code){
|
|
290
|
+
case 'ENOTFOUND':
|
|
291
|
+
m.emit('error', new HostNotfoundError());
|
|
292
|
+
break;
|
|
293
|
+
case 'ECONNREFUSED':
|
|
294
|
+
m.emit('error', new ConnRefusedError());
|
|
295
|
+
break;
|
|
296
|
+
case 'ETIMEDOUT':
|
|
297
|
+
m.emit('error', new ConnTimedoutError());
|
|
298
|
+
break;
|
|
299
|
+
case 'ECONNRESET':
|
|
300
|
+
m.emit('error', new ConnResetError());
|
|
301
|
+
break;
|
|
302
|
+
default:
|
|
303
|
+
m.emit('error', utils.createErrorType('ERR_CONNOTHER', `网络错误: ${err.message}`));
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
// 接收req事件,转发 到 request 上发射,网络关闭事件,触发 error
|
|
270
307
|
for (const ev of writeEvents)req.on(ev, writeEventEmit[ev]);
|
|
271
308
|
// RFC7230§5.3.1: When making a request directly to an origin server, […]
|
|
272
309
|
// a client MUST send only the absolute path […] as the request-target.
|
|
@@ -302,9 +339,10 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
|
|
|
302
339
|
}
|
|
303
340
|
return R;
|
|
304
341
|
}
|
|
305
|
-
|
|
342
|
+
/**
|
|
343
|
+
* 写入错误,释放请求,触发 abort 终止事件
|
|
344
|
+
*/ abort() {
|
|
306
345
|
destroyRequest(this._currentRequest);
|
|
307
|
-
this._currentRequest.abort();
|
|
308
346
|
this.emit('abort');
|
|
309
347
|
}
|
|
310
348
|
/**
|
|
@@ -359,7 +397,11 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
|
|
|
359
397
|
const m = this;
|
|
360
398
|
// log({data: chunk, encoding, cb}, 'write')
|
|
361
399
|
// Writing is not allowed if end has been called
|
|
362
|
-
if (m._ending)
|
|
400
|
+
if (m._ending) {
|
|
401
|
+
// throw new WriteAfterEndError()
|
|
402
|
+
m.emit('error', new WriteAfterEndError());
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
363
405
|
// ! 数据写入时连接,pipe 时可设置 header
|
|
364
406
|
if (!m._currentRequest) m.request();
|
|
365
407
|
// Validate input and shift parameters if necessary
|
|
@@ -673,13 +715,15 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
|
|
|
673
715
|
/**
|
|
674
716
|
* 处理响应stream
|
|
675
717
|
* 自动解压,透传流,需设置 decompress = false,避免解压数据
|
|
676
|
-
* @param {
|
|
718
|
+
* @param {Response} res
|
|
719
|
+
* @returns {Response | stream.Readable}
|
|
677
720
|
*/ processStream(res) {
|
|
678
721
|
const m = this;
|
|
679
722
|
const { opt } = m;
|
|
680
723
|
const streams = [
|
|
681
724
|
res
|
|
682
725
|
];
|
|
726
|
+
let responseStream = res;
|
|
683
727
|
// 'transfer-encoding': 'chunked'时,无content-length,axios v1.2 不能自动解压
|
|
684
728
|
const responseLength = +res.headers['content-length'];
|
|
685
729
|
// log('processStream', {
|
|
@@ -707,19 +751,23 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
|
|
|
707
751
|
case 'compress':
|
|
708
752
|
case 'x-compress':
|
|
709
753
|
// add the unzipper to the body stream processing pipeline
|
|
754
|
+
// @ts-ignore
|
|
710
755
|
streams.push(zlib.createUnzip(zlibOptions));
|
|
711
756
|
// remove the content-encoding in order to not confuse downstream operations
|
|
712
757
|
res.headers['content-encoding'] = undefined;
|
|
713
758
|
break;
|
|
714
759
|
case 'deflate':
|
|
760
|
+
// @ts-ignore
|
|
715
761
|
streams.push(new ZlibTransform());
|
|
716
762
|
// add the unzipper to the body stream processing pipeline
|
|
763
|
+
// @ts-ignore
|
|
717
764
|
streams.push(zlib.createUnzip(zlibOptions));
|
|
718
765
|
// remove the content-encoding in order to not confuse downstream operations
|
|
719
766
|
res.headers['content-encoding'] = undefined;
|
|
720
767
|
break;
|
|
721
768
|
case 'br':
|
|
722
769
|
if (isBrotliSupported) {
|
|
770
|
+
// @ts-ignore
|
|
723
771
|
streams.push(zlib.createBrotliDecompress(brotliOptions));
|
|
724
772
|
res.headers['content-encoding'] = undefined;
|
|
725
773
|
}
|
|
@@ -728,9 +776,12 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
|
|
|
728
776
|
}
|
|
729
777
|
}
|
|
730
778
|
// 响应流,用于读
|
|
731
|
-
|
|
779
|
+
// @ts-ignore
|
|
780
|
+
responseStream = streams.length > 1 ? stream.pipeline(streams, utils.noop) : streams[0];
|
|
732
781
|
// 将内部 responseStream 可读流 映射到 redirectReq
|
|
782
|
+
// @ts-ignore
|
|
733
783
|
m.responseStream = responseStream;
|
|
784
|
+
// @ts-ignore
|
|
734
785
|
responseStream.redirectReq = m // 事情触发时引用
|
|
735
786
|
;
|
|
736
787
|
// stream 模式,事件透传到 请求类
|
|
@@ -880,7 +931,9 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
|
|
|
880
931
|
}
|
|
881
932
|
}
|
|
882
933
|
/**
|
|
883
|
-
*
|
|
934
|
+
* 释放请求,触发error事件
|
|
935
|
+
* 'error' event, and emit a 'close' event.
|
|
936
|
+
* Calling this will cause remaining data in the response to be dropped and the socket to be destroyed.
|
|
884
937
|
* @param {*} request
|
|
885
938
|
* @param {*} error
|
|
886
939
|
*/ function destroyRequest(request, error) {
|
|
@@ -888,7 +941,8 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
|
|
|
888
941
|
request.removeListener(ev, writeEventEmit[ev]);
|
|
889
942
|
}
|
|
890
943
|
request.on('error', utils.noop);
|
|
891
|
-
request.destroy(error)
|
|
944
|
+
request.destroy(error) // 触发 error 事件
|
|
945
|
+
;
|
|
892
946
|
}
|
|
893
947
|
/**
|
|
894
948
|
*
|
package/package.json
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -1,14 +1,40 @@
|
|
|
1
1
|
export default request;
|
|
2
|
-
|
|
2
|
+
export type Response = import("./request").Response;
|
|
3
|
+
export type Opts = {
|
|
4
|
+
headers?: {
|
|
5
|
+
[x: string]: string;
|
|
6
|
+
};
|
|
7
|
+
url?: string;
|
|
8
|
+
protocol?: "http:" | "https:";
|
|
9
|
+
host?: string;
|
|
10
|
+
family?: string;
|
|
11
|
+
path?: string;
|
|
12
|
+
method?: string;
|
|
13
|
+
agent?: any;
|
|
14
|
+
agents?: any;
|
|
15
|
+
body?: any;
|
|
16
|
+
data?: any;
|
|
17
|
+
stream?: boolean;
|
|
18
|
+
decompress?: boolean;
|
|
19
|
+
transformStream?: any;
|
|
20
|
+
beforeRedirect?: any;
|
|
21
|
+
followRedirects?: boolean;
|
|
22
|
+
maxRedirects?: number;
|
|
23
|
+
maxBodyLength?: number;
|
|
24
|
+
trackRedirects?: any;
|
|
25
|
+
};
|
|
26
|
+
export type Cb = (res: Response, stream?: stream.Readable) => void;
|
|
27
|
+
declare function request(uri: string | Opts, options?: Opts | Cb, callback?: Cb): Request;
|
|
3
28
|
declare namespace request {
|
|
4
|
-
export let get:
|
|
5
|
-
export let head:
|
|
6
|
-
export let options:
|
|
7
|
-
export let post:
|
|
8
|
-
export let put:
|
|
9
|
-
export let patch:
|
|
10
|
-
export let del:
|
|
11
|
-
let _delete:
|
|
29
|
+
export let get: (url: string | Opts, opts?: Opts | Cb, cb?: Cb) => void;
|
|
30
|
+
export let head: (url: string | Opts, opts?: Opts | Cb, cb?: Cb) => void;
|
|
31
|
+
export let options: (url: string | Opts, opts?: Opts | Cb, cb?: Cb) => void;
|
|
32
|
+
export let post: (url: string | Opts, opts?: Opts | Cb, cb?: Cb) => void;
|
|
33
|
+
export let put: (url: string | Opts, opts?: Opts | Cb, cb?: Cb) => void;
|
|
34
|
+
export let patch: (url: string | Opts, opts?: Opts | Cb, cb?: Cb) => void;
|
|
35
|
+
export let del: (url: string | Opts, opts?: Opts | Cb, cb?: Cb) => void;
|
|
36
|
+
let _delete: (url: string | Opts, opts?: Opts | Cb, cb?: Cb) => void;
|
|
12
37
|
export { _delete as delete };
|
|
13
38
|
}
|
|
39
|
+
import stream from 'node:stream';
|
|
14
40
|
import Request from './request.js';
|
package/types/request.d.ts
CHANGED
|
@@ -31,7 +31,8 @@ export default class Request extends stream.Duplex {
|
|
|
31
31
|
request(): http.ClientRequest;
|
|
32
32
|
abort(): void;
|
|
33
33
|
destroy(error: any): this;
|
|
34
|
-
|
|
34
|
+
send(): void;
|
|
35
|
+
override write(chunk: any, encoding?: BufferEncoding | ((error: Error | null) => void), cb?: (error: Error | null) => void): boolean;
|
|
35
36
|
override end(chunk?: any, encoding?: BufferEncoding | (() => void), cb?: () => void): this;
|
|
36
37
|
hasHeader(name: string): boolean;
|
|
37
38
|
getHeader(name: string): string;
|
|
@@ -42,7 +43,7 @@ export default class Request extends stream.Duplex {
|
|
|
42
43
|
sanitizeOptions(options: any): void;
|
|
43
44
|
processResponse(response: Response): void;
|
|
44
45
|
_isRedirect: boolean;
|
|
45
|
-
processStream(res:
|
|
46
|
+
processStream(res: Response): Response | stream.Readable;
|
|
46
47
|
override pipe<T>(dest: T & stream.Writable, opts?: {
|
|
47
48
|
end?: boolean;
|
|
48
49
|
}): T;
|
|
@@ -70,6 +71,7 @@ export type Opts = {
|
|
|
70
71
|
maxRedirects?: number;
|
|
71
72
|
maxBodyLength?: number;
|
|
72
73
|
trackRedirects?: any;
|
|
74
|
+
data?: any;
|
|
73
75
|
};
|
|
74
76
|
export type ResponseExt = {
|
|
75
77
|
redirects?: any[];
|
package/types/utils.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ declare namespace _default {
|
|
|
11
11
|
export { isObject };
|
|
12
12
|
export { isURL };
|
|
13
13
|
export { isReadStream };
|
|
14
|
+
export { isStream };
|
|
14
15
|
export { noop };
|
|
15
16
|
export { parseUrl };
|
|
16
17
|
export { spreadUrlObject };
|
|
@@ -38,6 +39,7 @@ declare function isFunction(thing: any): boolean;
|
|
|
38
39
|
declare function isObject(thing: any): boolean;
|
|
39
40
|
declare function isURL(value: any): boolean;
|
|
40
41
|
declare function isReadStream(rs: any): any;
|
|
42
|
+
declare function isStream(val: any): boolean;
|
|
41
43
|
declare function noop(): void;
|
|
42
44
|
declare function parseUrl(input: any): any;
|
|
43
45
|
declare function spreadUrlObject(urlObject: any, target: any): any;
|