@nest-omni/core 4.1.3-25 → 4.1.3-27

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.
Files changed (48) hide show
  1. package/cache/cache.service.d.ts +3 -1
  2. package/cache/cache.service.js +8 -8
  3. package/cache/decorators/cache-put.decorator.js +5 -4
  4. package/cache/dependencies/callback.dependency.js +9 -0
  5. package/cache/dependencies/tag.dependency.d.ts +1 -9
  6. package/cache/dependencies/tag.dependency.js +5 -14
  7. package/cache/providers/lrucache.provider.d.ts +1 -0
  8. package/cache/providers/lrucache.provider.js +6 -4
  9. package/cache/providers/redis-cache.provider.d.ts +1 -0
  10. package/cache/providers/redis-cache.provider.js +8 -6
  11. package/http-client/config/http-client.config.js +4 -2
  12. package/http-client/decorators/http-client.decorators.d.ts +1 -1
  13. package/http-client/decorators/http-client.decorators.js +1 -1
  14. package/http-client/examples/advanced-usage.example.js +3 -3
  15. package/http-client/examples/axios-config-extended.example.js +1 -3
  16. package/http-client/examples/flexible-response-example.d.ts +28 -0
  17. package/http-client/examples/flexible-response-example.js +120 -0
  18. package/http-client/examples/ssl-certificate.example.d.ts +2 -2
  19. package/http-client/examples/ssl-certificate.example.js +18 -17
  20. package/http-client/http-client.module.js +2 -2
  21. package/http-client/interfaces/http-client-config.interface.d.ts +6 -1
  22. package/http-client/services/api-client-registry.service.d.ts +6 -6
  23. package/http-client/services/api-client-registry.service.js +9 -9
  24. package/http-client/services/circuit-breaker.service.d.ts +9 -9
  25. package/http-client/services/circuit-breaker.service.js +24 -24
  26. package/http-client/services/http-client.service.d.ts +30 -13
  27. package/http-client/services/http-client.service.js +76 -47
  28. package/http-client/services/logging.service.d.ts +17 -33
  29. package/http-client/services/logging.service.js +81 -169
  30. package/http-client/utils/curl-generator.util.js +2 -5
  31. package/http-client/utils/index.d.ts +1 -0
  32. package/http-client/utils/index.js +1 -0
  33. package/http-client/utils/proxy-environment.util.d.ts +12 -12
  34. package/http-client/utils/proxy-environment.util.js +25 -19
  35. package/http-client/utils/retry-recorder.util.d.ts +0 -4
  36. package/http-client/utils/retry-recorder.util.js +2 -27
  37. package/http-client/utils/sanitize.util.d.ts +58 -0
  38. package/http-client/utils/sanitize.util.js +188 -0
  39. package/http-client/utils/security-validator.util.d.ts +19 -19
  40. package/http-client/utils/security-validator.util.js +66 -64
  41. package/interceptors/http-logging-interceptor.service.d.ts +38 -0
  42. package/interceptors/http-logging-interceptor.service.js +167 -0
  43. package/interceptors/index.d.ts +1 -0
  44. package/interceptors/index.js +1 -0
  45. package/package.json +1 -1
  46. package/setup/bootstrap.setup.js +1 -1
  47. package/shared/services/api-config.service.js +3 -18
  48. package/vault/vault-config.service.js +1 -1
@@ -25,6 +25,7 @@ const http_log_entity_1 = require("../entities/http-log.entity");
25
25
  const request_id_util_1 = require("../utils/request-id.util");
26
26
  const context_extractor_util_1 = require("../utils/context-extractor.util");
27
27
  const call_stack_extractor_util_1 = require("../utils/call-stack-extractor.util");
28
+ const sanitize_util_1 = require("../utils/sanitize.util");
28
29
  const transaction_1 = require("@nest-omni/transaction");
