@wiajs/request 3.0.28 → 3.0.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/request.cjs +160 -59
- package/dist/request.mjs +160 -59
- package/lib/index.js +77 -48
- package/lib/request.js +64 -12
- package/package.json +1 -1
- package/types/index.d.ts +35 -9
- package/types/request.d.ts +4 -2
- package/types/utils.d.ts +2 -0
package/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,37 @@ 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
|
+
log.error({
|
|
285
|
+
errcode: err.code
|
|
286
|
+
}, 'request');
|
|
287
|
+
switch(err.code){
|
|
288
|
+
case 'ENOTFOUND':
|
|
289
|
+
m.emit('error', new HostNotfoundError());
|
|
290
|
+
break;
|
|
291
|
+
case 'ECONNREFUSED':
|
|
292
|
+
m.emit('error', new ConnRefusedError());
|
|
293
|
+
break;
|
|
294
|
+
case 'ETIMEDOUT':
|
|
295
|
+
m.emit('error', new ConnTimedoutError());
|
|
296
|
+
break;
|
|
297
|
+
case 'ECONNRESET':
|
|
298
|
+
m.emit('error', new ConnResetError());
|
|
299
|
+
break;
|
|
300
|
+
default:
|
|
301
|
+
m.emit('error', utils.createErrorType('ERR_CONNOTHER', `网络错误: ${err.message}`));
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
// 接收req事件,转发 到 request 上发射,网络关闭事件,触发 error
|
|
270
305
|
for (const ev of writeEvents)req.on(ev, writeEventEmit[ev]);
|
|
271
306
|
// RFC7230§5.3.1: When making a request directly to an origin server, […]
|
|
272
307
|
// a client MUST send only the absolute path […] as the request-target.
|
|
@@ -302,9 +337,10 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
|
|
|
302
337
|
}
|
|
303
338
|
return R;
|
|
304
339
|
}
|
|
305
|
-
|
|
340
|
+
/**
|
|
341
|
+
* 写入错误,释放请求,触发 abort 终止事件
|
|
342
|
+
*/ abort() {
|
|
306
343
|
destroyRequest(this._currentRequest);
|
|
307
|
-
this._currentRequest.abort();
|
|
308
344
|
this.emit('abort');
|
|
309
345
|
}
|
|
310
346
|
/**
|
|
@@ -359,7 +395,11 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
|
|
|
359
395
|
const m = this;
|
|
360
396
|
// log({data: chunk, encoding, cb}, 'write')
|
|
361
397
|
// Writing is not allowed if end has been called
|
|
362
|
-
if (m._ending)
|
|
398
|
+
if (m._ending) {
|
|
399
|
+
// throw new WriteAfterEndError()
|
|
400
|
+
m.emit('error', new WriteAfterEndError());
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
363
403
|
// ! 数据写入时连接,pipe 时可设置 header
|
|
364
404
|
if (!m._currentRequest) m.request();
|
|
365
405
|
// Validate input and shift parameters if necessary
|
|
@@ -673,13 +713,15 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
|
|
|
673
713
|
/**
|
|
674
714
|
* 处理响应stream
|
|
675
715
|
* 自动解压,透传流,需设置 decompress = false,避免解压数据
|
|
676
|
-
* @param {
|
|
716
|
+
* @param {Response} res
|
|
717
|
+
* @returns {Response | stream.Readable}
|
|
677
718
|
*/ processStream(res) {
|
|
678
719
|
const m = this;
|
|
679
720
|
const { opt } = m;
|
|
680
721
|
const streams = [
|
|
681
722
|
res
|
|
682
723
|
];
|
|
724
|
+
let responseStream = res;
|
|
683
725
|
// 'transfer-encoding': 'chunked'时,无content-length,axios v1.2 不能自动解压
|
|
684
726
|
const responseLength = +res.headers['content-length'];
|
|
685
727
|
// log('processStream', {
|
|
@@ -707,19 +749,23 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
|
|
|
707
749
|
case 'compress':
|
|
708
750
|
case 'x-compress':
|
|
709
751
|
// add the unzipper to the body stream processing pipeline
|
|
752
|
+
// @ts-ignore
|
|
710
753
|
streams.push(zlib.createUnzip(zlibOptions));
|
|
711
754
|
// remove the content-encoding in order to not confuse downstream operations
|
|
712
755
|
res.headers['content-encoding'] = undefined;
|
|
713
756
|
break;
|
|
714
757
|
case 'deflate':
|
|
758
|
+
// @ts-ignore
|
|
715
759
|
streams.push(new ZlibTransform());
|
|
716
760
|
// add the unzipper to the body stream processing pipeline
|
|
761
|
+
// @ts-ignore
|
|
717
762
|
streams.push(zlib.createUnzip(zlibOptions));
|
|
718
763
|
// remove the content-encoding in order to not confuse downstream operations
|
|
719
764
|
res.headers['content-encoding'] = undefined;
|
|
720
765
|
break;
|
|
721
766
|
case 'br':
|
|
722
767
|
if (isBrotliSupported) {
|
|
768
|
+
// @ts-ignore
|
|
723
769
|
streams.push(zlib.createBrotliDecompress(brotliOptions));
|
|
724
770
|
res.headers['content-encoding'] = undefined;
|
|
725
771
|
}
|
|
@@ -728,9 +774,12 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
|
|
|
728
774
|
}
|
|
729
775
|
}
|
|
730
776
|
// 响应流,用于读
|
|
731
|
-
|
|
777
|
+
// @ts-ignore
|
|
778
|
+
responseStream = streams.length > 1 ? stream.pipeline(streams, utils.noop) : streams[0];
|
|
732
779
|
// 将内部 responseStream 可读流 映射到 redirectReq
|
|
780
|
+
// @ts-ignore
|
|
733
781
|
m.responseStream = responseStream;
|
|
782
|
+
// @ts-ignore
|
|
734
783
|
responseStream.redirectReq = m // 事情触发时引用
|
|
735
784
|
;
|
|
736
785
|
// stream 模式,事件透传到 请求类
|
|
@@ -880,7 +929,9 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
|
|
|
880
929
|
}
|
|
881
930
|
}
|
|
882
931
|
/**
|
|
883
|
-
*
|
|
932
|
+
* 释放请求,触发error事件
|
|
933
|
+
* 'error' event, and emit a 'close' event.
|
|
934
|
+
* Calling this will cause remaining data in the response to be dropped and the socket to be destroyed.
|
|
884
935
|
* @param {*} request
|
|
885
936
|
* @param {*} error
|
|
886
937
|
*/ function destroyRequest(request, error) {
|
|
@@ -888,7 +939,8 @@ const WriteAfterEndError = utils.createErrorType('ERR_STREAM_WRITE_AFTER_END', '
|
|
|
888
939
|
request.removeListener(ev, writeEventEmit[ev]);
|
|
889
940
|
}
|
|
890
941
|
request.on('error', utils.noop);
|
|
891
|
-
request.destroy(error)
|
|
942
|
+
request.destroy(error) // 触发 error 事件
|
|
943
|
+
;
|
|
892
944
|
}
|
|
893
945
|
/**
|
|
894
946
|
*
|
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;
|