@zwa73/utils 1.0.195 → 1.0.196

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.
@@ -0,0 +1,345 @@
1
+ import { AnyString,JToken, MPromise, StatusVerifyFn } from "@/src/UtilInterfaces";
2
+ import https from 'https';
3
+ import http from 'http';
4
+ import { SLogger } from "@/src/UtilLogger";
5
+ import { RepeatPromiseOpt, UtilFunc } from "@/src/UtilFunctions";
6
+ import qs from "querystring";
7
+
8
+ /**网络请求返回值 */
9
+ export type ComResp<T> = {
10
+ /**响应头 */
11
+ headers: http.IncomingHttpHeaders;
12
+ /**响应状态码 */
13
+ statusCode?: number;
14
+ /**响应数据 */
15
+ data: T;
16
+ }
17
+
18
+ /**网络请求选项 */
19
+ export type ComRequestOption = {
20
+ /**请求协议 */
21
+ protocol: 'http:'|'https:';
22
+ /**超时时间/毫秒 最小为10_000 默认无限 */
23
+ timeout?:number;
24
+ /**请求域名 */
25
+ hostname: string;
26
+ /**请求路径 */
27
+ path?: string;
28
+ /**请求方式 post 为 */
29
+ method: 'POST'|'GET';
30
+ /**端口 */
31
+ port?:number;
32
+ /**请求头 */
33
+ headers?: {
34
+ /**内容类型 */
35
+ 'Content-Type'?: 'application/json'|AnyString;
36
+ /**内容长度 一般无需填写 应为buffer长度而非字符串长度 */
37
+ 'Content-Length'?: number;
38
+ };
39
+ }&http.RequestOptions;
40
+
41
+ /**get请求所允许的数据 */
42
+ export type GetReqData = NodeJS.Dict<
43
+ | string
44
+ | number
45
+ | boolean
46
+ | readonly string[]
47
+ | readonly number[]
48
+ | readonly boolean[]
49
+ | null
50
+ >;
51
+
52
+ /**请求处理函数 需调用req.end() */
53
+ export type ProcReqFn = ((req:http.ClientRequest)=>MPromise<void>);
54
+ /**数据处理函数 */
55
+ export type ReduceDataFn<T> = (acc:T,data:string)=>MPromise<T>;
56
+
57
+ /**网络工具 */
58
+ export namespace UtilCom{
59
+
60
+
61
+ /**网络请求
62
+ * @param comReqOpt - 网络请求选项
63
+ * @param procReq - 请求处理函数 需调用req.end()
64
+ * @param reduceData - 数据处理函数
65
+ * @param initData - 初始数据
66
+ */
67
+ export async function comReq<T>(
68
+ comReqOpt:ComRequestOption,
69
+ procReq:ProcReqFn,
70
+ reduceData:ReduceDataFn<T>,
71
+ initData:T,
72
+ ){
73
+ const {protocol,timeout,...baseReqOpt} = comReqOpt;
74
+
75
+ const hasTimeLimit = (timeout ? timeout>=10_000 : false );
76
+
77
+ const flagName = `${comReq.name}.${protocol}${baseReqOpt.method}`;
78
+
79
+ return new Promise<ComResp<T>|undefined>(async (resolve, rejecte)=>{
80
+ const resFunc = (res:http.IncomingMessage)=>{
81
+ try{
82
+ //请求超时
83
+ if(hasTimeLimit){
84
+ res.setTimeout(timeout!, ()=>{
85
+ SLogger.warn(`${flagName} 接收反馈超时: ${timeout} ms`);
86
+ resolve(undefined);
87
+ });
88
+ }
89
+
90
+ let mergedata:T = initData;
91
+ res.setEncoding('utf8');
92
+ res.on('data', async chunk => mergedata=await reduceData(mergedata,chunk));
93
+
94
+ res.on('error',(e)=>{
95
+ SLogger.warn(`${flagName} 接收反馈错误:${e}`);
96
+ resolve(undefined);
97
+ });
98
+
99
+ res.on('end',()=>{
100
+ resolve({
101
+ headers: res.headers,
102
+ statusCode: res.statusCode,
103
+ data: mergedata,
104
+ });
105
+ });
106
+ }catch(err){
107
+ SLogger.warn(`${flagName} 未知错误:${err}`);
108
+ resolve(undefined);
109
+ return;
110
+ }
111
+ };
112
+ //路由 http/https
113
+ const req:http.ClientRequest= protocol=="https:"
114
+ ? https.request(baseReqOpt as http.RequestOptions, resFunc)
115
+ : http.request(baseReqOpt as http.RequestOptions, resFunc);
116
+
117
+ //请求超时
118
+ if(hasTimeLimit){
119
+ req.setTimeout(timeout!, ()=>{
120
+ SLogger.warn(`${flagName} 发送请求超时: ${timeout} ms`);
121
+ req.destroy();
122
+ });
123
+ //req.on('timeout', ()=>{
124
+ // SLogger.warn(`${flagName} 发送请求超时(timeout): ${timeLimit} ms`);
125
+ // req.destroy();
126
+ //});
127
+ }
128
+
129
+ req.on('error', (e)=>{
130
+ SLogger.warn(`${flagName} 发送请求错误:${e}`);
131
+ resolve(undefined);
132
+ });
133
+
134
+ await procReq(req);
135
+ });
136
+ }
137
+
138
+ /**发送json的网络请求
139
+ * @param comReqOpt - 网络请求选项
140
+ * @param reqData - 数据对象
141
+ * @returns 结果 undefined 为未能成功接收
142
+ */
143
+ async function jsonReq<T extends ComRequestOption>(
144
+ comReqOpt:T,
145
+ reqData?:T['method'] extends "POST" ? JToken :GetReqData
146
+ ){
147
+ const {method} = comReqOpt;
148
+ const isPost = (method=="POST");
149
+
150
+ if (!isPost && reqData != undefined) {
151
+ const queryString = qs.stringify(reqData as GetReqData);
152
+ if (queryString) {
153
+ // 检查当前路径是否已经包含问号
154
+ const separator = comReqOpt?.path?.includes('?') ? '&' : '?';
155
+ comReqOpt.path += separator + queryString;
156
+ }
157
+ }
158
+
159
+ const procReq = (req:http.ClientRequest)=>{
160
+ if(isPost) req.write(JSON.stringify(reqData));
161
+ req.end();
162
+ }
163
+
164
+ const reduceData = (acc:string,data:string)=>acc+data;
165
+ const result = await comReq(comReqOpt,procReq,reduceData,"");
166
+ if(result==undefined) return undefined;
167
+ const {data,...rest} = result;
168
+
169
+ if(data.trim()==""){
170
+ SLogger.warn(`${jsonReq.name} 接收反馈错误: 原始字符串为空`);
171
+ return {...result,raw:"",data:null};
172
+ }
173
+
174
+ try{
175
+ const obj = JSON.parse(data.trim()) as JToken;
176
+ SLogger.http(`${jsonReq.name} 接受信息:`,UtilFunc.stringifyJToken(obj,{compress:true,space:2}));
177
+ return{...rest,data:obj};
178
+ }
179
+ catch(e){
180
+ SLogger.warn(`${jsonReq.name} 接收反馈错误:${e}\n原始字符串:${data}`);
181
+ return {...result,raw:data,data:null};
182
+ }
183
+ }
184
+
185
+ /**重复发送json的网络请求
186
+ * @async
187
+ * @param comReqOpt - 网络请求选项
188
+ * @param reqData - 数据对象
189
+ * @param verifyFn - 有效性验证函数
190
+ * @param repeatOpt - 重试选项 默认 延迟:1000ms 间隔:180_000ms 重试:3次
191
+ * @returns 结果 undefined 为未能成功接收
192
+ */
193
+ async function repeatJsonComReq<T extends ComRequestOption>(
194
+ comReqOpt:T,
195
+ reqData?:T['method'] extends "POST" ? JToken :GetReqData,
196
+ verifyFn?:StatusVerifyFn<ComResp<JToken>|undefined>,
197
+ repeatOpt:RepeatPromiseOpt={},
198
+ ){
199
+ repeatOpt.tryDelay = repeatOpt.tryDelay??1000;
200
+ const procFn = ()=>jsonReq(comReqOpt,reqData);
201
+ return UtilFunc.repeatPromise(procFn,verifyFn,repeatOpt);
202
+ }
203
+
204
+ /**发送一个 https POST 请求并接受数据
205
+ * @async
206
+ * @param comReqOpt - 请求参数
207
+ * @param reqData - 数据对象
208
+ * @returns 结果 undefined 为未能成功接收
209
+ */
210
+ export function httpsPost(comReqOpt:Omit<ComRequestOption,'protocol'|'method'>,reqData?:JToken){
211
+ return jsonReq({
212
+ ...comReqOpt,
213
+ method:"POST",
214
+ protocol:"https:",
215
+ },reqData);
216
+ }
217
+
218
+ /**发送一个 http POST 请求并接受数据
219
+ * @async
220
+ * @param comReqOpt - 请求参数
221
+ * @param reqData - 数据对象
222
+ * @returns 结果 undefined 为未能成功接收
223
+ */
224
+ export function httpPost(comReqOpt:Omit<ComRequestOption,'protocol'|'method'>,reqData?:JToken){
225
+ return jsonReq({
226
+ ...comReqOpt,
227
+ method:"POST",
228
+ protocol:"http:",
229
+ },reqData);
230
+ }
231
+
232
+ /**发送一个 https GET 请求并接受数据
233
+ * @async
234
+ * @param comReqOpt - 请求参数
235
+ * @param reqData - 数据对象
236
+ * @returns 结果 undefined 为未能成功接收
237
+ */
238
+ export function httpsGet(comReqOpt:Omit<ComRequestOption,'protocol'|'method'>,reqData?:GetReqData){
239
+ return jsonReq({
240
+ ...comReqOpt,
241
+ method:"GET",
242
+ protocol:"https:",
243
+ },reqData);
244
+ }
245
+
246
+ /**发送一个 http GET 请求并接受数据
247
+ * @async
248
+ * @param comReqOpt - 请求参数
249
+ * @param reqData - 数据对象
250
+ * @returns 结果 undefined 为未能成功接收
251
+ */
252
+ export function httpGet(comReqOpt:Omit<ComRequestOption,'protocol'|'method'>,reqData?:GetReqData){
253
+ return jsonReq({
254
+ ...comReqOpt,
255
+ method:"GET",
256
+ protocol:"http:",
257
+ },reqData);
258
+ }
259
+
260
+
261
+ /**重复一个 https POST请求并接受数据
262
+ * @async
263
+ * @param comReqOpt - 网络请求选项
264
+ * @param reqData - 数据对象
265
+ * @param verifyFn - 有效性验证函数
266
+ * @param repeatOpt - 重试选项 默认 延迟:1000ms 间隔:180_000ms 重试:3次
267
+ * @returns 结果 undefined 为未能成功接收
268
+ */
269
+ export function httpsRepeatPost(
270
+ comReqOpt:Omit<ComRequestOption,'protocol'|'method'>,
271
+ reqData?:JToken,
272
+ verifyFn?:StatusVerifyFn<JToken|undefined>,
273
+ repeatOpt?:RepeatPromiseOpt
274
+ ){
275
+ return repeatJsonComReq({
276
+ ...comReqOpt,
277
+ method:"POST",
278
+ protocol:"https:",
279
+ },reqData,verifyFn,repeatOpt);
280
+ }
281
+
282
+ /**重复一个 http POST请求并接受数据
283
+ * @async
284
+ * @param comReqOpt - 网络请求选项
285
+ * @param reqData - 数据对象
286
+ * @param verifyFn - 有效性验证函数
287
+ * @param repeatOpt - 重试选项 默认 延迟:1000ms 间隔:180_000ms 重试:3次
288
+ * @returns 结果 undefined 为未能成功接收
289
+ */
290
+ export function httpRepeatPost(
291
+ comReqOpt:Omit<ComRequestOption,'protocol'|'method'>,
292
+ reqData?:JToken,
293
+ verifyFn?:StatusVerifyFn<JToken|undefined>,
294
+ repeatOpt?:RepeatPromiseOpt
295
+ ){
296
+ return repeatJsonComReq({
297
+ ...comReqOpt,
298
+ method:"POST",
299
+ protocol:"http:",
300
+ },reqData,verifyFn,repeatOpt);
301
+ }
302
+
303
+ /**重复一个 https GET 请求并接受数据
304
+ * @async
305
+ * @param comReqOpt - 网络请求选项
306
+ * @param reqData - 数据对象
307
+ * @param verifyFn - 有效性验证函数
308
+ * @param repeatOpt - 重试选项 默认 延迟:1000ms 间隔:180_000ms 重试:3次
309
+ * @returns 结果 undefined 为未能成功接收
310
+ */
311
+ export function httpsRepeatGet(
312
+ comReqOpt:Omit<ComRequestOption,'protocol'|'method'>,
313
+ reqData?:GetReqData,
314
+ verifyFn?:StatusVerifyFn<JToken|undefined>,
315
+ repeatOpt?:RepeatPromiseOpt
316
+ ){
317
+ return repeatJsonComReq({
318
+ ...comReqOpt,
319
+ method:"GET",
320
+ protocol:"https:",
321
+ },reqData,verifyFn,repeatOpt);
322
+ }
323
+
324
+ /**重复一个 http GET 请求并接受数据
325
+ * @async
326
+ * @param comReqOpt - 网络请求选项
327
+ * @param reqData - 数据对象
328
+ * @param verifyFn - 有效性验证函数
329
+ * @param repeatOpt - 重试选项 默认 延迟:1000ms 间隔:180_000ms 重试:3次
330
+ * @returns 结果 undefined 为未能成功接收
331
+ */
332
+ export function httpRepeatGet(
333
+ comReqOpt:Omit<ComRequestOption,'protocol'|'method'>,
334
+ reqData?:GetReqData,
335
+ verifyFn?:StatusVerifyFn<JToken|undefined>,
336
+ repeatOpt?:RepeatPromiseOpt
337
+ ){
338
+ return repeatJsonComReq({
339
+ ...comReqOpt,
340
+ method:"GET",
341
+ protocol:"http:",
342
+ },reqData,verifyFn,repeatOpt);
343
+ }
344
+
345
+ }
@@ -1,5 +1,5 @@
1
1
  import * as crypto from "crypto";
