nstarter-http-request 0.1.0

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 (263) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/README.md +160 -0
  3. package/dist/cjs/adapter/axios.adapter.js +224 -0
  4. package/dist/cjs/adapter/axios.adapter.js.map +1 -0
  5. package/dist/cjs/adapter/base.js +134 -0
  6. package/dist/cjs/adapter/base.js.map +1 -0
  7. package/dist/cjs/adapter/index.js +20 -0
  8. package/dist/cjs/adapter/index.js.map +1 -0
  9. package/dist/cjs/adapter/undici.adapter.js +272 -0
  10. package/dist/cjs/adapter/undici.adapter.js.map +1 -0
  11. package/dist/cjs/client.js +409 -0
  12. package/dist/cjs/client.js.map +1 -0
  13. package/dist/cjs/config.js +69 -0
  14. package/dist/cjs/config.js.map +1 -0
  15. package/dist/cjs/const/config.const.js +53 -0
  16. package/dist/cjs/const/config.const.js.map +1 -0
  17. package/dist/cjs/const/dns.const.js +16 -0
  18. package/dist/cjs/const/dns.const.js.map +1 -0
  19. package/dist/cjs/const/enum.const.js +22 -0
  20. package/dist/cjs/const/enum.const.js.map +1 -0
  21. package/dist/cjs/const/index.js +21 -0
  22. package/dist/cjs/const/index.js.map +1 -0
  23. package/dist/cjs/const/ip.const.js +110 -0
  24. package/dist/cjs/const/ip.const.js.map +1 -0
  25. package/dist/cjs/index.js +25 -0
  26. package/dist/cjs/index.js.map +1 -0
  27. package/dist/cjs/logger/base.js +60 -0
  28. package/dist/cjs/logger/base.js.map +1 -0
  29. package/dist/cjs/logger/http_client.logger.js +209 -0
  30. package/dist/cjs/logger/http_client.logger.js.map +1 -0
  31. package/dist/cjs/logger/index.js +20 -0
  32. package/dist/cjs/logger/index.js.map +1 -0
  33. package/dist/cjs/logger/log.filter.js +126 -0
  34. package/dist/cjs/logger/log.filter.js.map +1 -0
  35. package/dist/cjs/security/dns.validator.js +137 -0
  36. package/dist/cjs/security/dns.validator.js.map +1 -0
  37. package/dist/cjs/security/index.js +21 -0
  38. package/dist/cjs/security/index.js.map +1 -0
  39. package/dist/cjs/security/ip.validator.js +107 -0
  40. package/dist/cjs/security/ip.validator.js.map +1 -0
  41. package/dist/cjs/security/ssrf.guard.js +180 -0
  42. package/dist/cjs/security/ssrf.guard.js.map +1 -0
  43. package/dist/cjs/security/url.validator.js +170 -0
  44. package/dist/cjs/security/url.validator.js.map +1 -0
  45. package/dist/cjs/tsconfig.tsbuildinfo +1 -0
  46. package/dist/cjs/types/adapter.js +6 -0
  47. package/dist/cjs/types/adapter.js.map +1 -0
  48. package/dist/cjs/types/client.js +6 -0
  49. package/dist/cjs/types/client.js.map +1 -0
  50. package/dist/cjs/types/config.js +6 -0
  51. package/dist/cjs/types/config.js.map +1 -0
  52. package/dist/cjs/types/errors.js +35 -0
  53. package/dist/cjs/types/errors.js.map +1 -0
  54. package/dist/cjs/types/index.js +35 -0
  55. package/dist/cjs/types/index.js.map +1 -0
  56. package/dist/cjs/types/ip.js +6 -0
  57. package/dist/cjs/types/ip.js.map +1 -0
  58. package/dist/cjs/types/logger.js +6 -0
  59. package/dist/cjs/types/logger.js.map +1 -0
  60. package/dist/cjs/types/request_response.js +6 -0
  61. package/dist/cjs/types/request_response.js.map +1 -0
  62. package/dist/cjs/types/security.js +6 -0
  63. package/dist/cjs/types/security.js.map +1 -0
  64. package/dist/cjs/types/trace.js +14 -0
  65. package/dist/cjs/types/trace.js.map +1 -0
  66. package/dist/cjs/utils/common.js +31 -0
  67. package/dist/cjs/utils/common.js.map +1 -0
  68. package/dist/cjs/utils/domain.js +79 -0
  69. package/dist/cjs/utils/domain.js.map +1 -0
  70. package/dist/cjs/utils/index.js +44 -0
  71. package/dist/cjs/utils/index.js.map +1 -0
  72. package/dist/cjs/utils/ip.range.js +200 -0
  73. package/dist/cjs/utils/ip.range.js.map +1 -0
  74. package/dist/cjs/utils/trace.context.js +213 -0
  75. package/dist/cjs/utils/trace.context.js.map +1 -0
  76. package/dist/esm/adapter/axios.adapter.js +184 -0
  77. package/dist/esm/adapter/axios.adapter.js.map +1 -0
  78. package/dist/esm/adapter/base.js +130 -0
  79. package/dist/esm/adapter/base.js.map +1 -0
  80. package/dist/esm/adapter/index.js +4 -0
  81. package/dist/esm/adapter/index.js.map +1 -0
  82. package/dist/esm/adapter/undici.adapter.js +235 -0
  83. package/dist/esm/adapter/undici.adapter.js.map +1 -0
  84. package/dist/esm/client.js +405 -0
  85. package/dist/esm/client.js.map +1 -0
  86. package/dist/esm/config.js +65 -0
  87. package/dist/esm/config.js.map +1 -0
  88. package/dist/esm/const/config.const.js +50 -0
  89. package/dist/esm/const/config.const.js.map +1 -0
  90. package/dist/esm/const/dns.const.js +13 -0
  91. package/dist/esm/const/dns.const.js.map +1 -0
  92. package/dist/esm/const/enum.const.js +19 -0
  93. package/dist/esm/const/enum.const.js.map +1 -0
  94. package/dist/esm/const/index.js +5 -0
  95. package/dist/esm/const/index.js.map +1 -0
  96. package/dist/esm/const/ip.const.js +107 -0
  97. package/dist/esm/const/ip.const.js.map +1 -0
  98. package/dist/esm/index.js +9 -0
  99. package/dist/esm/index.js.map +1 -0
  100. package/dist/esm/logger/base.js +55 -0
  101. package/dist/esm/logger/base.js.map +1 -0
  102. package/dist/esm/logger/http_client.logger.js +205 -0
  103. package/dist/esm/logger/http_client.logger.js.map +1 -0
  104. package/dist/esm/logger/index.js +4 -0
  105. package/dist/esm/logger/index.js.map +1 -0
  106. package/dist/esm/logger/log.filter.js +122 -0
  107. package/dist/esm/logger/log.filter.js.map +1 -0
  108. package/dist/esm/security/dns.validator.js +133 -0
  109. package/dist/esm/security/dns.validator.js.map +1 -0
  110. package/dist/esm/security/index.js +5 -0
  111. package/dist/esm/security/index.js.map +1 -0
  112. package/dist/esm/security/ip.validator.js +103 -0
  113. package/dist/esm/security/ip.validator.js.map +1 -0
  114. package/dist/esm/security/ssrf.guard.js +176 -0
  115. package/dist/esm/security/ssrf.guard.js.map +1 -0
  116. package/dist/esm/security/url.validator.js +166 -0
  117. package/dist/esm/security/url.validator.js.map +1 -0
  118. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -0
  119. package/dist/esm/types/adapter.js +5 -0
  120. package/dist/esm/types/adapter.js.map +1 -0
  121. package/dist/esm/types/client.js +5 -0
  122. package/dist/esm/types/client.js.map +1 -0
  123. package/dist/esm/types/config.js +5 -0
  124. package/dist/esm/types/config.js.map +1 -0
  125. package/dist/esm/types/errors.js +30 -0
  126. package/dist/esm/types/errors.js.map +1 -0
  127. package/dist/esm/types/index.js +19 -0
  128. package/dist/esm/types/index.js.map +1 -0
  129. package/dist/esm/types/ip.js +5 -0
  130. package/dist/esm/types/ip.js.map +1 -0
  131. package/dist/esm/types/logger.js +5 -0
  132. package/dist/esm/types/logger.js.map +1 -0
  133. package/dist/esm/types/request_response.js +5 -0
  134. package/dist/esm/types/request_response.js.map +1 -0
  135. package/dist/esm/types/security.js +5 -0
  136. package/dist/esm/types/security.js.map +1 -0
  137. package/dist/esm/types/trace.js +11 -0
  138. package/dist/esm/types/trace.js.map +1 -0
  139. package/dist/esm/utils/common.js +27 -0
  140. package/dist/esm/utils/common.js.map +1 -0
  141. package/dist/esm/utils/domain.js +71 -0
  142. package/dist/esm/utils/domain.js.map +1 -0
  143. package/dist/esm/utils/index.js +7 -0
  144. package/dist/esm/utils/index.js.map +1 -0
  145. package/dist/esm/utils/ip.range.js +187 -0
  146. package/dist/esm/utils/ip.range.js.map +1 -0
  147. package/dist/esm/utils/trace.context.js +199 -0
  148. package/dist/esm/utils/trace.context.js.map +1 -0
  149. package/dist/types/adapter/axios.adapter.d.ts +51 -0
  150. package/dist/types/adapter/axios.adapter.d.ts.map +1 -0
  151. package/dist/types/adapter/base.d.ts +56 -0
  152. package/dist/types/adapter/base.d.ts.map +1 -0
  153. package/dist/types/adapter/index.d.ts +4 -0
  154. package/dist/types/adapter/index.d.ts.map +1 -0
  155. package/dist/types/adapter/undici.adapter.d.ts +68 -0
  156. package/dist/types/adapter/undici.adapter.d.ts.map +1 -0
  157. package/dist/types/client.d.ts +105 -0
  158. package/dist/types/client.d.ts.map +1 -0
  159. package/dist/types/config.d.ts +14 -0
  160. package/dist/types/config.d.ts.map +1 -0
  161. package/dist/types/const/config.const.d.ts +23 -0
  162. package/dist/types/const/config.const.d.ts.map +1 -0
  163. package/dist/types/const/dns.const.d.ts +13 -0
  164. package/dist/types/const/dns.const.d.ts.map +1 -0
  165. package/dist/types/const/enum.const.d.ts +17 -0
  166. package/dist/types/const/enum.const.d.ts.map +1 -0
  167. package/dist/types/const/index.d.ts +5 -0
  168. package/dist/types/const/index.d.ts.map +1 -0
  169. package/dist/types/const/ip.const.d.ts +42 -0
  170. package/dist/types/const/ip.const.d.ts.map +1 -0
  171. package/dist/types/index.d.ts +9 -0
  172. package/dist/types/index.d.ts.map +1 -0
  173. package/dist/types/logger/base.d.ts +42 -0
  174. package/dist/types/logger/base.d.ts.map +1 -0
  175. package/dist/types/logger/http_client.logger.d.ts +49 -0
  176. package/dist/types/logger/http_client.logger.d.ts.map +1 -0
  177. package/dist/types/logger/index.d.ts +4 -0
  178. package/dist/types/logger/index.d.ts.map +1 -0
  179. package/dist/types/logger/log.filter.d.ts +56 -0
  180. package/dist/types/logger/log.filter.d.ts.map +1 -0
  181. package/dist/types/security/dns.validator.d.ts +61 -0
  182. package/dist/types/security/dns.validator.d.ts.map +1 -0
  183. package/dist/types/security/index.d.ts +5 -0
  184. package/dist/types/security/index.d.ts.map +1 -0
  185. package/dist/types/security/ip.validator.d.ts +31 -0
  186. package/dist/types/security/ip.validator.d.ts.map +1 -0
  187. package/dist/types/security/ssrf.guard.d.ts +54 -0
  188. package/dist/types/security/ssrf.guard.d.ts.map +1 -0
  189. package/dist/types/security/url.validator.d.ts +76 -0
  190. package/dist/types/security/url.validator.d.ts.map +1 -0
  191. package/dist/types/types/adapter.d.ts +30 -0
  192. package/dist/types/types/adapter.d.ts.map +1 -0
  193. package/dist/types/types/client.d.ts +85 -0
  194. package/dist/types/types/client.d.ts.map +1 -0
  195. package/dist/types/types/config.d.ts +99 -0
  196. package/dist/types/types/config.d.ts.map +1 -0
  197. package/dist/types/types/errors.d.ts +23 -0
  198. package/dist/types/types/errors.d.ts.map +1 -0
  199. package/dist/types/types/index.d.ts +10 -0
  200. package/dist/types/types/index.d.ts.map +1 -0
  201. package/dist/types/types/ip.d.ts +32 -0
  202. package/dist/types/types/ip.d.ts.map +1 -0
  203. package/dist/types/types/logger.d.ts +136 -0
  204. package/dist/types/types/logger.d.ts.map +1 -0
  205. package/dist/types/types/request_response.d.ts +54 -0
  206. package/dist/types/types/request_response.d.ts.map +1 -0
  207. package/dist/types/types/security.d.ts +115 -0
  208. package/dist/types/types/security.d.ts.map +1 -0
  209. package/dist/types/types/trace.d.ts +34 -0
  210. package/dist/types/types/trace.d.ts.map +1 -0
  211. package/dist/types/utils/common.d.ts +14 -0
  212. package/dist/types/utils/common.d.ts.map +1 -0
  213. package/dist/types/utils/domain.d.ts +39 -0
  214. package/dist/types/utils/domain.d.ts.map +1 -0
  215. package/dist/types/utils/index.d.ts +6 -0
  216. package/dist/types/utils/index.d.ts.map +1 -0
  217. package/dist/types/utils/ip.range.d.ts +61 -0
  218. package/dist/types/utils/ip.range.d.ts.map +1 -0
  219. package/dist/types/utils/trace.context.d.ts +106 -0
  220. package/dist/types/utils/trace.context.d.ts.map +1 -0
  221. package/docs/adapters.md +53 -0
  222. package/docs/configuration.md +149 -0
  223. package/docs/logging.md +70 -0
  224. package/docs/proxy.md +44 -0
  225. package/docs/security.md +56 -0
  226. package/docs/trace-context.md +436 -0
  227. package/package.json +50 -0
  228. package/src/adapter/axios.adapter.ts +228 -0
  229. package/src/adapter/base.ts +180 -0
  230. package/src/adapter/index.ts +3 -0
  231. package/src/adapter/undici.adapter.ts +282 -0
  232. package/src/client.ts +552 -0
  233. package/src/config.ts +86 -0
  234. package/src/const/config.const.ts +60 -0
  235. package/src/const/dns.const.ts +15 -0
  236. package/src/const/enum.const.ts +17 -0
  237. package/src/const/index.ts +4 -0
  238. package/src/const/ip.const.ts +139 -0
  239. package/src/index.ts +8 -0
  240. package/src/logger/base.ts +75 -0
  241. package/src/logger/http_client.logger.ts +272 -0
  242. package/src/logger/index.ts +3 -0
  243. package/src/logger/log.filter.ts +149 -0
  244. package/src/security/dns.validator.ts +170 -0
  245. package/src/security/index.ts +4 -0
  246. package/src/security/ip.validator.ts +124 -0
  247. package/src/security/ssrf.guard.ts +224 -0
  248. package/src/security/url.validator.ts +192 -0
  249. package/src/types/adapter.ts +38 -0
  250. package/src/types/client.ts +119 -0
  251. package/src/types/config.ts +110 -0
  252. package/src/types/errors.ts +38 -0
  253. package/src/types/index.ts +27 -0
  254. package/src/types/ip.ts +34 -0
  255. package/src/types/logger.ts +150 -0
  256. package/src/types/request_response.ts +65 -0
  257. package/src/types/security.ts +126 -0
  258. package/src/types/trace.ts +35 -0
  259. package/src/utils/common.ts +28 -0
  260. package/src/utils/domain.ts +78 -0
  261. package/src/utils/index.ts +7 -0
  262. package/src/utils/ip.range.ts +218 -0
  263. package/src/utils/trace.context.ts +240 -0
