@zwa73/utils 1.0.232 → 1.0.234
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/UtilHttp.d.ts +117 -98
- package/dist/UtilHttp.js +171 -136
- package/package.json +1 -1
package/dist/UtilHttp.d.ts
CHANGED
|
@@ -2,7 +2,6 @@ import { AnyString, JToken, MPromise, PartialOption, StatusVerifyFn } from "./Ut
|
|
|
2
2
|
import http from 'http';
|
|
3
3
|
import { PromiseRetries } from "./UtilFunctions";
|
|
4
4
|
import FormData from "form-data";
|
|
5
|
-
import { RequiredOnly } from "@zwa73/js-utils";
|
|
6
5
|
/**网络请求返回值 */
|
|
7
6
|
export type RequestResult<T> = {
|
|
8
7
|
/**响应头 */
|
|
@@ -39,34 +38,41 @@ export type RequestOption = {
|
|
|
39
38
|
/**getquery请求所允许的数据 */
|
|
40
39
|
export type QueryRequestData = NodeJS.Dict<string | number | boolean | readonly string[] | readonly number[] | readonly boolean[] | null>;
|
|
41
40
|
/**请求处理函数 需调用req.end() */
|
|
42
|
-
export type RequestProcFn = (
|
|
41
|
+
export type RequestProcFn = (req: http.ClientRequest) => MPromise<void>;
|
|
42
|
+
/**结果处理函数 */
|
|
43
|
+
export type RequestParseFn<D, R> = (result: RequestResult<D> | undefined) => MPromise<R>;
|
|
43
44
|
/**数据处理函数 */
|
|
44
45
|
export type RequestReduceFn<T> = (acc: T, data: string) => MPromise<T>;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
type
|
|
53
|
-
init: D
|
|
54
|
-
reduce
|
|
55
|
-
parse:
|
|
46
|
+
/**数据初始化函数 */
|
|
47
|
+
export type RequestInitFn<T> = (res: http.IncomingMessage) => MPromise<T>;
|
|
48
|
+
/**accept处理数据
|
|
49
|
+
* @template D - 接受时转换的数据类型
|
|
50
|
+
* @template R - 完成处理的数据类型
|
|
51
|
+
*/
|
|
52
|
+
type AcceptProcCtor<D, R, T extends {}> = AcceptProcData<D, R> | ((arg: T) => MPromise<AcceptProcData<D, R>>);
|
|
53
|
+
type AcceptProcData<D, R> = {
|
|
54
|
+
init: RequestInitFn<D>;
|
|
55
|
+
reduce?: RequestReduceFn<D>;
|
|
56
|
+
parse: RequestParseFn<D, R>;
|
|
56
57
|
};
|
|
57
58
|
/**send处理数据 */
|
|
58
|
-
type
|
|
59
|
-
|
|
59
|
+
type SendProcCtor<T extends {}> = SendProcData | ((opt: RequestOption, arg: T) => MPromise<SendProcData>);
|
|
60
|
+
type SendProcData = {
|
|
61
|
+
proc: RequestProcFn;
|
|
60
62
|
};
|
|
61
|
-
declare const SendNoneProc:
|
|
62
|
-
declare const AcceptStringProc:
|
|
63
|
-
declare const AcceptNoneProc:
|
|
63
|
+
declare const SendNoneProc: SendProcCtor<{}>;
|
|
64
|
+
declare const AcceptStringProc: AcceptProcCtor<string, RequestResult<string> | undefined, {}>;
|
|
65
|
+
declare const AcceptNoneProc: AcceptProcCtor<undefined, RequestResult<undefined> | undefined, {}>;
|
|
64
66
|
/**send处理的参数 */
|
|
65
|
-
type SendParams<
|
|
67
|
+
type SendParams<S extends SendProcCtor<any>> = S extends SendProcCtor<infer P> ? P : never;
|
|
68
|
+
/**send处理的参数 */
|
|
69
|
+
type AcceptParams<A extends AcceptProcCtor<any, any, any>> = A extends AcceptProcCtor<any, any, infer P> ? P : never;
|
|
70
|
+
type HasConflict<A, B> = keyof A & keyof B extends never ? false : true;
|
|
71
|
+
type ConflictCheck<A, B, C> = HasConflict<A, B> extends true ? A & B & C & Error & "❌ A 与 B 有字段冲突" : HasConflict<A, C> extends true ? A & B & C & Error & "❌ A 与 C 有字段冲突" : HasConflict<B, C> extends true ? A & B & C & Error & "❌ B 与 C 有字段冲突" : A & B & C;
|
|
66
72
|
/**accept处理的结果 */
|
|
67
|
-
type ParseResult<P extends
|
|
73
|
+
type ParseResult<P extends AcceptProcCtor<any, any, any>> = P extends AcceptProcCtor<any, infer T, any> ? Awaited<T> : never;
|
|
68
74
|
/**http请求工具 */
|
|
69
|
-
export declare class UtilHttp<D extends Partial<RequestOption> & Required<Pick<RequestOption, 'protocol'>>, S extends
|
|
75
|
+
export declare class UtilHttp<D extends Partial<RequestOption> & Required<Pick<RequestOption, 'protocol'>>, S extends SendProcCtor<any>, A extends AcceptProcCtor<any, any, any>> {
|
|
70
76
|
private _data;
|
|
71
77
|
private _send;
|
|
72
78
|
private _accept;
|
|
@@ -74,11 +80,11 @@ export declare class UtilHttp<D extends Partial<RequestOption> & Required<Pick<R
|
|
|
74
80
|
/**设为https请求 */
|
|
75
81
|
static https(): UtilHttp<{
|
|
76
82
|
readonly protocol: "https:";
|
|
77
|
-
},
|
|
83
|
+
}, SendProcCtor<{}>, AcceptProcCtor<string, RequestResult<string> | undefined, {}>>;
|
|
78
84
|
/**设为http请求 */
|
|
79
85
|
static http(): UtilHttp<{
|
|
80
86
|
readonly protocol: "http:";
|
|
81
|
-
},
|
|
87
|
+
}, SendProcCtor<{}>, AcceptProcCtor<string, RequestResult<string> | undefined, {}>>;
|
|
82
88
|
/**从url创建 */
|
|
83
89
|
static url(urlStr: `${'http:' | 'https:'}//${string}`): UtilHttp<{
|
|
84
90
|
protocol: "http:" | "https:";
|
|
@@ -86,7 +92,7 @@ export declare class UtilHttp<D extends Partial<RequestOption> & Required<Pick<R
|
|
|
86
92
|
hostname: string;
|
|
87
93
|
path: string;
|
|
88
94
|
port: number | undefined;
|
|
89
|
-
},
|
|
95
|
+
}, SendProcCtor<{}>, AcceptProcCtor<string, RequestResult<string> | undefined, {}>>;
|
|
90
96
|
/**设为get方式的请求 */
|
|
91
97
|
get(): UtilHttp<D & {
|
|
92
98
|
method: "GET";
|
|
@@ -100,11 +106,6 @@ export declare class UtilHttp<D extends Partial<RequestOption> & Required<Pick<R
|
|
|
100
106
|
* 将会替换对应字段, 修改headers请用header函数
|
|
101
107
|
*/
|
|
102
108
|
option<OPT extends Partial<RequestOption>>(option: OPT): UtilHttp<D & OPT, S, A>;
|
|
103
|
-
/**完成参数
|
|
104
|
-
* 会检查必要参数完整性
|
|
105
|
-
* 将会替换对应字段, 修改headers请用header函数
|
|
106
|
-
*/
|
|
107
|
-
finalize<OPT extends PartialOption<RequestOption, D>>(option: OPT): UtilHttp<D & OPT, S, A>;
|
|
108
109
|
/**补充header */
|
|
109
110
|
header<HAD extends http.OutgoingHttpHeaders>(headers: HAD): UtilHttp<D & {
|
|
110
111
|
headers: HAD;
|
|
@@ -120,7 +121,10 @@ export declare class UtilHttp<D extends Partial<RequestOption> & Required<Pick<R
|
|
|
120
121
|
headers: {
|
|
121
122
|
"Content-Type": "application/json";
|
|
122
123
|
};
|
|
123
|
-
},
|
|
124
|
+
}, (opt: RequestOption, arg: {
|
|
125
|
+
/**发送的json */
|
|
126
|
+
json: JToken;
|
|
127
|
+
}) => MPromise<SendProcData>, AcceptProcData<string, RequestResult<JToken> | undefined>>;
|
|
124
128
|
/**收发皆为json的post预设 */
|
|
125
129
|
postJson(): UtilHttp<D & {
|
|
126
130
|
method: "POST";
|
|
@@ -128,15 +132,21 @@ export declare class UtilHttp<D extends Partial<RequestOption> & Required<Pick<R
|
|
|
128
132
|
headers: {
|
|
129
133
|
'Content-Type': "application/json";
|
|
130
134
|
};
|
|
131
|
-
},
|
|
135
|
+
}, (opt: RequestOption, arg: {
|
|
136
|
+
/**发送的json */
|
|
137
|
+
json: JToken;
|
|
138
|
+
}) => MPromise<SendProcData>, AcceptProcData<string, RequestResult<JToken> | undefined>>;
|
|
132
139
|
/**无查询参数获取json的get预设 */
|
|
133
140
|
getJson(): UtilHttp<D & {
|
|
134
141
|
method: "GET";
|
|
135
|
-
},
|
|
142
|
+
}, SendProcCtor<{}>, AcceptProcData<string, RequestResult<JToken> | undefined>>;
|
|
136
143
|
/**有查询参数获取json的get预设 */
|
|
137
144
|
queryJson(): UtilHttp<D & {
|
|
138
145
|
method: "GET";
|
|
139
|
-
},
|
|
146
|
+
}, (opt: RequestOption, arg: {
|
|
147
|
+
/**附加的查询表单数据 */
|
|
148
|
+
query: QueryRequestData;
|
|
149
|
+
}) => MPromise<SendProcData>, AcceptProcData<string, RequestResult<JToken> | undefined>>;
|
|
140
150
|
/**收发皆为json的https-post预设 */
|
|
141
151
|
static httpsPostJson(): UtilHttp<{
|
|
142
152
|
readonly protocol: "https:";
|
|
@@ -146,7 +156,10 @@ export declare class UtilHttp<D extends Partial<RequestOption> & Required<Pick<R
|
|
|
146
156
|
headers: {
|
|
147
157
|
'Content-Type': "application/json";
|
|
148
158
|
};
|
|
149
|
-
},
|
|
159
|
+
}, (opt: RequestOption, arg: {
|
|
160
|
+
/**发送的json */
|
|
161
|
+
json: JToken;
|
|
162
|
+
}) => MPromise<SendProcData>, AcceptProcData<string, RequestResult<JToken> | undefined>>;
|
|
150
163
|
/**收发皆为json的http-post预设 */
|
|
151
164
|
static httpPostJson(): UtilHttp<{
|
|
152
165
|
readonly protocol: "http:";
|
|
@@ -156,67 +169,57 @@ export declare class UtilHttp<D extends Partial<RequestOption> & Required<Pick<R
|
|
|
156
169
|
headers: {
|
|
157
170
|
'Content-Type': "application/json";
|
|
158
171
|
};
|
|
159
|
-
},
|
|
172
|
+
}, (opt: RequestOption, arg: {
|
|
173
|
+
/**发送的json */
|
|
174
|
+
json: JToken;
|
|
175
|
+
}) => MPromise<SendProcData>, AcceptProcData<string, RequestResult<JToken> | undefined>>;
|
|
160
176
|
/**无查询参数获取json的https-get预设 */
|
|
161
177
|
static httpsGetJson(): UtilHttp<{
|
|
162
178
|
readonly protocol: "https:";
|
|
163
179
|
} & {
|
|
164
180
|
method: "GET";
|
|
165
|
-
},
|
|
181
|
+
}, SendProcCtor<{}>, AcceptProcData<string, RequestResult<JToken> | undefined>>;
|
|
166
182
|
/**有查询参数获取json的https-get预设 */
|
|
167
183
|
static httpsQueryJson(): UtilHttp<{
|
|
168
184
|
readonly protocol: "http:";
|
|
169
185
|
} & {
|
|
170
186
|
method: "GET";
|
|
171
|
-
},
|
|
187
|
+
}, (opt: RequestOption, arg: {
|
|
188
|
+
/**附加的查询表单数据 */
|
|
189
|
+
query: QueryRequestData;
|
|
190
|
+
}) => MPromise<SendProcData>, AcceptProcData<string, RequestResult<JToken> | undefined>>;
|
|
172
191
|
/**无查询参数获取json的http-get预设 */
|
|
173
192
|
static httpGetJson(): UtilHttp<{
|
|
174
193
|
readonly protocol: "http:";
|
|
175
194
|
} & {
|
|
176
195
|
method: "GET";
|
|
177
|
-
},
|
|
196
|
+
}, SendProcCtor<{}>, AcceptProcData<string, RequestResult<JToken> | undefined>>;
|
|
178
197
|
/**有查询参数获取json的http-get预设 */
|
|
179
198
|
static httpQueryJson(): UtilHttp<{
|
|
180
199
|
readonly protocol: "http:";
|
|
181
200
|
} & {
|
|
182
201
|
method: "GET";
|
|
183
|
-
},
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
readonly none: UtilHttp<D, S, AcceptProc<undefined, undefined>>;
|
|
189
|
-
}[T];
|
|
190
|
-
acceptJson(): UtilHttp<D, S, AcceptProc<string, RequestResult<JToken> | undefined>>;
|
|
202
|
+
}, (opt: RequestOption, arg: {
|
|
203
|
+
/**附加的查询表单数据 */
|
|
204
|
+
query: QueryRequestData;
|
|
205
|
+
}) => MPromise<SendProcData>, AcceptProcData<string, RequestResult<JToken> | undefined>>;
|
|
206
|
+
acceptJson(): UtilHttp<D, S, AcceptProcData<string, RequestResult<JToken> | undefined>>;
|
|
191
207
|
acceptString(): UtilHttp<D, S, typeof AcceptStringProc>;
|
|
192
208
|
acceptNone(): UtilHttp<D, S, typeof AcceptNoneProc>;
|
|
209
|
+
acceptFile(): UtilHttp<D, S, (arg: {
|
|
210
|
+
acceptFilepath: string;
|
|
211
|
+
}) => MPromise<AcceptProcData<{
|
|
212
|
+
promise: Promise<boolean>;
|
|
213
|
+
}, {
|
|
214
|
+
/**响应头 */
|
|
215
|
+
headers: http.IncomingHttpHeaders;
|
|
216
|
+
/**响应状态码 */
|
|
217
|
+
statusCode?: number;
|
|
218
|
+
/**保存文件路径 */
|
|
219
|
+
filepath: string;
|
|
220
|
+
} | undefined>>>;
|
|
193
221
|
/**自定的接收数据类型*/
|
|
194
|
-
acceptRaw<AD, AT>(proc:
|
|
195
|
-
/**预设的发送数据类型 */
|
|
196
|
-
send<T extends SendType>(t: T): {
|
|
197
|
-
readonly json: UtilHttp<D & {
|
|
198
|
-
headers: {
|
|
199
|
-
"Content-Type": "application/json";
|
|
200
|
-
};
|
|
201
|
-
}, SendProc<[JToken]>, A>;
|
|
202
|
-
readonly query: UtilHttp<D, SendProc<[QueryRequestData]>, A>;
|
|
203
|
-
readonly formData: UtilHttp<D & {
|
|
204
|
-
headers: {
|
|
205
|
-
"Content-Type": "multipart/form-data";
|
|
206
|
-
};
|
|
207
|
-
}, SendProc<[FormData]>, A>;
|
|
208
|
-
readonly form: UtilHttp<D & {
|
|
209
|
-
headers: {
|
|
210
|
-
"Content-Type": "application/x-www-form-urlencoded";
|
|
211
|
-
};
|
|
212
|
-
}, SendProc<[QueryRequestData]>, A>;
|
|
213
|
-
readonly file: UtilHttp<D & {
|
|
214
|
-
headers: {
|
|
215
|
-
"Content-Type": "multipart/form-data";
|
|
216
|
-
};
|
|
217
|
-
}, SendProc<[string, (string | undefined)?]>, A>;
|
|
218
|
-
readonly none: UtilHttp<D, SendProc<[]>, A>;
|
|
219
|
-
}[T];
|
|
222
|
+
acceptRaw<AD, AR, AT extends {}>(proc: AcceptProcCtor<AD, AR, AT>): UtilHttp<D, S, typeof proc>;
|
|
220
223
|
/**发送json
|
|
221
224
|
* 请求参数为 (token:JToken)
|
|
222
225
|
*/
|
|
@@ -224,58 +227,74 @@ export declare class UtilHttp<D extends Partial<RequestOption> & Required<Pick<R
|
|
|
224
227
|
headers: {
|
|
225
228
|
"Content-Type": "application/json";
|
|
226
229
|
};
|
|
227
|
-
},
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
230
|
+
}, (opt: RequestOption, arg: {
|
|
231
|
+
/**发送的json */
|
|
232
|
+
json: JToken;
|
|
233
|
+
}) => MPromise<SendProcData>, A>;
|
|
234
|
+
/**利用 appendQuery 直接将表单附加在path上发送请求 */
|
|
235
|
+
sendQuery(): UtilHttp<D, (opt: RequestOption, arg: {
|
|
236
|
+
/**附加的查询表单数据 */
|
|
237
|
+
query: QueryRequestData;
|
|
238
|
+
}) => MPromise<SendProcData>, A>;
|
|
239
|
+
/**发送form-data包提供的表单数据 */
|
|
235
240
|
sendFormData(): UtilHttp<D & {
|
|
236
241
|
headers: {
|
|
237
242
|
"Content-Type": "multipart/form-data";
|
|
238
243
|
};
|
|
239
|
-
},
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
244
|
+
}, (opt: RequestOption, arg: {
|
|
245
|
+
/**form-data包提供的FormData表单数据 */
|
|
246
|
+
formdata: FormData;
|
|
247
|
+
}) => MPromise<SendProcData>, A>;
|
|
248
|
+
/**发送表单 */
|
|
243
249
|
sendForm(): UtilHttp<D & {
|
|
244
250
|
headers: {
|
|
245
251
|
"Content-Type": "application/x-www-form-urlencoded";
|
|
246
252
|
};
|
|
247
|
-
},
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
253
|
+
}, (opt: RequestOption, arg: {
|
|
254
|
+
/**表单 */
|
|
255
|
+
form: QueryRequestData;
|
|
256
|
+
}) => MPromise<SendProcData>, A>;
|
|
257
|
+
/**发送文件 */
|
|
251
258
|
sendFile(): UtilHttp<D & {
|
|
252
259
|
headers: {
|
|
253
260
|
"Content-Type": "multipart/form-data";
|
|
254
261
|
};
|
|
255
|
-
},
|
|
262
|
+
}, (opt: RequestOption, arg: {
|
|
263
|
+
/**文件路径 */
|
|
264
|
+
filepath: string;
|
|
265
|
+
/**文件名 */
|
|
266
|
+
filename?: string;
|
|
267
|
+
}) => MPromise<SendProcData>, A>;
|
|
256
268
|
sendNone(): UtilHttp<D, typeof SendNoneProc, A>;
|
|
257
269
|
/**自定的发送数据类型 */
|
|
258
|
-
sendRaw<T extends any[]>(proc:
|
|
270
|
+
sendRaw<T extends any[]>(proc: SendProcCtor<T>): UtilHttp<D, typeof proc, A>;
|
|
259
271
|
/**发送请求
|
|
260
272
|
* @param datas - 数据对象
|
|
261
273
|
*/
|
|
262
|
-
once
|
|
274
|
+
once<OPT extends PartialOption<RequestOption, D>>(arg: ConflictCheck<SendParams<S>, AcceptParams<A>, ({} extends OPT ? {
|
|
275
|
+
option?: OPT;
|
|
276
|
+
} : {
|
|
277
|
+
option: OPT;
|
|
278
|
+
})>): Promise<ParseResult<A>>;
|
|
263
279
|
/**重复发送网络请求
|
|
264
280
|
* @param verify - 有效性验证函数
|
|
265
281
|
* @param retries - 重试选项 默认 延迟:1000ms 间隔:180_000ms 重试:3次
|
|
266
282
|
* @param datas - 数据对象
|
|
267
283
|
*/
|
|
268
|
-
retry(
|
|
284
|
+
retry<OPT extends PartialOption<RequestOption, D>>(arg: ConflictCheck<SendParams<S>, AcceptParams<A>, {
|
|
269
285
|
verify?: StatusVerifyFn<ParseResult<A>>;
|
|
270
286
|
retries?: PromiseRetries;
|
|
271
|
-
}
|
|
287
|
+
} & ({} extends OPT ? {
|
|
288
|
+
option?: OPT;
|
|
289
|
+
} : {
|
|
290
|
+
option: OPT;
|
|
291
|
+
})>): Promise<import("@zwa73/js-utils").PromiseRetryResult<ParseResult<A>>>;
|
|
272
292
|
/**发送网络请求
|
|
273
|
-
* @param option
|
|
274
|
-
* @param
|
|
275
|
-
* @param
|
|
276
|
-
* @param init - 初始数据
|
|
293
|
+
* @param option - 网络请求选项
|
|
294
|
+
* @param reqProc - 请求处理函数 需调用req.end()
|
|
295
|
+
* @param acceptProc - 响应处理数据
|
|
277
296
|
*/
|
|
278
|
-
static request<T>(option: RequestOption,
|
|
297
|
+
static request<T>(option: RequestOption, sendProc: SendProcData, acceptProc: Omit<AcceptProcData<T, unknown>, 'parse'>): Promise<RequestResult<T> | undefined>;
|
|
279
298
|
/**构建query */
|
|
280
299
|
static buildQuery(base: string, data: QueryRequestData): string;
|
|
281
300
|
}
|
package/dist/UtilHttp.js
CHANGED
|
@@ -16,20 +16,29 @@ const https_proxy_agent_1 = __importDefault(require("https-proxy-agent"));
|
|
|
16
16
|
const js_utils_1 = require("@zwa73/js-utils");
|
|
17
17
|
const fs_1 = __importDefault(require("fs"));
|
|
18
18
|
const pathe_1 = __importDefault(require("pathe"));
|
|
19
|
-
const AcceptTypeList = ["json", "string"];
|
|
20
|
-
const SendTypeList = ["json", "query", "formData", "none"];
|
|
21
19
|
const SendNoneProc = {
|
|
22
|
-
proc:
|
|
20
|
+
proc: req => void req.end()
|
|
23
21
|
};
|
|
24
22
|
const AcceptStringProc = {
|
|
25
|
-
init: '',
|
|
23
|
+
init: () => '',
|
|
26
24
|
reduce: (acc, dat) => acc + dat,
|
|
27
|
-
parse:
|
|
25
|
+
parse: result => {
|
|
26
|
+
if (result == undefined) {
|
|
27
|
+
UtilLogger_1.SLogger.warn(`accept json 接收反馈错误: 响应结果无效`);
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
28
32
|
};
|
|
29
33
|
const AcceptNoneProc = {
|
|
30
|
-
init: undefined,
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
init: () => undefined,
|
|
35
|
+
parse: result => {
|
|
36
|
+
if (result == undefined) {
|
|
37
|
+
UtilLogger_1.SLogger.warn(`accept none 接收反馈错误: 响应结果无效`);
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
33
42
|
};
|
|
34
43
|
/**http请求工具 */
|
|
35
44
|
class UtilHttp {
|
|
@@ -80,14 +89,6 @@ class UtilHttp {
|
|
|
80
89
|
this._data = { ...this._data, ...option };
|
|
81
90
|
return this;
|
|
82
91
|
}
|
|
83
|
-
/**完成参数
|
|
84
|
-
* 会检查必要参数完整性
|
|
85
|
-
* 将会替换对应字段, 修改headers请用header函数
|
|
86
|
-
*/
|
|
87
|
-
finalize(option) {
|
|
88
|
-
this._data = { ...this._data, ...option };
|
|
89
|
-
return this;
|
|
90
|
-
}
|
|
91
92
|
/**补充header */
|
|
92
93
|
header(headers) {
|
|
93
94
|
this._data.headers = {
|
|
@@ -157,41 +158,32 @@ class UtilHttp {
|
|
|
157
158
|
}
|
|
158
159
|
//#endregion
|
|
159
160
|
//#region 接收数据类型
|
|
160
|
-
/**预设的接收数据类型*/
|
|
161
|
-
accept(t) {
|
|
162
|
-
const map = {
|
|
163
|
-
'json': this.acceptJson(),
|
|
164
|
-
'string': this.acceptString(),
|
|
165
|
-
'none': this.acceptNone(),
|
|
166
|
-
};
|
|
167
|
-
return map[t];
|
|
168
|
-
}
|
|
169
161
|
acceptJson() {
|
|
170
|
-
const
|
|
171
|
-
init: '',
|
|
162
|
+
const acceptProc = {
|
|
163
|
+
init: () => '',
|
|
172
164
|
reduce: (acc, curr) => acc + curr,
|
|
173
|
-
parse:
|
|
165
|
+
parse: result => {
|
|
174
166
|
if (result == undefined) {
|
|
175
|
-
UtilLogger_1.SLogger.warn(`json
|
|
167
|
+
UtilLogger_1.SLogger.warn(`accept json 接收反馈错误: 响应结果无效`);
|
|
176
168
|
return undefined;
|
|
177
169
|
}
|
|
178
170
|
const { data, ...rest } = result;
|
|
179
171
|
if (data.trim() == "") {
|
|
180
|
-
UtilLogger_1.SLogger.warn(`json
|
|
172
|
+
UtilLogger_1.SLogger.warn(`accept json 接收反馈错误: 原始字符串为空`, UtilFunctions_1.UtilFunc.stringifyJToken(result, { compress: true, space: 2 }));
|
|
181
173
|
return { ...result, raw: "", data: null };
|
|
182
174
|
}
|
|
183
175
|
try {
|
|
184
176
|
const obj = JSON.parse(data.trim());
|
|
185
|
-
UtilLogger_1.SLogger.http(`json
|
|
177
|
+
UtilLogger_1.SLogger.http(`accept json 接受信息 data:`, UtilFunctions_1.UtilFunc.stringifyJToken(obj, { compress: true, space: 2 }), `result:`, UtilFunctions_1.UtilFunc.stringifyJToken(rest, { compress: true, space: 2 }));
|
|
186
178
|
return { ...rest, data: obj };
|
|
187
179
|
}
|
|
188
180
|
catch (err) {
|
|
189
|
-
UtilLogger_1.SLogger.warn(`json
|
|
181
|
+
UtilLogger_1.SLogger.warn(`accept json 接收反馈错误:`, err, UtilFunctions_1.UtilFunc.stringifyJToken(result, { compress: true, space: 2 }));
|
|
190
182
|
return { ...result, raw: data, data: null };
|
|
191
183
|
}
|
|
192
184
|
}
|
|
193
185
|
};
|
|
194
|
-
this._accept =
|
|
186
|
+
this._accept = acceptProc;
|
|
195
187
|
return this;
|
|
196
188
|
}
|
|
197
189
|
acceptString() {
|
|
@@ -202,6 +194,36 @@ class UtilHttp {
|
|
|
202
194
|
this._accept = AcceptNoneProc;
|
|
203
195
|
return this;
|
|
204
196
|
}
|
|
197
|
+
acceptFile() {
|
|
198
|
+
const acceptProc = (arg) => ({
|
|
199
|
+
init: res => {
|
|
200
|
+
const fileStream = fs_1.default.createWriteStream(arg.acceptFilepath);
|
|
201
|
+
const fileWritePromise = new Promise((resolve) => {
|
|
202
|
+
fileStream.on('error', err => {
|
|
203
|
+
UtilLogger_1.SLogger.warn(`accept file 文件流写入错误:`, err);
|
|
204
|
+
resolve(false); // 标记写入已结束, 但失败
|
|
205
|
+
});
|
|
206
|
+
fileStream.on('finish', () => {
|
|
207
|
+
resolve(true); // 标记写入成功
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
res.pipe(fileStream);
|
|
211
|
+
return { promise: fileWritePromise };
|
|
212
|
+
},
|
|
213
|
+
parse: async (result) => {
|
|
214
|
+
if (result == undefined) {
|
|
215
|
+
UtilLogger_1.SLogger.warn(`accept file 接收反馈错误: 响应结果无效`);
|
|
216
|
+
return undefined;
|
|
217
|
+
}
|
|
218
|
+
const success = await result.data.promise;
|
|
219
|
+
if (!success)
|
|
220
|
+
return undefined;
|
|
221
|
+
return { ...result, filepath: arg.acceptFilepath };
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
this._accept = acceptProc;
|
|
225
|
+
return this;
|
|
226
|
+
}
|
|
205
227
|
/**自定的接收数据类型*/
|
|
206
228
|
acceptRaw(proc) {
|
|
207
229
|
this._accept = proc;
|
|
@@ -209,113 +231,99 @@ class UtilHttp {
|
|
|
209
231
|
}
|
|
210
232
|
//#endregion
|
|
211
233
|
//#region 发送数据类型
|
|
212
|
-
/**预设的发送数据类型 */
|
|
213
|
-
send(t) {
|
|
214
|
-
const map = {
|
|
215
|
-
'json': this.sendJson(),
|
|
216
|
-
'query': this.sendQuery(),
|
|
217
|
-
'formData': this.sendFormData(),
|
|
218
|
-
'form': this.sendForm(),
|
|
219
|
-
'file': this.sendFile(),
|
|
220
|
-
'none': this.sendNone(),
|
|
221
|
-
};
|
|
222
|
-
return map[t];
|
|
223
|
-
}
|
|
224
234
|
/**发送json
|
|
225
235
|
* 请求参数为 (token:JToken)
|
|
226
236
|
*/
|
|
227
237
|
sendJson() {
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
238
|
+
const sendProc = (opt, arg) => {
|
|
239
|
+
const { method } = opt;
|
|
240
|
+
const isPost = (method == "POST");
|
|
241
|
+
const data = JSON.stringify(arg.json);
|
|
242
|
+
this._data.headers ??= {};
|
|
243
|
+
this._data.headers['Content-Length'] = Buffer.byteLength(data);
|
|
244
|
+
return {
|
|
245
|
+
proc: req => {
|
|
236
246
|
if (isPost)
|
|
237
247
|
req.write(data);
|
|
238
248
|
req.end();
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
}
|
|
249
|
+
}
|
|
250
|
+
};
|
|
242
251
|
};
|
|
243
|
-
this._send =
|
|
252
|
+
this._send = sendProc;
|
|
244
253
|
this._data.headers ??= {};
|
|
245
254
|
this._data.headers['Content-Type'] = 'application/json';
|
|
246
255
|
return this;
|
|
247
256
|
}
|
|
248
|
-
/**利用 appendQuery
|
|
249
|
-
* 请求参数为 (form:QueryRequestData)
|
|
250
|
-
*/
|
|
257
|
+
/**利用 appendQuery 直接将表单附加在path上发送请求 */
|
|
251
258
|
sendQuery() {
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
}
|
|
259
|
+
const sendProc = (opt, arg) => {
|
|
260
|
+
opt.path = UtilHttp.buildQuery(opt.path ?? '', arg.query);
|
|
261
|
+
return {
|
|
262
|
+
proc: req => void req.end()
|
|
263
|
+
};
|
|
258
264
|
};
|
|
259
|
-
this._send =
|
|
265
|
+
this._send = sendProc;
|
|
260
266
|
return this;
|
|
261
267
|
}
|
|
262
|
-
|
|
263
|
-
* 请求参数为 (formData: FormData)
|
|
264
|
-
*/
|
|
268
|
+
/**发送form-data包提供的表单数据 */
|
|
265
269
|
sendFormData() {
|
|
266
|
-
const
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
270
|
+
const sendProc = (opt, arg) => {
|
|
271
|
+
const { method } = opt;
|
|
272
|
+
const isPost = (method == "POST");
|
|
273
|
+
opt.headers = arg.formdata.getHeaders();
|
|
274
|
+
return {
|
|
275
|
+
proc: (req) => {
|
|
276
|
+
if (isPost)
|
|
277
|
+
arg.formdata.pipe(req);
|
|
278
|
+
else
|
|
279
|
+
req.end();
|
|
280
|
+
}
|
|
281
|
+
};
|
|
274
282
|
};
|
|
275
|
-
this._send =
|
|
283
|
+
this._send = sendProc;
|
|
276
284
|
this._data.headers ??= {};
|
|
277
285
|
this._data.headers['Content-Type'] = 'multipart/form-data';
|
|
278
286
|
return this;
|
|
279
287
|
}
|
|
280
|
-
/**发送表单
|
|
281
|
-
* 请求参数为 (form:QueryRequestData)
|
|
282
|
-
*/
|
|
288
|
+
/**发送表单 */
|
|
283
289
|
sendForm() {
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
290
|
+
const snedProc = (opt, arg) => {
|
|
291
|
+
const { method } = opt;
|
|
292
|
+
const isPost = (method == "POST");
|
|
293
|
+
const data = querystring_1.default.stringify(arg.form);
|
|
294
|
+
this._data.headers ??= {};
|
|
295
|
+
this._data.headers['Content-Length'] = Buffer.byteLength(data);
|
|
296
|
+
return {
|
|
297
|
+
proc: req => {
|
|
292
298
|
if (isPost)
|
|
293
299
|
req.write(data);
|
|
294
300
|
req.end();
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
}
|
|
301
|
+
}
|
|
302
|
+
};
|
|
298
303
|
};
|
|
299
|
-
this._send =
|
|
304
|
+
this._send = snedProc;
|
|
300
305
|
this._data.headers ??= {};
|
|
301
306
|
this._data.headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
|
302
307
|
return this;
|
|
303
308
|
}
|
|
304
|
-
/**发送文件
|
|
305
|
-
* 请求参数为 (filepath:string, filename?: string)
|
|
306
|
-
*/
|
|
309
|
+
/**发送文件 */
|
|
307
310
|
sendFile() {
|
|
308
|
-
const proc = {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
311
|
+
const proc = (opt, arg) => {
|
|
312
|
+
const { method } = opt;
|
|
313
|
+
const isPost = (method == "POST");
|
|
314
|
+
let { filepath, filename } = arg;
|
|
315
|
+
const formData = new form_data_1.default();
|
|
316
|
+
filename = filename ?? pathe_1.default.basename(filepath);
|
|
317
|
+
formData.append(filename, fs_1.default.createReadStream(filepath));
|
|
318
|
+
opt.headers = formData.getHeaders();
|
|
319
|
+
return {
|
|
320
|
+
proc: req => {
|
|
321
|
+
if (isPost)
|
|
322
|
+
formData.pipe(req);
|
|
323
|
+
else
|
|
324
|
+
req.end();
|
|
325
|
+
}
|
|
326
|
+
};
|
|
319
327
|
};
|
|
320
328
|
this._send = proc;
|
|
321
329
|
this._data.headers ??= {};
|
|
@@ -335,11 +343,15 @@ class UtilHttp {
|
|
|
335
343
|
/**发送请求
|
|
336
344
|
* @param datas - 数据对象
|
|
337
345
|
*/
|
|
338
|
-
async once(
|
|
339
|
-
const fullopt = this._data;
|
|
340
|
-
const
|
|
341
|
-
|
|
342
|
-
|
|
346
|
+
async once(arg) {
|
|
347
|
+
const fullopt = { ...this._data, ...arg.option ?? {} };
|
|
348
|
+
const sendProc = typeof this._send === 'function'
|
|
349
|
+
? await this._send(fullopt, arg)
|
|
350
|
+
: this._send;
|
|
351
|
+
const { parse, ...acceptProc } = typeof this._accept === 'function'
|
|
352
|
+
? await this._accept(arg)
|
|
353
|
+
: this._accept;
|
|
354
|
+
const res = await UtilHttp.request(fullopt, sendProc, acceptProc);
|
|
343
355
|
return parse(res);
|
|
344
356
|
}
|
|
345
357
|
/**重复发送网络请求
|
|
@@ -347,20 +359,21 @@ class UtilHttp {
|
|
|
347
359
|
* @param retries - 重试选项 默认 延迟:1000ms 间隔:180_000ms 重试:3次
|
|
348
360
|
* @param datas - 数据对象
|
|
349
361
|
*/
|
|
350
|
-
async retry(
|
|
351
|
-
let { retries, verify } =
|
|
362
|
+
async retry(arg) {
|
|
363
|
+
let { retries, verify } = arg;
|
|
352
364
|
retries ??= {};
|
|
353
365
|
retries.tryDelay = retries.tryDelay ?? 1000;
|
|
354
|
-
const procFn = async () => this.once(
|
|
366
|
+
const procFn = async () => this.once(arg);
|
|
355
367
|
return UtilFunctions_1.UtilFunc.retryPromise(procFn, verify, retries);
|
|
356
368
|
}
|
|
357
369
|
/**发送网络请求
|
|
358
|
-
* @param option
|
|
359
|
-
* @param
|
|
360
|
-
* @param
|
|
361
|
-
* @param init - 初始数据
|
|
370
|
+
* @param option - 网络请求选项
|
|
371
|
+
* @param reqProc - 请求处理函数 需调用req.end()
|
|
372
|
+
* @param acceptProc - 响应处理数据
|
|
362
373
|
*/
|
|
363
|
-
static async request(option,
|
|
374
|
+
static async request(option, sendProc, acceptProc) {
|
|
375
|
+
const { reduce: reqReduce, init: reqInit } = acceptProc;
|
|
376
|
+
const { proc: reqProc } = sendProc;
|
|
364
377
|
const { protocol, timeout, ...baseReqOpt } = option;
|
|
365
378
|
const plusTimeout = (timeout ?? 0) + 1000;
|
|
366
379
|
const hasTimeLimit = (timeout ? timeout >= 10_000 : false);
|
|
@@ -379,7 +392,7 @@ class UtilHttp {
|
|
|
379
392
|
clearTimeout(finallyTimeout);
|
|
380
393
|
resolve(t);
|
|
381
394
|
};
|
|
382
|
-
const resFunc = (res) => {
|
|
395
|
+
const resFunc = async (res) => {
|
|
383
396
|
try {
|
|
384
397
|
//请求超时
|
|
385
398
|
if (hasTimeLimit) {
|
|
@@ -387,16 +400,30 @@ class UtilHttp {
|
|
|
387
400
|
UtilLogger_1.SLogger.warn(`${flagName} http.response 触发 ${timeout} ms 超时, 继续挂起等待`);
|
|
388
401
|
});
|
|
389
402
|
}
|
|
390
|
-
let mergedata
|
|
403
|
+
let mergedata;
|
|
404
|
+
try {
|
|
405
|
+
mergedata = await reqInit(res);
|
|
406
|
+
}
|
|
407
|
+
catch (err) {
|
|
408
|
+
UtilLogger_1.SLogger.error(`${flagName} init函数错误:`, err);
|
|
409
|
+
finallyResolve(undefined);
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
391
412
|
res.setEncoding(option.responseEncode ?? 'utf8');
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
413
|
+
if (reqReduce) {
|
|
414
|
+
res.on('data', chunk => {
|
|
415
|
+
dataPromise = reduceQueue
|
|
416
|
+
.enqueue(async () => {
|
|
417
|
+
try {
|
|
418
|
+
mergedata = await reqReduce(mergedata, chunk);
|
|
419
|
+
}
|
|
420
|
+
catch (err) {
|
|
421
|
+
UtilLogger_1.SLogger.error(`${flagName} reduce函数错误:`, err, `chunk:${chunk}\nmergedata:`, mergedata);
|
|
422
|
+
finallyResolve(undefined);
|
|
423
|
+
}
|
|
424
|
+
});
|
|
398
425
|
});
|
|
399
|
-
}
|
|
426
|
+
}
|
|
400
427
|
res.on('error', err => {
|
|
401
428
|
UtilLogger_1.SLogger.warn(`${flagName} 接收反馈错误:`, err);
|
|
402
429
|
finallyResolve(undefined);
|
|
@@ -431,7 +458,7 @@ class UtilHttp {
|
|
|
431
458
|
finallyResolve(undefined);
|
|
432
459
|
});
|
|
433
460
|
try {
|
|
434
|
-
await
|
|
461
|
+
await reqProc(req);
|
|
435
462
|
}
|
|
436
463
|
catch (err) {
|
|
437
464
|
UtilLogger_1.SLogger.error(`${flagName} proc函数错误:`, err);
|
|
@@ -456,24 +483,30 @@ if (false)
|
|
|
456
483
|
const tool = UtilHttp
|
|
457
484
|
.url('https://httpbin.org/post')
|
|
458
485
|
.post()
|
|
459
|
-
.
|
|
486
|
+
.option({ timeout: 20000 });
|
|
460
487
|
//json
|
|
461
488
|
const sj = await tool.clone()
|
|
462
489
|
.sendJson()
|
|
463
490
|
.acceptJson()
|
|
464
|
-
.once({
|
|
491
|
+
.once({
|
|
492
|
+
json: { test: 1 },
|
|
493
|
+
});
|
|
465
494
|
console.log(sj);
|
|
466
495
|
//form
|
|
467
496
|
const sf = await tool.clone()
|
|
468
497
|
.sendForm()
|
|
469
498
|
.acceptJson()
|
|
470
|
-
.once({
|
|
499
|
+
.once({
|
|
500
|
+
form: { test: 1 }
|
|
501
|
+
});
|
|
471
502
|
console.log(sf);
|
|
472
503
|
//query
|
|
473
504
|
const sq = await tool.clone()
|
|
474
505
|
.sendQuery()
|
|
475
506
|
.acceptJson()
|
|
476
|
-
.once({
|
|
507
|
+
.once({
|
|
508
|
+
query: { test: 1 }
|
|
509
|
+
});
|
|
477
510
|
console.log(sq);
|
|
478
511
|
const filepath = pathe_1.default.join(__dirname, '..', 'input.wav');
|
|
479
512
|
//formData
|
|
@@ -487,6 +520,8 @@ if (false)
|
|
|
487
520
|
const sfile = await tool.clone()
|
|
488
521
|
.sendFile()
|
|
489
522
|
.acceptJson()
|
|
490
|
-
.once(
|
|
523
|
+
.once({
|
|
524
|
+
filepath: filepath
|
|
525
|
+
});
|
|
491
526
|
console.log(sfile);
|
|
492
527
|
})());
|