2
- import { PRecord, AnyFunc, ExtractOutcome, IJData, JObject, JToken, Keyable, Literal, Matchable, MatchableFlag, Outcome, ReqStat, ReqVerifyFn, ProperSubsetCheck, UnionToIntersection, AnyRecord, AllExtends, SrtSegment, MPromise } from "@/src/UtilInterfaces";
2
+ import { PRecord, AnyFunc, ExtractOutcome, IJData, JObject, JToken, Keyable, Literal, Matchable, MatchableFlag, Outcome, PromiseStatus, StatusVerifyFn, ProperSubsetCheck, UnionToIntersection, AnyRecord, AllExtends, SrtSegment, MPromise } from "@/src/UtilInterfaces";
3
3
  import * as cp from "child_process";
4
4
  import { LogLevel, SLogger } from "@/src/UtilLogger";
5
5
  import { Completed, Failed, FailedLike, None, StatusSymbol, Success, SuccessLike, Terminated, Timeout } from "./UtilSymbol";
@@ -51,7 +51,7 @@ type PromiseResult<T> = {
51
51
  /**请求结果 */
52
52
  result:T;
53
53
  /**请求状态 */
54
- stat:ReqStat;
54
+ stat:PromiseStatus;
55
55
  /**请求下标/序号 */
56
56
  index:number;
57
57
  };