@@ -0,0 +1,405 @@
1
+ /**
2
+ * HTTP 客户端核心类
3
+ */
4
+ import { mergeConfig, validateConfig } from './config';
5
+ import { SsrfGuard } from './security';
6
+ import { AxiosAdapter, UndiciAdapter } from './adapter';
7
+ import { NullLogger, NsHttpClientLogger } from './logger';
8
+ import { EClientAdapter } from './const';
9
+ import { HttpError } from './types';
10
+ import { DomainUtils, TraceContextUtils } from './utils';
11
+ import { PassThrough, Readable } from 'node:stream';
12
+ /**
13
+ * HTTP 客户端
14
+ */
15
+ export class NsHttpClient {
16
+ constructor(userConfig = {}) {
17
+ // 合并配置
18
+ this.config = mergeConfig(userConfig);
19
+ // 验证配置
20
+ validateConfig(this.config);
21
+ // 初始化日志记录器
22
+ this.logger = this.initLogger();
23
+ this.httpLogger = this.initHttpLogger();
24
+ // 初始化 SSRF 防护
25
+ this.ssrfGuard = new SsrfGuard(this.config.security);
26
+ // 初始化适配器
27
+ this.adapter = this.initAdapter();
28
+ this.logger.debug('NsHttpClient initialized', {
29
+ adapter: this.config.adapter,
30
+ security: {
31
+ enableDnsValidation: this.config.security.enableDnsValidation,
32
+ enableIpValidation: this.config.security.enableIpValidation,
33
+ allowPrivateIp: this.config.security.allowPrivateIp
34
+ }
35
+ });
36
+ }
37
+ /**
38
+ * 从配置创建 HTTP 客户端
39
+ * @param config
40
+ */
41
+ static fromHttpClientConfig(config = {}) {
42
+ return new NsHttpClient(config);
43
+ }
44
+ /**
45
+ * 挂载适配器.
46
+ * @param adapter
47
+ */
48
+ withAdapter(adapter) {
49
+ this.config.adapter = adapter;
50
+ this.adapter = this.initAdapter();
51
+ return this;
52
+ }
53
+ /**
54
+ * 挂载正向代理.
55
+ * @param proxy
56
+ */
57
+ withForwardProxy(proxy) {
58
+ this.forwardProxy = proxy;
59
+ this.logger.info('Forward proxy configured', {
60
+ enabled: proxy.enabled,
61
+ http_proxy: proxy.http_proxy,
62
+ https_proxy: proxy.https_proxy,
63
+ no_proxy_count: proxy.no_proxy?.length || 0
64
+ });
65
+ return this;
66
+ }
67
+ /**
68
+ * 初始化日志记录器
69
+ */
70
+ initLogger() {
71
+ if (!this.config.logging.enabled) {
72
+ return new NullLogger();
73
+ }
74
+ return this.config.logging.logger || new NullLogger();
75
+ }
76
+ /**
77
+ * 初始化 HTTP 客户端日志记录器
78
+ */
79
+ initHttpLogger() {
80
+ if (!this.config.logging.enabled) {
81
+ return undefined;
82
+ }
83
+ // 如果用户提供了自定义的 httpLogger,直接使用
84
+ if (this.config.logging.httpLogger) {
85
+ return this.config.logging.httpLogger;
86
+ }
87
+ // 否则,使用 NsHttpClientLogger 包装通用的 logger
88
+ return NsHttpClientLogger.create(this.logger, this.config.logging.filter, {
89
+ logRequestBody: this.config.logging.logRequestBody,
90
+ logResponseBody: this.config.logging.logResponseBody,
91
+ bodyMaxLength: this.config.logging.bodyMaxLength
92
+ });
93
+ }
94
+ /**
95
+ * 初始化适配器
96
+ */
97
+ initAdapter() {
98
+ const adapter = this.config.adapter === EClientAdapter.axios
99
+ ? new AxiosAdapter(this.config.request, this.config.security, this.logger)
100
+ : new UndiciAdapter(this.config.request, this.config.security, this.logger);
101
+ if (!adapter.isAvailable()) {
102
+ throw new Error(`Adapter "${this.config.adapter}" is not available. ` +
103
+ `Please install it: npm install ${this.config.adapter}`);
104
+ }
105
+ return adapter;
106
+ }
107
+ /**
108
+ * 发送 HTTP 请求
109
+ * @param options 请求选项
110
+ * @returns 响应结果
111
+ */
112
+ async request(options) {
113
+ const startTime = Date.now();
114
+ try {
115
+ // 安全验证
116
+ const { safeUrl, result: ssrfResult } = await this.ssrfGuard.validateAndGetSafeUrl(options.url);
117
+ this.logger.debug('URL validation passed', {
118
+ originalUrl: options.url,
119
+ safeUrl,
120
+ resolvedIps: ssrfResult.resolvedIps,
121
+ scenario: options.scenario
122
+ });
123
+ // 使用安全的 URL 发起请求
124
+ const safeOptions = {
125
+ ...options,
126
+ url: safeUrl
127
+ };
128
+ // 如果 URL 被替换为 IP,需要设置 Host 头
129
+ if (ssrfResult.safeIp && ssrfResult.hostname !== ssrfResult.safeIp) {
130
+ safeOptions.headers = {
131
+ ...safeOptions.headers,
132
+ Host: ssrfResult.hostname
133
+ };
134
+ }
135
+ // 处理 W3C Trace Context traceparent 头
136
+ if (options.traceparent) {
137
+ // 验证 traceparent 格式
138
+ if (!TraceContextUtils.isValidTraceParent(options.traceparent)) {
139
+ this.logger.warn('Invalid traceparent format, ignoring', {
140
+ traceparent: options.traceparent
141
+ });
142
+ }
143
+ else {
144
+ safeOptions.headers = {
145
+ ...safeOptions.headers,
146
+ traceparent: options.traceparent
147
+ };
148
+ this.logger.debug('Traceparent header added', {
149
+ traceparent: options.traceparent,
150
+ sampled: TraceContextUtils.isSampled(options.traceparent)
151
+ });
152
+ }
153
+ }
154
+ // 应用正向代理配置
155
+ if (this.forwardProxy) {
156
+ this.applyForwardProxy(safeOptions);
157
+ }
158
+ // 发起请求
159
+ const response = await this.adapter.request(safeOptions);
160
+ // 首次响应时间(TTFB)
161
+ const ttfb = Date.now() - startTime;
162
+ // 如果是流式响应,包装流对象以追踪完整生命周期
163
+ if (options.responseType === 'stream' && this.isStreamResponse(response.data)) {
164
+ return this.wrapStreamResponse(safeOptions, response, startTime, ttfb);
165
+ }
166
+ // 记录非流式响应日志
167
+ this.logResponse(safeOptions, response, ttfb);
168
+ return response;
169
+ }
170
+ catch (error) {
171
+ // 记录错误日志
172
+ this.logError(options, error, Date.now() - startTime);
173
+ throw error;
174
+ }
175
+ }
176
+ /**
177
+ * 便捷方法:GET 请求
178
+ */
179
+ async get(url, options) {
180
+ return this.request({ ...options, method: 'GET', url });
181
+ }
182
+ /**
183
+ * 便捷方法:POST 请求
184
+ */
185
+ async post(url, body, options) {
186
+ return this.request({ ...options, method: 'POST', url, body });
187
+ }
188
+ /**
189
+ * 便捷方法:PUT 请求
190
+ */
191
+ async put(url, body, options) {
192
+ return this.request({ ...options, method: 'PUT', url, body });
193
+ }
194
+ /**
195
+ * 便捷方法:DELETE 请求
196
+ */
197
+ async delete(url, options) {
198
+ return this.request({ ...options, method: 'DELETE', url });
199
+ }
200
+ /**
201
+ * 便捷方法:PATCH 请求
202
+ */
203
+ async patch(url, body, options) {
204
+ return this.request({ ...options, method: 'PATCH', url, body });
205
+ }
206
+ /**
207
+ * 记录响应日志
208
+ */
209
+ logResponse(options, response, duration, streamMetrics) {
210
+ if (!this.httpLogger) {
211
+ return;
212
+ }
213
+ // 计算实际重试次数
214
+ const retryCount = options.retries ?? this.config.request.retries;
215
+ this.httpLogger.logSuccess({
216
+ request: {
217
+ method: options.method,
218
+ url: options.url,
219
+ headers: options.headers,
220
+ body: options.body,
221
+ scenario: options.scenario,
222
+ meta: options.meta
223
+ },
224
+ response,
225
+ duration,
226
+ retryCount,
227
+ streamMetrics
228
+ });
229
+ }
230
+ /**
231
+ * 判断响应数据是否为流对象(Node.js Readable)
232
+ */
233
+ isStreamResponse(data) {
234
+ // undici 和 axios 都返回 Node.js Readable
235
+ return data instanceof Readable;
236
+ }
237
+ /**
238
+ * 包装流式响应,追踪流的完整生命周期
239
+ */
240
+ /* eslint-disable max-lines-per-function */
241
+ wrapStreamResponse(options, response, requestStartTime, ttfb) {
242
+ const stream = response.data;
243
+ let bytesTransferred = 0;
244
+ // 记录首次响应日志(流开始)
245
+ this.logResponse(options, response, ttfb, {
246
+ ttfb,
247
+ completed: false
248
+ });
249
+ this.logger.debug('Stream response started', {
250
+ method: options.method,
251
+ url: options.url,
252
+ ttfb,
253
+ status: response.status
254
+ });
255
+ // 所有适配器都返回 Node.js Readable
256
+ const originalStream = stream;
257
+ const wrappedStream = new PassThrough();
258
+ // 监听数据事件统计字节数
259
+ originalStream.on('data', (chunk) => {
260
+ bytesTransferred += chunk.length;
261
+ wrappedStream.write(chunk);
262
+ });
263
+ // 监听结束事件记录日志
264
+ originalStream.on('end', () => {
265
+ const totalDuration = Date.now() - requestStartTime;
266
+ wrappedStream.end();
267
+ // 记录流完成日志
268
+ this.logStreamCompleted(options, response, ttfb, totalDuration, bytesTransferred);
269
+ });
270
+ // 监听错误事件
271
+ originalStream.on('error', (error) => {
272
+ const totalDuration = Date.now() - requestStartTime;
273
+ this.logger.error('Stream read error', {
274
+ method: options.method,
275
+ url: options.url,
276
+ ttfb,
277
+ totalDuration,
278
+ bytesTransferred,
279
+ error: error.message
280
+ });
281
+ wrappedStream.destroy(error);
282
+ });
283
+ // 使用 pipe 连接流
284
+ originalStream.pipe(wrappedStream, { end: false });
285
+ // 返回包装后的响应
286
+ return {
287
+ ...response,
288
+ data: wrappedStream
289
+ };
290
+ }
291
+ /**
292
+ * 记录流完成日志
293
+ */
294
+ logStreamCompleted(options, response, ttfb, totalDuration, bytesTransferred) {
295
+ // 记录流完成日志
296
+ this.logResponse(options, response, totalDuration, {
297
+ ttfb,
298
+ completed: true,
299
+ totalDuration,
300
+ bytesTransferred
301
+ });
302
+ this.logger.debug('Stream response completed', {
303
+ method: options.method,
304
+ url: options.url,
305
+ ttfb,
306
+ totalDuration,
307
+ streamDuration: totalDuration - ttfb,
308
+ bytesTransferred,
309
+ throughput: bytesTransferred > 0 && totalDuration > ttfb
310
+ ? `${(bytesTransferred / 1024 / ((totalDuration - ttfb) / 1000)).toFixed(2)} KB/s`
311
+ : 'N/A'
312
+ });
313
+ }
314
+ /**
315
+ * 记录错误日志
316
+ */
317
+ logError(options, error, duration) {
318
+ if (!this.httpLogger) {
319
+ return;
320
+ }
321
+ // 计算实际重试次数
322
+ const retryCount = options.retries ?? this.config.request.retries;
323
+ const httpError = error instanceof HttpError ? error : undefined;
324
+ this.httpLogger.logFailed({
325
+ request: {
326
+ method: options.method,
327
+ url: options.url,
328
+ headers: options.headers,
329
+ body: options.body,
330
+ scenario: options.scenario,
331
+ meta: options.meta
332
+ },
333
+ error: error instanceof Error ? error : new Error(String(error)),
334
+ errorCode: httpError?.code || 'UNKNOWN_ERROR',
335
+ status: httpError?.status,
336
+ response: httpError?.response,
337
+ duration,
338
+ retryCount
339
+ });
340
+ }
341
+ /**
342
+ * 应用正向代理配置
343
+ * @param options 请求选项
344
+ */
345
+ applyForwardProxy(options) {
346
+ if (!this.forwardProxy || !this.forwardProxy.enabled) {
347
+ return;
348
+ }
349
+ const { https_proxy, http_proxy, no_proxy } = this.forwardProxy;
350
+ // 解析目标 URL
351
+ const targetUrl = new URL(options.url);
352
+ const hostname = targetUrl.hostname;
353
+ // 检查 no_proxy 规则(使用传统匹配模式)
354
+ const noProxyRegExps = DomainUtils.createLegacyDomainMatchers(no_proxy ?? []);
355
+ if (noProxyRegExps.length > 0 && hostname) {
356
+ for (const noProxyRegex of noProxyRegExps) {
357
+ if (noProxyRegex.test(hostname)) {
358
+ this.logger.debug('Skip proxy for no_proxy matched host', {
359
+ hostname,
360
+ pattern: noProxyRegex.source
361
+ });
362
+ return;
363
+ }
364
+ }
365
+ }
366
+ const protocol = targetUrl.protocol || 'http:';
367
+ const isHttps = /https:?/.test(protocol);
368
+ const proxyUrl = isHttps ? https_proxy : http_proxy;
369
+ if (!proxyUrl) {
370
+ this.logger.warn('Forward proxy enabled but proxy URL not configured', {
371
+ protocol
372
+ });
373
+ return;
374
+ }
375
+ // 将代理信息附加到请求元数据中,由适配器处理
376
+ options.meta = {
377
+ ...options.meta,
378
+ __forwardProxy: {
379
+ proxyUrl,
380
+ isHttps,
381
+ protocol
382
+ }
383
+ };
384
+ this.logger.debug('Applied forward proxy', {
385
+ url: options.url,
386
+ proxyUrl,
387
+ isHttps
388
+ });
389
+ }
390
+ /**
391
+ * 清空 DNS 缓存
392
+ */
393
+ clearDnsCache() {
394
+ this.ssrfGuard.clearDnsCache();
395
+ this.logger.debug('DNS cache cleared');
396
+ }
397
+ /**
398
+ * 获取 DNS 缓存大小
399
+ * @returns 缓存条目数量
400
+ */
401
+ getDnsCacheSize() {
402
+ return this.ssrfGuard.getDnsCacheSize();
403
+ }
404
+ }
405
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ import { DEFAULT_HTTP_CLIENT_CONFIG, DEFAULT_LOGGING_CONFIG, DEFAULT_REQUEST_CONFIG, DEFAULT_SECURITY_CONFIG, MAX_DNS_CACHE_TTL } from './const';
2
+ /**
3
+ * 合并配置
4
+ * @param userConfig 用户配置
5
+ * @returns 完整配置
6
+ */
7
+ export function mergeConfig(userConfig = {}) {
8
+ return {
9
+ adapter: userConfig.adapter ?? DEFAULT_HTTP_CLIENT_CONFIG.adapter,
10
+ security: {
11
+ ...DEFAULT_SECURITY_CONFIG,
12
+ ...userConfig.security
13
+ },
14
+ logging: {
15
+ ...DEFAULT_LOGGING_CONFIG,
16
+ ...userConfig.logging
17
+ },
18
+ request: {
19
+ ...DEFAULT_REQUEST_CONFIG,
20
+ ...userConfig.request
21
+ }
22
+ };
23
+ }
24
+ /**
25
+ * 验证配置
26
+ * @param config 配置
27
+ * @throws {Error} 配置无效时抛出错误
28
+ */
29
+ export function validateConfig(config) {
30
+ // 验证适配器
31
+ if (!['axios', 'undici'].includes(config.adapter)) {
32
+ throw new Error(`Invalid adapter: ${config.adapter}. Must be 'axios' or 'undici'.`);
33
+ }
34
+ // 验证安全配置
35
+ if (config.security.dnsCacheTtl < 0) {
36
+ throw new Error('DNS cache TTL must be non-negative.');
37
+ }
38
+ if (config.security.dnsCacheTtl > MAX_DNS_CACHE_TTL) {
39
+ throw new Error(`DNS cache TTL must not exceed ${MAX_DNS_CACHE_TTL}ms (24 hours) to prevent memory buildup.`);
40
+ }
41
+ // 验证请求配置
42
+ if (config.request.timeout <= 0) {
43
+ throw new Error('Timeout must be positive.');
44
+ }
45
+ if (config.request.retries < 0) {
46
+ throw new Error('Retries must be non-negative.');
47
+ }
48
+ if (config.request.retryDelay < 0) {
49
+ throw new Error('Retry delay must be non-negative.');
50
+ }
51
+ if (config.request.maxRedirects < 0) {
52
+ throw new Error('Max redirects must be non-negative.');
53
+ }
54
+ if (config.request.maxRequestBodySize <= 0) {
55
+ throw new Error('Max request body size must be positive.');
56
+ }
57
+ if (config.request.maxResponseBodySize <= 0) {
58
+ throw new Error('Max response body size must be positive.');
59
+ }
60
+ // 验证日志配置
61
+ if (config.logging.bodyMaxLength <= 0) {
62
+ throw new Error('Body max length must be positive.');
63
+ }
64
+ }
65
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,0BAA0B,EAC1B,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,iBAAiB,EACpB,MAAM,SAAS,CAAC;AAEjB;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,aAAsC,EAAE;IAChE,OAAO;QACH,OAAO,EAAE,UAAU,CAAC,OAAO,IAAI,0BAA0B,CAAC,OAAO;QACjE,QAAQ,EAAE;YACN,GAAG,uBAAuB;YAC1B,GAAG,UAAU,CAAC,QAAQ;SACzB;QACD,OAAO,EAAE;YACL,GAAG,sBAAsB;YACzB,GAAG,UAAU,CAAC,OAAO;SACxB;QACD,OAAO,EAAE;YACL,GAAG,sBAAsB;YACzB,GAAG,UAAU,CAAC,OAAO;SACxB;KACJ,CAAC;AACN,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,MAAwB;IACnD,QAAQ;IACR,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,oBAAqB,MAAM,CAAC,OAAQ,gCAAgC,CAAC,CAAC;IAC1F,CAAC;IAED,SAAS;IACT,IAAI,MAAM,CAAC,QAAQ,CAAC,WAAW,GAAG,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IAC3D,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,CAAC,WAAW,GAAG,iBAAiB,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,iCAAkC,iBAAkB,0CAA0C,CAAC,CAAC;IACpH,CAAC;IAED,SAAS;IACT,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,IAAI,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACzD,CAAC;IAED,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,GAAG,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IAC3D,CAAC;IAED,IAAI,MAAM,CAAC,OAAO,CAAC,kBAAkB,IAAI,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC/D,CAAC;IAED,IAAI,MAAM,CAAC,OAAO,CAAC,mBAAmB,IAAI,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAChE,CAAC;IAED,SAAS;IACT,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,IAAI,CAAC,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACzD,CAAC;AACL,CAAC"}
@@ -0,0 +1,50 @@
1
+ import { EClientAdapter } from './enum.const';
2
+ import { DEFAULT_DNS_CACHE_TTL, DEFAULT_DNS_CACHE_MAX_SIZE } from './dns.const';
3
+ /**
4
+ * DNS 缓存最大 TTL(毫秒)- 5 分钟
5
+ * 避免过长的缓存时间导致内存积压
6
+ */
7
+ export const MAX_DNS_CACHE_TTL = 5 * 60 * 1000; // 300000ms (5 分钟)
8
+ /**
9
+ * 默认安全配置
10
+ */
11
+ export const DEFAULT_SECURITY_CONFIG = {
12
+ rejectUnauthorized: true,
13
+ enableDnsValidation: true,
14
+ enableIpValidation: true,
15
+ allowPrivateIp: false,
16
+ whitelist: [],
17
+ blacklist: [],
18
+ dnsCacheTtl: DEFAULT_DNS_CACHE_TTL,
19
+ dnsCacheMaxSize: DEFAULT_DNS_CACHE_MAX_SIZE
20
+ };
21
+ /**
22
+ * 默认日志配置
23
+ */
24
+ export const DEFAULT_LOGGING_CONFIG = {
25
+ enabled: true,
26
+ logRequestBody: true,
27
+ logResponseBody: true,
28
+ bodyMaxLength: 1024 * 1024 // 1MB
29
+ };
30
+ /**
31
+ * 默认请求配置
32
+ */
33
+ export const DEFAULT_REQUEST_CONFIG = {
34
+ timeout: 30000, // 30 秒
35
+ retries: 0,
36
+ retryDelay: 1000, // 1 秒
37
+ maxRedirects: 5,
38
+ maxRequestBodySize: 10 * 1024 * 1024, // 10MB
39
+ maxResponseBodySize: 50 * 1024 * 1024 // 50MB
40
+ };
41
+ /**
42
+ * 默认 HTTP 客户端配置
43
+ */
44
+ export const DEFAULT_HTTP_CLIENT_CONFIG = {
45
+ adapter: EClientAdapter.axios,
46
+ security: DEFAULT_SECURITY_CONFIG,
47
+ logging: DEFAULT_LOGGING_CONFIG,
48
+ request: DEFAULT_REQUEST_CONFIG
49
+ };
50
+ //# sourceMappingURL=config.const.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.const.js","sourceRoot":"","sources":["../../../src/const/config.const.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAEhF;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,mBAAmB;AAEnE;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAmB;IACnD,kBAAkB,EAAE,IAAI;IACxB,mBAAmB,EAAE,IAAI;IACzB,kBAAkB,EAAE,IAAI;IACxB,cAAc,EAAE,KAAK;IACrB,SAAS,EAAE,EAAE;IACb,SAAS,EAAE,EAAE;IACb,WAAW,EAAE,qBAAqB;IAClC,eAAe,EAAE,0BAA0B;CAC9C,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAkB;IACjD,OAAO,EAAE,IAAI;IACb,cAAc,EAAE,IAAI;IACpB,eAAe,EAAE,IAAI;IACrB,aAAa,EAAE,IAAI,GAAG,IAAI,CAAC,MAAM;CACpC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAkB;IACjD,OAAO,EAAE,KAAK,EAAE,OAAO;IACvB,OAAO,EAAE,CAAC;IACV,UAAU,EAAE,IAAI,EAAE,MAAM;IACxB,YAAY,EAAE,CAAC;IACf,kBAAkB,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,OAAO;IAC7C,mBAAmB,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,OAAO;CAChD,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAqB;IACxD,OAAO,EAAE,cAAc,CAAC,KAAK;IAC7B,QAAQ,EAAE,uBAAuB;IACjC,OAAO,EAAE,sBAAsB;IAC/B,OAAO,EAAE,sBAAsB;CAClC,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * 默认 DNS 缓存 TTL(毫秒)- 60 秒
3
+ */
4
+ export const DEFAULT_DNS_CACHE_TTL = 60000;
5
+ /**
6
+ * 默认 DNS 解析超时时间(毫秒)- 3 秒
7
+ */
8
+ export const DEFAULT_DNS_RESOLVE_TIMEOUT = 3000;
9
+ /**
10
+ * 默认 DNS 缓存最大条目数
11
+ */
12
+ export const DEFAULT_DNS_CACHE_MAX_SIZE = 500;
13
+ //# sourceMappingURL=dns.const.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dns.const.js","sourceRoot":"","sources":["../../../src/const/dns.const.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAC;AAE3C;;GAEG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,IAAI,CAAC;AAEhD;;GAEG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * HTTP请求客户端适配器枚举.
3
+ */
4
+ export var EClientAdapter;
5
+ (function (EClientAdapter) {
6
+ EClientAdapter["axios"] = "axios";
7
+ EClientAdapter["undici"] = "undici";
8
+ })(EClientAdapter || (EClientAdapter = {}));
9
+ /**
10
+ * 日志级别
11
+ */
12
+ export var ELogLevel;
13
+ (function (ELogLevel) {
14
+ ELogLevel["DEBUG"] = "debug";
15
+ ELogLevel["INFO"] = "info";
16
+ ELogLevel["WARN"] = "warn";
17
+ ELogLevel["ERROR"] = "error";
18
+ })(ELogLevel || (ELogLevel = {}));
19
+ //# sourceMappingURL=enum.const.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enum.const.js","sourceRoot":"","sources":["../../../src/const/enum.const.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAN,IAAY,cAGX;AAHD,WAAY,cAAc;IACtB,iCAAiB,CAAA;IACjB,mCAAmB,CAAA;AACvB,CAAC,EAHW,cAAc,KAAd,cAAc,QAGzB;AAED;;GAEG;AACH,MAAM,CAAN,IAAY,SAKX;AALD,WAAY,SAAS;IACjB,4BAAe,CAAA;IACf,0BAAa,CAAA;IACb,0BAAa,CAAA;IACb,4BAAe,CAAA;AACnB,CAAC,EALW,SAAS,KAAT,SAAS,QAKpB"}
@@ -0,0 +1,5 @@
1
+ export * from './ip.const';
2
+ export * from './config.const';
3
+ export * from './enum.const';
4
+ export * from './dns.const';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/const/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC"}