29
30
  /**
30
31
  * HTTP日志服务
@@ -61,13 +62,15 @@ let HttpLoggingService = HttpLoggingService_1 = class HttpLoggingService {
61
62
  }
62
63
  initRepository(dataSource, tableName) {
63
64
  try {
64
- this.logRepository = (0, transaction_1.getDataSource)(dataSource).getRepository(http_log_entity_1.HttpLogEntity);
65
+ this.logRepository =
66
+ (0, transaction_1.getDataSource)(dataSource).getRepository(http_log_entity_1.HttpLogEntity);
65
67
  this.logger.log('Database logging initialized');
66
68
  return this.logRepository;
67
69
  }
68
70
  catch (error) {
69
- this.logger.error('Failed to initialize database logging', error);
70
- throw error;
71
+ this.logger.warn('Database logging not available, continuing without it');
72
+ this.logRepository = null;
73
+ return null;
71
74
  }
72
75
  }
73
76
  /**
@@ -77,16 +80,16 @@ let HttpLoggingService = HttpLoggingService_1 = class HttpLoggingService {
77
80
  // 从ContextProvider获取上下文信息
78
81
  const context = context_extractor_util_1.ContextExtractor.getHttpContext();
79
82
  const actualRequestId = requestId || context.requestId || (0, request_id_util_1.generateRequestId)();
80
- const { logHeaders = true, logBody = true, sanitizeHeaders = [], } = loggingOptions || {};
83
+ const { logHeaders = true, logBody = true, sanitize = [], } = loggingOptions || {};
81
84
  const logData = {
82
85
  requestId: actualRequestId,
83
86
  userId: context.userId,
84
- method: config.method ? config.method.toUpperCase() : 'GET',
85
- url: config.url,
86
- headers: logHeaders
87
- ? this.sanitizeHeaders(config.headers, sanitizeHeaders)
87
+ method: (config === null || config === void 0 ? void 0 : config.method) ? config.method.toUpperCase() : 'GET',
88
+ url: config ? sanitize_util_1.SanitizeUtil.sanitizeQueryString(config.url, sanitize) : '',
89
+ headers: logHeaders && config
90
+ ? sanitize_util_1.SanitizeUtil.sanitizeHeaders(config.headers, sanitize)
88
91
  : undefined,
89
- body: logBody ? this.sanitizeBody(config.data) : undefined,
92
+ body: logBody && config ? sanitize_util_1.SanitizeUtil.sanitizeBody(config.data, sanitize) : undefined,
90
93
  clientIp: context.clientIp,
91
94
  serviceName: context.appId,
92
95
  };
@@ -107,8 +110,8 @@ let HttpLoggingService = HttpLoggingService_1 = class HttpLoggingService {
107
110
  */