@@ -228,7 +228,7 @@ static getNeverResolvedPromise<T>():Promise<T>{
228
228
  * @returns 重复结果
229
229
  */
230
230
  @LogTimeAsync("repeatPromise ",true)
231
- static async repeatPromise<T>(procFn:()=>Promise<T>,verifyFn?:ReqVerifyFn<T>,opt:RepeatPromiseOpt = {}):
231
+ static async repeatPromise<T>(procFn:()=>Promise<T>,verifyFn?:StatusVerifyFn<T>,opt:RepeatPromiseOpt = {}):
232
232
  Promise<RepeatPromiseResult<T>>{
233
233
  opt.count = opt.count??3;
234
234
  opt.tryInterval = opt.tryInterval??180_000;
@@ -140,14 +140,14 @@ export type ExclusiveJObject<B extends JObject,T extends JToken,K extends string
140
140
  TMP extends JArray = ExclusiveRecursive<B,T,K>> = TMP[number];
141
141
 
142
142
 
143
- /**请求完成状态 成功/失败/终止
144
- * 成功 将直接返回 结果
145
- * 终止 将直接返回 null
143
+ /**Promise完成状态 成功/失败/终止
144
+ * 成功 将直接返回 结果
145
+ * 终止 将直接返回 结果
146
146
  * 失败 将重试
147
147
  */
148
- export type ReqStat = Success|Failed|Terminated;
149
- /**请求状态验证函数 */
150
- export type ReqVerifyFn<T> = (obj:T)=>Promise<ReqStat>|ReqStat;
148
+ export type PromiseStatus = Success|Failed|Terminated;
149
+ /**状态验证函数 */
150
+ export type StatusVerifyFn<T> = (obj:T)=>Promise<PromiseStatus>|PromiseStatus;
151
151
 
152
152
  /**获取Promise的结果类型 如同await那样
153
153
  * @deprecated 请使用官方的 Awaited<T> 类型