108
111
  logRequestSuccess(response_1, startTime_1, requestId_1, loggingOptions_1) {
109
112
  return __awaiter(this, arguments, void 0, function* (response, startTime, requestId, loggingOptions, databaseLogging = false, retryRecords, circuitBreakerState, decoratorContext, clientName, callingContext) {
110
- var _a, _b, _c, _d;
111
- const { logHeaders = true, logBody = true, sanitizeHeaders = [], } = loggingOptions || {};
113
+ var _a, _b, _c, _d, _e, _f;
114
+ const { logHeaders = true, logBody = true, sanitize = [], } = loggingOptions || {};
112
115
  const responseTime = Date.now() - startTime;
113
116
  // 获取当前上下文信息
114
117
  const context = context_extractor_util_1.ContextExtractor.getHttpContext();
@@ -118,9 +121,9 @@ let HttpLoggingService = HttpLoggingService_1 = class HttpLoggingService {
118
121
  statusCode: response.status,
119
122
  responseTime,
120
123
  headers: logHeaders
121
- ? this.sanitizeHeaders(response.headers, sanitizeHeaders)
124
+ ? sanitize_util_1.SanitizeUtil.sanitizeHeaders(response.headers, sanitize)
122
125
  : undefined,
123
- body: logBody ? this.sanitizeBody(response.data) : undefined,
126
+ body: logBody ? sanitize_util_1.SanitizeUtil.sanitizeBody(response.data, sanitize) : undefined,
124
127
  responseSize: JSON.stringify(response.data).length,
125
128
  circuitBreakerState,
126
129
  };
@@ -139,7 +142,7 @@ let HttpLoggingService = HttpLoggingService_1 = class HttpLoggingService {
139
142
  dataSource: (_a = loggingOptions.databaseLogging) === null || _a === void 0 ? void 0 : _a.dataSource,
140
143
  tableName: (_b = loggingOptions.databaseLogging) === null || _b === void 0 ? void 0 : _b.tableName,
141
144
  });
142
- this.initRepository(loggingOptions.databaseLogging.dataSource, loggingOptions.databaseLogging.tableName);
145
+ this.initRepository(((_c = loggingOptions.databaseLogging) === null || _c === void 0 ? void 0 : _c.dataSource) || 'default', ((_d = loggingOptions.databaseLogging) === null || _d === void 0 ? void 0 : _d.tableName) || 'http_log');
143
146
  }
144
147
  // 数据库日志记录
145
148
  if (databaseLogging && this.logRepository) {
@@ -156,25 +159,25 @@ let HttpLoggingService = HttpLoggingService_1 = class HttpLoggingService {
156
159
  this.saveToDatabase({
157
160
  requestId,
158
161
  userId: context.userId,
159
- method: ((_c = response.config.method) === null || _c === void 0 ? void 0 : _c.toUpperCase()) || 'UNKNOWN',
160
- url: this.getFullUrl(response.config) || '',
161
- headers: this.sanitizeHeaders(response.config.headers, sanitizeHeaders),
162
- body: this.sanitizeBodyAsString(response.config.data),
163
- params: response.config.params,
162
+ method: ((_e = response.config.method) === null || _e === void 0 ? void 0 : _e.toUpperCase()) || 'UNKNOWN',
163
+ url: sanitize_util_1.SanitizeUtil.sanitizeQueryString(this.getFullUrl(response.config), sanitize),
164
+ headers: sanitize_util_1.SanitizeUtil.sanitizeHeaders(response.config.headers, sanitize),
165
+ body: sanitize_util_1.SanitizeUtil.sanitizeBodyAsString(response.config.data, sanitize),
166
+ params: sanitize_util_1.SanitizeUtil.sanitizeParams(response.config.params, sanitize),
164
167
  statusCode: response.status,
165
168
  responseTime,
166
169
  attemptCount: (retryRecords === null || retryRecords === void 0 ? void 0 : retryRecords.length)
167
170
  ? Math.max(...retryRecords.map((r) => r.attempt)) + 1
168
171
  : 1,
169
172
  success: true,
170
- responseHeaders: this.sanitizeHeaders(response.headers, sanitizeHeaders),
173
+ responseHeaders: sanitize_util_1.SanitizeUtil.sanitizeHeaders(response.headers, sanitize),
171
174
  responseBody: logBody
172
- ? this.sanitizeBodyAsString(response.data)
175
+ ? sanitize_util_1.SanitizeUtil.sanitizeBodyAsString(response.data, sanitize)
173
176
  : undefined,
174
177
  serviceName: clientName || context.appId,
175
178
  operationName: callInfo.operationName,
176
179
  clientIp: context.clientIp,
177
- source: (_d = context.metadata) === null || _d === void 0 ? void 0 : _d.source,
180
+ source: (_f = context.metadata) === null || _f === void 0 ? void 0 : _f.source,
178
181
  tags: context.tags,
179
182
  metadata: logData,
180
183
  retryRecords,
@@ -187,8 +190,8 @@ let HttpLoggingService = HttpLoggingService_1 = class HttpLoggingService {
187
190
  * 记录请求错误
188
191
  */
189
192
  logRequestError(error, startTime, requestId, attemptCount, loggingOptions, databaseLogging = false, retryRecords, circuitBreakerState, decoratorContext, clientName, callingContext) {
190
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
191
- const { logHeaders = true, sanitizeHeaders = [] } = loggingOptions;
193
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
194
+ const { logHeaders = true, sanitize = [] } = loggingOptions;
192
195
  const responseTime = Date.now() - startTime;
193
196
  // 获取当前上下文信息
194
197
  const context = context_extractor_util_1.ContextExtractor.getHttpContext();
@@ -202,7 +205,7 @@ let HttpLoggingService = HttpLoggingService_1 = class HttpLoggingService {
202
205
  errorCode: error.code,
203
206
  statusCode: (_a = error.response) === null || _a === void 0 ? void 0 : _a.status,
204
207
  headers: ((_b = error.config) === null || _b === void 0 ? void 0 : _b.headers) && logHeaders
205
- ? this.sanitizeHeaders(error.config.headers, sanitizeHeaders)
208
+ ? sanitize_util_1.SanitizeUtil.sanitizeHeaders(error.config.headers, sanitize)
206
209
  : undefined,
207
210
  circuitBreakerState,
208
211
  };
@@ -222,7 +225,7 @@ let HttpLoggingService = HttpLoggingService_1 = class HttpLoggingService {
222
225
  break;
223
226
  }
224
227
  if (!this.logRepository) {
225
- this.initRepository(loggingOptions.databaseLogging.dataSource, loggingOptions.databaseLogging.tableName);
228
+ this.initRepository(((_c = loggingOptions.databaseLogging) === null || _c === void 0 ? void 0 : _c.dataSource) || 'default', ((_d = loggingOptions.databaseLogging) === null || _d === void 0 ? void 0 : _d.tableName) || 'http_log');
226
229
  }
227
230
  // 数据库日志记录
228
231
  if (databaseLogging && this.logRepository) {
@@ -233,14 +236,14 @@ let HttpLoggingService = HttpLoggingService_1 = class HttpLoggingService {
233
236
  this.saveToDatabase({
234
237
  requestId,
235
238
  userId: context.userId,
236
- method: ((_d = (_c = error.config) === null || _c === void 0 ? void 0 : _c.method) === null || _d === void 0 ? void 0 : _d.toUpperCase()) || 'UNKNOWN',
237
- url: this.getFullUrl(error.config) || '',
238
- headers: ((_e = error.config) === null || _e === void 0 ? void 0 : _e.headers)
239
- ? this.sanitizeHeaders(error.config.headers, sanitizeHeaders)
239
+ method: ((_f = (_e = error.config) === null || _e === void 0 ? void 0 : _e.method) === null || _f === void 0 ? void 0 : _f.toUpperCase()) || 'UNKNOWN',
240
+ url: sanitize_util_1.SanitizeUtil.sanitizeQueryString(this.getFullUrl(error.config), sanitize),
241
+ headers: ((_g = error.config) === null || _g === void 0 ? void 0 : _g.headers)
242
+ ? sanitize_util_1.SanitizeUtil.sanitizeHeaders(error.config.headers, sanitize)
240
243
  : {},
241
- body: this.sanitizeBodyAsString((_f = error.config) === null || _f === void 0 ? void 0 : _f.data),
242
- params: (_g = error.config) === null || _g === void 0 ? void 0 : _g.params,
243
- statusCode: (_h = error.response) === null || _h === void 0 ? void 0 : _h.status,
244
+ body: sanitize_util_1.SanitizeUtil.sanitizeBodyAsString((_h = error.config) === null || _h === void 0 ? void 0 : _h.data, sanitize),
245
+ params: sanitize_util_1.SanitizeUtil.sanitizeParams((_j = error.config) === null || _j === void 0 ? void 0 : _j.params, sanitize),
246
+ statusCode: (_k = error.response) === null || _k === void 0 ? void 0 : _k.status,
244
247
  responseTime,
245
248
  attemptCount,
246
249
  success: false,
@@ -250,7 +253,7 @@ let HttpLoggingService = HttpLoggingService_1 = class HttpLoggingService {
250
253
  serviceName: clientName || context.appId,
251
254
  operationName: callInfo.operationName,
252
255
  clientIp: context.clientIp,
253
- source: (_j = context.metadata) === null || _j === void 0 ? void 0 : _j.source,
256
+ source: (_l = context.metadata) === null || _l === void 0 ? void 0 : _l.source,
254
257
  tags: context.tags,
255
258
  metadata: logData,
256
259
  retryRecords,
@@ -374,6 +377,50 @@ let HttpLoggingService = HttpLoggingService_1 = class HttpLoggingService {
374
377
  };
375
378
  });
376
379
  }
380
+ /**
381
+ * 获取日志队列统计信息
382
+ */
383
+ getQueueStats() {
384
+ return {
385
+ queueSize: this.logQueue.length,
386
+ isProcessing: this.isProcessing,
387
+ config: Object.assign({}, this.asyncConfig),
388
+ };
389
+ }
390
+ /**
391
+ * 手动刷新日志队列
392
+ */
393
+ manualFlush() {
394
+ return __awaiter(this, void 0, void 0, function* () {
395
+ return new Promise((resolve) => {
396
+ const checkProcessing = () => {
397
+ if (!this.isProcessing) {
398
+ this.flush();
399
+ // 等待刷新完成
400
+ setTimeout(() => resolve(), 100);
401
+ }
402
+ else {
403
+ setTimeout(checkProcessing, 50);
404
+ }
405
+ };
406
+ checkProcessing();
407
+ });
408
+ });
409
+ }
410
+ /**
411
+ * 设置异步日志配置
412
+ */
413
+ setAsyncConfig(config) {
414
+ Object.assign(this.asyncConfig, config);
415
+ // 重启刷新任务
416
+ if (this.flushTimer) {
417
+ clearInterval(this.flushTimer);
418
+ }
419
+ if (this.asyncConfig.enabled) {
420
+ this.startFlushTask();
421
+ }
422
+ this.logger.log(`Async log config updated: ${JSON.stringify(this.asyncConfig)}`);
423
+ }
377
424
  /**
378
425
  * 提取调用信息
379
426
  */
@@ -536,141 +583,6 @@ let HttpLoggingService = HttpLoggingService_1 = class HttpLoggingService {
536
583
  }
537
584
  });
538
585
  }
539
- /**
540
- * 获取日志队列统计信息
541
- */
542
- getQueueStats() {
543
- return {
544
- queueSize: this.logQueue.length,
545
- isProcessing: this.isProcessing,
546
- config: Object.assign({}, this.asyncConfig),
547
- };
548
- }
549
- /**
550
- * 手动刷新日志队列
551
- */
552
- manualFlush() {
553
- return __awaiter(this, void 0, void 0, function* () {
554
- return new Promise((resolve) => {
555
- const checkProcessing = () => {
556
- if (!this.isProcessing) {
557
- this.flush();
558
- // 等待刷新完成
559
- setTimeout(() => resolve(), 100);
560
- }
561
- else {
562
- setTimeout(checkProcessing, 50);
563
- }
564
- };
565
- checkProcessing();
566
- });
567
- });
568
- }
569
- /**
570
- * 设置异步日志配置
571
- */
572
- setAsyncConfig(config) {
573
- Object.assign(this.asyncConfig, config);
574
- // 重启刷新任务
575
- if (this.flushTimer) {
576
- clearInterval(this.flushTimer);
577
- }
578
- if (this.asyncConfig.enabled) {
579
- this.startFlushTask();
580
- }
581
- this.logger.log(`Async log config updated: ${JSON.stringify(this.asyncConfig)}`);
582
- }
583
- /**
584
- * 转换请求体为字符串
585
- */
586
- sanitizeBodyAsString(data) {
587
- if (!data)
588
- return undefined;
589
- if (typeof data === 'string') {
590
- return data.length > 5000 ? data.substring(0, 5000) + '...' : data;
591
- }
592
- const jsonString = JSON.stringify(data);
593
- return jsonString.length > 5000
594
- ? jsonString.substring(0, 5000) + '...'
595
- : jsonString;
596
- }
597
- /**
598
- * 清理敏感头信息
599
- */
600
- sanitizeHeaders(headers, sanitizeHeaders) {
601
- if (!headers)
602
- return {};
603
- const sanitized = {};
604
- const defaultSensitiveHeaders = [
605
- 'authorization',
606
- 'apikey',
607
- 'password',
608
- 'token',
609
- 'secret',
610
- 'cookie',
611
- 'set-cookie',
612
- 'x-api-key',
613
- 'x-auth-token',
614
- ];
615
- const headersToSanitize = [...defaultSensitiveHeaders, ...sanitizeHeaders];
616
- Object.keys(headers).forEach((key) => {
617
- if (headersToSanitize.some((sensitive) => key.toLowerCase().includes(sensitive.toLowerCase()))) {
618
- sanitized[key] = '[FILTERED]';
619
- }
620
- else {
621
- sanitized[key] = String(headers[key]);
622
- }
623
- });
624
- return sanitized;
625
- }
626
- /**
627
- * 清理敏感请求体信息
628
- */
629
- sanitizeBody(body) {
630
- if (!body)
631
- return undefined;
632
- if (typeof body === 'string') {
633
- try {
634
- body = JSON.parse(body);
635
- }
636
- catch (_a) {
637
- return body.length > 1000 ? body.substring(0, 1000) + '...' : body;
638
- }
639
- }
640
- if (typeof body === 'object') {
641
- const sanitized = Object.assign({}, body);
642
- const sensitiveFields = [
643
- 'password',
644
- 'secret',
645
- 'token',
646
- 'key',
647
- 'authorization',
648
- 'credential',
649
- 'private',
650
- 'confidential',
651
- 'ssn',
652
- 'creditCard',
653
- ];
654
- this.sanitizeObject(sanitized, sensitiveFields);
655
- return sanitized;
656
- }
657
- return body;
658
- }
659
- /**
660
- * 递归清理对象中的敏感字段
661
- */
662
- sanitizeObject(obj, sensitiveFields) {
663
- if (typeof obj !== 'object' || obj === null)
664
- return;
665
- for (const key in obj) {
666
- if (sensitiveFields.some((field) => key.toLowerCase().includes(field.toLowerCase()))) {
667
- obj[key] = '[FILTERED]';
668
- }
669
- else if (typeof obj[key] === 'object') {
670
- this.sanitizeObject(obj[key], sensitiveFields);
671
- }
672
- }
673
- }
674
586
  /**
675
587
  * 获取完整URL
676
588
  * @param config Axios请求配置
@@ -137,13 +137,10 @@ class CurlGenerator {
137
137
  config.url = urlMatch[1];
138
138
  }
139
139
  // 提取头信息
140
- const headerMatches = curlCommand.match(/-H\s+'([^:]+):\s*([^']+)'/g) || [];
140
+ const headerMatches = Array.from(curlCommand.matchAll(/-H\s+'([^:]+):\s*([^']+)'/g));
141
141
  config.headers = {};
142
142
  headerMatches.forEach((header) => {
143
- const headerMatch = header.match(/-H\s+'([^:]+):\s*([^']+)'/);
144
- if (headerMatch) {
145
- config.headers[headerMatch[1]] = headerMatch[2];
146
- }
143
+ config.headers[header[1]] = header[2];
147
144
  });
148
145
  // 提取数据
149
146
  const dataMatch = curlCommand.match(/-d\s+'([^']+)'/);
@@ -3,3 +3,4 @@ export * from './retry-recorder.util';
3
3
  export * from './context-extractor.util';
4
4
  export * from './call-stack-extractor.util';
5
5
  export * from './proxy-environment.util';
6
+ export * from './sanitize.util';
@@ -19,3 +19,4 @@ __exportStar(require("./retry-recorder.util"), exports);
19
19
  __exportStar(require("./context-extractor.util"), exports);
20
20
  __exportStar(require("./call-stack-extractor.util"), exports);
21
21
  __exportStar(require("./proxy-environment.util"), exports);
22
+ __exportStar(require("./sanitize.util"), exports);
@@ -12,6 +12,18 @@ export declare class ProxyEnvironmentParser {
12
12
  * @returns 解析后的代理配置,如果不应使用代理则返回 false
13
13
  */
14
14
  static parseFromEnvironment(protocol?: 'http' | 'https', targetUrl?: string): false | Required<Omit<ProxyConfig, 'enabled' | 'fromEnvironment'>>;
15
+ /**
16
+ * 获取所有代理相关的环境变量
17
+ */
18
+ static getProxyEnvironmentVariables(): {
19
+ HTTP_PROXY?: string;
20
+ HTTPS_PROXY?: string;
21
+ NO_PROXY?: string;
22
+ };
23
+ /**
24
+ * 检查是否设置了代理环境变量
25
+ */
26
+ static hasProxyEnvironment(): boolean;
15
27
  /**
16
28
  * 解析代理 URL
17
29
  * 支持格式: http://proxy:port, http://user:pass@proxy:port
@@ -27,16 +39,4 @@ export declare class ProxyEnvironmentParser {
27
39
  * 支持精确匹配和 CIDR 表示法
28
40
  */
29
41
  private static isIpMatch;
30
- /**
31
- * 获取所有代理相关的环境变量
32
- */
33
- static getProxyEnvironmentVariables(): {
34
- HTTP_PROXY?: string;
35
- HTTPS_PROXY?: string;
36
- NO_PROXY?: string;
37
- };
38
- /**
39
- * 检查是否设置了代理环境变量
40
- */
41
- static hasProxyEnvironment(): boolean;
42
42
  }
@@ -40,6 +40,23 @@ class ProxyEnvironmentParser {
40
40
  return false;
41
41
  }
42
42
  }
43
+ /**
44
+ * 获取所有代理相关的环境变量
45
+ */
46
+ static getProxyEnvironmentVariables() {
47
+ return {
48
+ HTTP_PROXY: process.env.HTTP_PROXY || process.env.http_proxy,
49
+ HTTPS_PROXY: process.env.HTTPS_PROXY || process.env.https_proxy,
50
+ NO_PROXY: process.env.NO_PROXY || process.env.no_proxy,
51
+ };
52
+ }
53
+ /**
54
+ * 检查是否设置了代理环境变量
55
+ */
56
+ static hasProxyEnvironment() {
57
+ const vars = this.getProxyEnvironmentVariables();
58
+ return !!(vars.HTTP_PROXY || vars.HTTPS_PROXY);
59
+ }
43
60
  /**
44
61
  * 解析代理 URL
45
62
  * 支持格式: http://proxy:port, http://user:pass@proxy:port
@@ -50,7 +67,11 @@ class ProxyEnvironmentParser {
50
67
  const config = {
51
68
  protocol: url.protocol.replace(':', '') || 'http',
52
69
  host: url.hostname,
53
- port: url.port ? parseInt(url.port, 10) : url.protocol === 'https:' ? 443 : 80,
70
+ port: url.port
71
+ ? parseInt(url.port, 10)
72
+ : url.protocol === 'https:'
73
+ ? 443
74
+ : 80,
54
75
  auth: undefined,
55
76
  };
56
77
  // 解析认证信息
@@ -79,7 +100,9 @@ class ProxyEnvironmentParser {
79
100
  const url = new URL(targetUrl);
80
101
  const hostname = url.hostname;
81
102
  // NO_PROXY 可以是逗号分隔的列表
82
- const bypassList = noProxy.split(',').map((item) => item.trim().toLowerCase());
103
+ const bypassList = noProxy
104
+ .split(',')
105
+ .map((item) => item.trim().toLowerCase());
83
106
  for (const bypass of bypassList) {
84
107
  if (!bypass)
85
108
  continue;
@@ -126,23 +149,6 @@ class ProxyEnvironmentParser {
126
149
  }
127
150
  return false;
128
151
  }
129
- /**
130
- * 获取所有代理相关的环境变量
131
- */
132
- static getProxyEnvironmentVariables() {
133
- return {
134
- HTTP_PROXY: process.env.HTTP_PROXY || process.env.http_proxy,
135
- HTTPS_PROXY: process.env.HTTPS_PROXY || process.env.https_proxy,
136
- NO_PROXY: process.env.NO_PROXY || process.env.no_proxy,
137
- };
138
- }
139
- /**
140
- * 检查是否设置了代理环境变量
141
- */
142
- static hasProxyEnvironment() {
143
- const vars = this.getProxyEnvironmentVariables();
144
- return !!(vars.HTTP_PROXY || vars.HTTPS_PROXY);
145
- }
146
152
  }
147
153
  exports.ProxyEnvironmentParser = ProxyEnvironmentParser;
148
154
  ProxyEnvironmentParser.logger = new common_1.Logger(ProxyEnvironmentParser.name);
@@ -21,10 +21,6 @@ export declare class RetryRecorder {
21
21
  * 获取重试原因
22
22
  */
23
23
  private static getRetryReason;
24
- /**
25
- * 过滤敏感头信息
26
- */
27
- private static sanitizeHeaders;
28
24
  /**
29
25
  * 添加重试记录
30
26
  */
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RetryRecorder = void 0;
4
+ const sanitize_util_1 = require("./sanitize.util");
4
5
  /**
5
6
  * 请求重试记录器
6
7
  */
@@ -22,7 +23,7 @@ class RetryRecorder {
22
23
  requestConfig: {
23
24
  method: ((_a = config.method) === null || _a === void 0 ? void 0 : _a.toUpperCase()) || 'UNKNOWN',
24
25
  url: config.url || '',
25
- headers: this.sanitizeHeaders(config.headers || {}),
26
+ headers: sanitize_util_1.SanitizeUtil.sanitizeHeaders(config.headers || {}),
26
27
  },
27
28
  };
28
29
  }
@@ -83,32 +84,6 @@ class RetryRecorder {
83
84
  }
84
85
  return `HTTP error: ${status}`;
85
86
  }
86
- /**
87
- * 过滤敏感头信息
88
- */
89
- static sanitizeHeaders(headers) {
90
- const sanitized = {};
91
- const sensitiveKeys = [
92
- 'authorization',
93
- 'apikey',
94
- 'password',
95
- 'secret',
96
- 'token',
97
- 'x-api-key',
98
- 'x-auth-token',
99
- 'cookie',
100
- 'set-cookie',
101
- ];
102
- Object.entries(headers).forEach(([key, value]) => {
103
- if (sensitiveKeys.some((sensitive) => key.toLowerCase().includes(sensitive))) {
104
- sanitized[key] = '[FILTERED]';
105
- }
106
- else {
107
- sanitized[key] = value;
108
- }
109
- });
110
- return sanitized;
111
- }
112
87
  /**
113
88
  * 添加重试记录
114
89
  */
@@ -0,0 +1,58 @@
1
+ /**
2
+ * HTTP 请求数据脱敏工具
3
+ * 统一处理 headers、body、query string 的敏感信息过滤
4
+ */
5
+ export declare class SanitizeUtil {
6
+ /**
7
+ * 默认敏感字段列表
8
+ */
9
+ private static readonly DEFAULT_SENSITIVE_FIELDS;
10
+ /**
11
+ * 脱敏 headers
12
+ * @param headers - 原始 headers 对象
13
+ * @param sensitiveFields - 自定义敏感字段列表
14
+ * @returns 脱敏后的 headers
15
+ */
16
+ static sanitizeHeaders(headers: any, sensitiveFields?: string[]): Record<string, string>;
17
+ /**
18
+ * 脱敏 body
19
+ * @param body - 原始 body 数据
20
+ * @param sensitiveFields - 自定义敏感字段列表
21
+ * @returns 脱敏后的 body
22
+ */
23
+ static sanitizeBody(body: any, sensitiveFields?: string[]): any;
24
+ /**
25
+ * 脱敏 URL 中的 query string
26
+ * @param url - 原始 URL
27
+ * @param sensitiveFields - 自定义敏感字段列表
28
+ * @returns 脱敏后的 URL
29
+ */
30
+ static sanitizeQueryString(url: string, sensitiveFields?: string[]): string;
31
+ /**
32
+ * 脱敏 params 对象
33
+ * @param params - 原始 params 对象
34
+ * @param sensitiveFields - 自定义敏感字段列表
35
+ * @returns 脱敏后的 params
36
+ */
37
+ static sanitizeParams(params: Record<string, any>, sensitiveFields?: string[]): Record<string, any>;
38
+ /**
39
+ * 将 body 转换为字符串并脱敏
40
+ * @param data - 原始数据
41
+ * @param sensitiveFields - 自定义敏感字段列表
42
+ * @returns 脱敏后的字符串
43
+ */
44
+ static sanitizeBodyAsString(data: any, sensitiveFields?: string[]): string | undefined;
45
+ /**
46
+ * 判断字段是否为敏感字段
47
+ * @param key - 字段名
48
+ * @param sensitiveFields - 敏感字段列表
49
+ * @returns 是否为敏感字段
50
+ */
51
+ private static isSensitiveField;
52
+ /**
53
+ * 递归脱敏对象中的敏感字段
54
+ * @param obj - 目标对象
55
+ * @param sensitiveFields - 敏感字段列表
56
+ */
57
+ private static sanitizeObject;
58
+ }