@wiajs/req 1.7.7

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 (78) hide show
  1. package/CHANGELOG.md +1023 -0
  2. package/LICENSE +7 -0
  3. package/MIGRATION_GUIDE.md +3 -0
  4. package/README.md +1645 -0
  5. package/SECURITY.md +6 -0
  6. package/dist/node/req.cjs +4397 -0
  7. package/dist/node/req.mjs +3551 -0
  8. package/dist/web/req.mjs +2609 -0
  9. package/index.d.cts +545 -0
  10. package/index.d.ts +565 -0
  11. package/index.js +43 -0
  12. package/lib/adapters/README.md +37 -0
  13. package/lib/adapters/adapters.js +57 -0
  14. package/lib/adapters/fetch.js +229 -0
  15. package/lib/adapters/http.js +552 -0
  16. package/lib/adapters/xhr.js +200 -0
  17. package/lib/axios.js +89 -0
  18. package/lib/cancel/CancelToken.js +106 -0
  19. package/lib/cancel/CanceledError.js +20 -0
  20. package/lib/cancel/isCancel.js +4 -0
  21. package/lib/core/Axios.js +359 -0
  22. package/lib/core/AxiosError.js +89 -0
  23. package/lib/core/AxiosHeaders.js +243 -0
  24. package/lib/core/InterceptorManager.js +59 -0
  25. package/lib/core/README.md +8 -0
  26. package/lib/core/buildFullPath.js +18 -0
  27. package/lib/core/dispatchRequest.js +72 -0
  28. package/lib/core/mergeConfig.js +98 -0
  29. package/lib/core/settle.js +21 -0
  30. package/lib/core/transformData.js +22 -0
  31. package/lib/defaults/index.js +136 -0
  32. package/lib/defaults/transitional.js +6 -0
  33. package/lib/env/README.md +3 -0
  34. package/lib/env/classes/FormData.js +2 -0
  35. package/lib/env/data.js +1 -0
  36. package/lib/helpers/AxiosTransformStream.js +116 -0
  37. package/lib/helpers/AxiosURLSearchParams.js +50 -0
  38. package/lib/helpers/HttpStatusCode.js +69 -0
  39. package/lib/helpers/README.md +7 -0
  40. package/lib/helpers/ZlibHeaderTransformStream.js +22 -0
  41. package/lib/helpers/bind.js +6 -0
  42. package/lib/helpers/buildURL.js +42 -0
  43. package/lib/helpers/callbackify.js +14 -0
  44. package/lib/helpers/combineURLs.js +11 -0
  45. package/lib/helpers/composeSignals.js +37 -0
  46. package/lib/helpers/cookies.js +29 -0
  47. package/lib/helpers/deprecatedMethod.js +18 -0
  48. package/lib/helpers/formDataToJSON.js +78 -0
  49. package/lib/helpers/formDataToStream.js +77 -0
  50. package/lib/helpers/fromDataURI.js +44 -0
  51. package/lib/helpers/isAbsoluteURL.js +13 -0
  52. package/lib/helpers/isAxiosError.js +11 -0
  53. package/lib/helpers/isURLSameOrigin.js +50 -0
  54. package/lib/helpers/null.js +2 -0
  55. package/lib/helpers/parseHeaders.js +61 -0
  56. package/lib/helpers/parseProtocol.js +5 -0
  57. package/lib/helpers/progressEventReducer.js +54 -0
  58. package/lib/helpers/readBlob.js +13 -0
  59. package/lib/helpers/resolveConfig.js +45 -0
  60. package/lib/helpers/speedometer.js +40 -0
  61. package/lib/helpers/spread.js +26 -0
  62. package/lib/helpers/throttle.js +41 -0
  63. package/lib/helpers/toFormData.js +175 -0
  64. package/lib/helpers/toURLEncodedForm.js +15 -0
  65. package/lib/helpers/trackStream.js +75 -0
  66. package/lib/helpers/validator.js +84 -0
  67. package/lib/platform/browser/classes/Blob.js +2 -0
  68. package/lib/platform/browser/classes/FormData.js +2 -0
  69. package/lib/platform/browser/classes/URLSearchParams.js +3 -0
  70. package/lib/platform/browser/index.js +19 -0
  71. package/lib/platform/common/utils.js +37 -0
  72. package/lib/platform/index.js +6 -0
  73. package/lib/platform/node/classes/FormData.js +2 -0
  74. package/lib/platform/node/classes/URLSearchParams.js +3 -0
  75. package/lib/platform/node/index.js +16 -0
  76. package/lib/req.js +67 -0
  77. package/lib/utils.js +635 -0
  78. package/package.json +214 -0
@@ -0,0 +1,552 @@
1
+ import request from "@wiajs/request";
2
+ import Agent from "@wiajs/agent";
3
+ import { log as Log, name } from "@wiajs/log";
4
+ import utils from "../utils.js";
5
+ import settle from "../core/settle.js";
6
+ import buildFullPath from "../core/buildFullPath.js";
7
+ import buildURL from "../helpers/buildURL.js";
8
+ // import {getProxyForUrl} from 'proxy-from-env';
9
+ import util from "node:util";
10
+ // import followRedirects from 'follow-redirects';
11
+ // import Redirect from '../request/index.js'
12
+ import zlib from "node:zlib";
13
+ import { VERSION } from "../env/data.js";
14
+ import transitionalDefaults from "../defaults/transitional.js";
15
+ import AxiosError from "../core/AxiosError.js";
16
+ import CanceledError from "../cancel/CanceledError.js";
17
+ import platform from "../platform/index.js";
18
+ import fromDataURI from "../helpers/fromDataURI.js";
19
+ import stream from "node:stream";
20
+ import AxiosHeaders from "../core/AxiosHeaders.js";
21
+ import AxiosTransformStream from "../helpers/AxiosTransformStream.js";
22
+ import { EventEmitter } from "node:events";
23
+ import formDataToStream from "../helpers/formDataToStream.js";
24
+ import readBlob from "../helpers/readBlob.js";
25
+ import callbackify from "../helpers/callbackify.js";
26
+ import { progressEventReducer, progressEventDecorator, asyncDecorator } from "../helpers/progressEventReducer.js";
27
+ // import Agent from '../fea/agent.js'
28
+ const log = Log({
29
+ env: `wia:req:${name(import.meta.url)}`
30
+ });
31
+ const isBrotliSupported = utils.isFunction(zlib.createBrotliDecompress);
32
+ const isHttps = /https:?/;
33
+ const supportedProtocols = platform.protocols.map((protocol)=>`${protocol}:`);
34
+ const isHttpAdapterSupported = typeof process !== "undefined" && utils.kindOf(process) === "process";
35
+ /**
36
+ * !+++
37
+ * 将request 函数改为类,请求拆分为 init 初始化和 请求执行,
38
+ * 如需重新发起请求时,无需重新初始化
39
+ */ let HttpAdapter = class HttpAdapter {
40
+ /**
41
+ *
42
+ * @param {*} config
43
+ */ constructor(config){
44
+ this.isDone = false;
45
+ this.rejected = false;
46
+ /** @type {*} */ this.req = null;
47
+ /** @type {*} */ this.config = null;
48
+ /** @type {*} */ this.data = null;
49
+ /** @type {*} */ this.transport = null;
50
+ this.config = config;
51
+ // temporary internal emitter until the AxiosRequest class will be implemented
52
+ this.emitter = new EventEmitter();
53
+ }
54
+ /**
55
+ *
56
+ * @param {number} code
57
+ * @returns
58
+ */ noBody(code) {
59
+ return this.method === "HEAD" || // Informational
60
+ code >= 100 && code < 200 || // No Content
61
+ code === 204 || // Not Modified
62
+ code === 304;
63
+ }
64
+ /**
65
+ * 发起终止事件
66
+ * @param {*} reason
67
+ */ abort(reason) {
68
+ this.emitter.emit("abort", !reason || reason.type ? new CanceledError(null, this.config, this.req) : reason);
69
+ }
70
+ onFinished() {
71
+ const { config, emitter, abort } = this;
72
+ config?.cancelToken?.unsubscribe(abort);
73
+ config?.signal?.removeEventListener("abort", abort);
74
+ emitter?.removeAllListeners();
75
+ }
76
+ /**
77
+ *
78
+ * @param {*} value
79
+ * @param {*} isRejected
80
+ */ onDone(value, isRejected) {
81
+ this.isDone = true;
82
+ if (isRejected) {
83
+ this.rejected = true;
84
+ this.onFinished();
85
+ }
86
+ }
87
+ /**
88
+ *
89
+ * @param {*} value
90
+ * @param {*} isRejected
91
+ * @returns
92
+ */ done(value, isRejected) {
93
+ if (this.isDone) return;
94
+ this.isDone = true;
95
+ this?.onDone(value, isRejected);
96
+ }
97
+ /**
98
+ * 初始化,生成 options 供请求调用
99
+ * @returns {*} options
100
+ */ async init() {
101
+ // biome-ignore lint/complexity/noUselessThisAlias: <explanation>
102
+ const _ = this;
103
+ const { config } = _;
104
+ let { data, lookup, family } = config;
105
+ const method = config.method.toUpperCase();
106
+ _.method = method;
107
+ if (lookup) {
108
+ const _lookup = callbackify(lookup, /** @param {*} value */ (value)=>utils.isArray(value) ? value : [
109
+ value
110
+ ]);
111
+ // hotfix to support opt.all option which is required for node 20.x
112
+ /**
113
+ * @param {string} hostname
114
+ * @param {*} opt
115
+ * @param {*} cb
116
+ */ lookup = (hostname, opt, cb)=>{
117
+ _lookup(hostname, opt, (err, arg0, arg1)=>{
118
+ if (err) return cb(err);
119
+ const addresses = utils.isArray(arg0) ? arg0.map((addr)=>buildAddressEntry(addr)) : [
120
+ buildAddressEntry(arg0, arg1)
121
+ ];
122
+ opt.all ? cb(err, addresses) : cb(err, addresses[0].address, addresses[0].family);
123
+ });
124
+ };
125
+ }
126
+ if (config.cancelToken || config.signal) {
127
+ config.cancelToken?.subscribe(_.abort);
128
+ if (config.signal) {
129
+ if (config.signal.aborted) _.abort();
130
+ else config.signal.addEventListener("abort", _.abort);
131
+ }
132
+ }
133
+ // Parse url
134
+ const fullPath = buildFullPath(config.baseURL, config.url);
135
+ // 'https://user:pass@sub.host.com:8080/p/a/t/h?query=string#hash'
136
+ const parsed = new URL(fullPath, platform.hasBrowserEnv ? platform.origin : undefined);
137
+ // http: or https:
138
+ const protocol = parsed.protocol || supportedProtocols[0];
139
+ _.protocol = protocol;
140
+ if (protocol === "data:" && method !== "GET") {
141
+ // throw error
142
+ const response = {
143
+ status: 405,
144
+ statusText: "method not allowed",
145
+ headers: {},
146
+ config
147
+ };
148
+ throw new AxiosError(`Request failed with status code ${response.status}`, [
149
+ AxiosError.ERR_BAD_REQUEST,
150
+ AxiosError.ERR_BAD_RESPONSE
151
+ ][Math.floor(response.status / 100) - 4], response.config, response.request, response);
152
+ }
153
+ if (supportedProtocols.indexOf(protocol) === -1) {
154
+ throw new AxiosError(`Unsupported protocol ${protocol}`, AxiosError.ERR_BAD_REQUEST, config);
155
+ }
156
+ const headers = AxiosHeaders.from(config.headers).normalize();
157
+ // Set User-Agent (required by some servers)
158
+ // See https://github.com/axios/axios/issues/69
159
+ // User-Agent is specified; handle case where no UA header is desired
160
+ // Only set header if it hasn't been set in config
161
+ // ! headers.set('User-Agent', 'axios/' + VERSION, false);
162
+ headers.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.35", false);
163
+ const { onDownloadProgress, onUploadProgress, maxRate } = config;
164
+ // support for spec compliant FormData objects
165
+ if (utils.isSpecCompliantForm(data)) {
166
+ const userBoundary = headers.getContentType(/boundary=([-_\w\d]{10,70})/i);
167
+ data = formDataToStream(data, /** @param {*} formHeaders */ (formHeaders)=>headers.set(formHeaders), {
168
+ tag: `axios-${VERSION}-boundary`,
169
+ boundary: userBoundary?.[1] || undefined
170
+ });
171
+ // support for https://www.npmjs.com/package/form-data api
172
+ } else if (utils.isFormData(data) && utils.isFunction(data.getHeaders)) {
173
+ headers.set(data.getHeaders());
174
+ if (!headers.hasContentLength()) {
175
+ try {
176
+ const knownLength = await util.promisify(data.getLength).call(data);
177
+ Number.isFinite(knownLength) && knownLength >= 0 && headers.setContentLength(knownLength);
178
+ /*eslint no-empty:0*/ } catch (e) {}
179
+ }
180
+ } else if (utils.isBlob(data)) {
181
+ data.size && headers.setContentType(data.type || "application/octet-stream");
182
+ headers.setContentLength(data.size || 0);
183
+ data = stream.Readable.from(readBlob(data));
184
+ } else if (data && !utils.isStream(data)) {
185
+ if (Buffer.isBuffer(data)) {
186
+ // Nothing to do...
187
+ } else if (utils.isArrayBuffer(data)) {
188
+ data = Buffer.from(new Uint8Array(data));
189
+ } else if (utils.isString(data)) {
190
+ data = Buffer.from(data, "utf-8");
191
+ } else {
192
+ throw new AxiosError("Data after transformation must be a string, an ArrayBuffer, a Buffer, or a Stream", AxiosError.ERR_BAD_REQUEST, config);
193
+ }
194
+ // Add Content-Length header if data exists
195
+ headers.setContentLength(data.length, false);
196
+ if (config.maxBodyLength > -1 && data.length > config.maxBodyLength) {
197
+ throw new AxiosError("Request body larger than maxBodyLength limit", AxiosError.ERR_BAD_REQUEST, config);
198
+ }
199
+ }
200
+ const contentLength = utils.toFiniteNumber(headers.getContentLength());
201
+ let maxUploadRate;
202
+ let maxDownloadRate;
203
+ if (utils.isArray(maxRate)) [maxUploadRate, maxDownloadRate] = maxRate;
204
+ else {
205
+ maxUploadRate = maxRate;
206
+ maxDownloadRate = maxRate;
207
+ }
208
+ _.maxUploadRate = maxUploadRate;
209
+ _.maxDownloadRate = maxDownloadRate;
210
+ if (data && (onUploadProgress || maxUploadRate)) {
211
+ if (!utils.isStream(data)) {
212
+ data = stream.Readable.from(data, {
213
+ objectMode: false
214
+ });
215
+ }
216
+ data = stream.pipeline([
217
+ data,
218
+ new AxiosTransformStream({
219
+ maxRate: utils.toFiniteNumber(maxUploadRate)
220
+ })
221
+ ], utils.noop);
222
+ onUploadProgress && data.on("progress", flushOnFinish(data, progressEventDecorator(contentLength, progressEventReducer(asyncDecorator(onUploadProgress), false, 3))));
223
+ }
224
+ // HTTP basic authentication
225
+ let auth;
226
+ if (config.auth) {
227
+ const username = config.auth.username || "";
228
+ const password = config.auth.password || "";
229
+ auth = `${username}:${password}`;
230
+ }
231
+ if (!auth && parsed.username) {
232
+ const urlUsername = parsed.username;
233
+ const urlPassword = parsed.password;
234
+ auth = `${urlUsername}:${urlPassword}`;
235
+ }
236
+ auth && headers.delete("authorization");
237
+ let path;
238
+ try {
239
+ path = buildURL(parsed.pathname + parsed.search, config.params, config.paramsSerializer).replace(/^\?/, "");
240
+ } catch (err) {
241
+ /** @type {*} */ const customErr = new Error(err.message);
242
+ customErr.config = config;
243
+ customErr.url = config.url;
244
+ customErr.exists = true;
245
+ throw customErr;
246
+ }
247
+ headers.set("Accept-Encoding", `gzip, compress, deflate${isBrotliSupported ? ", br" : ""}`, false);
248
+ /** @type {*} */ const options = {
249
+ path,
250
+ method,
251
+ headers: headers.toJSON(),
252
+ agents: {
253
+ http: config.httpAgent,
254
+ https: config.httpsAgent
255
+ },
256
+ auth,
257
+ protocol,
258
+ family,
259
+ beforeRedirect: dispatchBeforeRedirect,
260
+ beforeRedirects: {}
261
+ };
262
+ // cacheable-lookup integration hotfix
263
+ if (!utils.isUndefined(lookup)) options.lookup = lookup;
264
+ if (config.socketPath) options.socketPath = config.socketPath;
265
+ else {
266
+ options.hostname = parsed.hostname.startsWith("[") ? parsed.hostname.slice(1, -1) : parsed.hostname;
267
+ options.port = parsed.port;
268
+ // ! proxy
269
+ if (config.agent) options.agents = new Agent(config.agent);
270
+ }
271
+ // 执行请求的具体对象
272
+ _.transport = config.transport;
273
+ const isHttpsRequest = isHttps.test(options.protocol);
274
+ options.agent = isHttpsRequest ? config.httpsAgent : config.httpAgent;
275
+ if (config.maxBodyLength > -1) options.maxBodyLength = config.maxBodyLength;
276
+ else options.maxBodyLength = Number.POSITIVE_INFINITY;
277
+ // maxRedirects 缺省 21,不跳转,直接使用系统http or https,不支持 stream
278
+ // if (config.maxRedirects === 0 && !config.stream) transport = isHttpsRequest ? https : http;
279
+ // 自动跳转
280
+ // else {
281
+ // 支持跳转或stream,需使用 http、https 封装类
282
+ if (config.maxRedirects) options.maxRedirects = config.maxRedirects;
283
+ if (config.beforeRedirect) options.beforeRedirects.config = config.beforeRedirect;
284
+ if (config.insecureHTTPParser) options.insecureHTTPParser = config.insecureHTTPParser;
285
+ _.options = options;
286
+ _.data = data;
287
+ log({
288
+ config
289
+ }, "init");
290
+ return options;
291
+ }
292
+ /**
293
+ * 执行请求
294
+ * 需抛出内部异常
295
+ * @param {Axios} axios 实例
296
+ * @returns {Promise<*>}
297
+ */ async request(axios) {
298
+ /** @type {*} */ // biome-ignore lint/style/useConst: <explanation>
299
+ let R;
300
+ // biome-ignore lint/complexity/noUselessThisAlias: <explanation>
301
+ const _ = this;
302
+ try {
303
+ await _.init();
304
+ const { transport, protocol, config, options, data, abort, emitter, maxDownloadRate } = _;
305
+ const { responseType, responseEncoding, onDownloadProgress } = config;
306
+ if (protocol === "data:") {
307
+ /** @type {*} */ let convertedData;
308
+ try {
309
+ convertedData = fromDataURI(config.url, responseType === "blob", {
310
+ Blob: config.env?.Blob
311
+ });
312
+ } catch (err) {
313
+ throw AxiosError.from(err, AxiosError.ERR_BAD_REQUEST, config);
314
+ }
315
+ if (responseType === "text") {
316
+ convertedData = convertedData.toString(responseEncoding);
317
+ if (!responseEncoding || responseEncoding === "utf8") {
318
+ convertedData = utils.stripBOM(convertedData);
319
+ }
320
+ } else if (responseType === "stream") {
321
+ convertedData = stream.Readable.from(convertedData);
322
+ }
323
+ // 返回响应
324
+ R = {
325
+ data: convertedData,
326
+ status: 200,
327
+ statusText: "OK",
328
+ headers: new AxiosHeaders(),
329
+ config
330
+ };
331
+ } else {
332
+ let transformStream;
333
+ if (onDownloadProgress || maxDownloadRate) {
334
+ transformStream = new AxiosTransformStream({
335
+ maxRate: utils.toFiniteNumber(maxDownloadRate)
336
+ });
337
+ onDownloadProgress && transformStream.on("progress", flushOnFinish(transformStream, progressEventDecorator(transformStream.responseLength, progressEventReducer(asyncDecorator(onDownloadProgress), true, 3))));
338
+ }
339
+ options.transformStream = transformStream;
340
+ // 发起异步请求
341
+ R = await new Promise((resolve, reject)=>{
342
+ _.emitter.once("abort", reject);
343
+ options.stream = config.stream;
344
+ options.decompress = config.decompress;
345
+ // Create the request,promise false: return stream
346
+ // log.debug('request', {options});
347
+ const req = transport ? transport.request(options) : request(options);
348
+ if (!req) return reject(new AxiosError("Request failed.", AxiosError.ERR_BAD_REQUEST, config));
349
+ _.req = req;
350
+ emitter.once("abort", (err)=>{
351
+ log("onabort");
352
+ reject(err);
353
+ req.destroy(err);
354
+ });
355
+ // Handle errors
356
+ req.on("error", /** @param {*} err */ (err)=>{
357
+ log("onerror");
358
+ // @todo remove
359
+ // if (req.aborted && err.code !== AxiosError.ERR_FR_TOO_MANY_REDIRECTS) return;
360
+ reject(AxiosError.from(err, null, config, req));
361
+ });
362
+ // set tcp keep alive to prevent drop connection by peer
363
+ req.on("socket", /** @param {*} socket */ (socket)=>{
364
+ log("onsocket");
365
+ // default interval of sending ack packet is 1 minute
366
+ socket.setKeepAlive(true, 1000 * 60);
367
+ });
368
+ // Handle request timeout
369
+ if (config.timeout) {
370
+ // This is forcing a int timeout to avoid problems if the `req` interface doesn't handle other types.
371
+ const timeout = Number.parseInt(config.timeout);
372
+ if (Number.isNaN(timeout)) {
373
+ reject(new AxiosError("error trying to parse `config.timeout` to int", AxiosError.ERR_BAD_OPTION_VALUE, config, req));
374
+ } else {
375
+ // Sometime, the response will be very slow, and does not respond, the connect event will be block by event loop system.
376
+ // And timer callback will be fired, and abort() will be invoked before connection, then get "socket hang up" and code ECONNRESET.
377
+ // At this time, if we have a large number of request, nodejs will hang up some socket on background. and the number will up and up.
378
+ // And then these socket which be hang up will devouring CPU little by little.
379
+ // ClientRequest.setTimeout will be fired on the specify milliseconds, and can make sure that abort() will be fired after connect.
380
+ req.setTimeout(timeout, ()=>{
381
+ if (_.isDone) return;
382
+ let timeoutErrorMessage = config.timeout ? `timeout of ${config.timeout}ms exceeded` : "timeout exceeded";
383
+ const transitional = config.transitional || transitionalDefaults;
384
+ if (config.timeoutErrorMessage) {
385
+ timeoutErrorMessage = config.timeoutErrorMessage;
386
+ }
387
+ reject(new AxiosError(timeoutErrorMessage, transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED, config, req));
388
+ abort();
389
+ });
390
+ }
391
+ }
392
+ // stream finished
393
+ req.on("finished", _.onFinished.bind(_));
394
+ // ! stream 模式不等待响应数据,直接返回 req,建立pipe管道流
395
+ if (config.stream) resolve(req);
396
+ else {
397
+ // 非stream模式,等待响应数据,返回数据
398
+ req.on("response", /**
399
+ * @param {*} res
400
+ * @param {*} stream
401
+ */ (res, stream)=>{
402
+ if (req.destroyed) return;
403
+ // 'transfer-encoding': 'chunked'时,无content-length,axios v1.2 不能自动解压
404
+ const responseLength = +res.headers["content-length"];
405
+ log("onresponse", {
406
+ statusCode: res.statusCode,
407
+ responseLength,
408
+ headers: res.headers
409
+ });
410
+ // return the last request(ClientRequest) in case of redirects
411
+ const lastRequest = res.req || req;
412
+ /** @type {*} */ const response = {
413
+ status: res.statusCode,
414
+ statusText: res.statusMessage,
415
+ headers: new AxiosHeaders(res.headers),
416
+ config,
417
+ request: lastRequest
418
+ };
419
+ // 直接返回 responseStream
420
+ if (responseType === "stream") {
421
+ response.data = stream;
422
+ settle(resolve, reject, response);
423
+ } else {
424
+ // 处理 responseStream
425
+ /** @type {*} */ const responseBuffer = [];
426
+ let totalResponseBytes = 0;
427
+ // 处理数据
428
+ stream.on("data", /** @param {*} chunk */ (chunk)=>{
429
+ responseBuffer.push(chunk);
430
+ totalResponseBytes += chunk.length;
431
+ // make sure the content length is not over the maxContentLength if specified
432
+ if (config.maxContentLength > -1 && totalResponseBytes > config.maxContentLength) {
433
+ // stream.destroy() emit aborted event before calling reject() on Node.js v16
434
+ _.rejected = true;
435
+ stream.destroy();
436
+ reject(new AxiosError(`maxContentLength size of ${config.maxContentLength} exceeded`, AxiosError.ERR_BAD_RESPONSE, config, lastRequest));
437
+ }
438
+ });
439
+ stream.on("aborted", function handlerStreamAborted() {
440
+ if (_.rejected) return;
441
+ const err = new AxiosError(`maxContentLength size of ${config.maxContentLength} exceeded`, AxiosError.ERR_BAD_RESPONSE, config, lastRequest);
442
+ stream.destroy(err);
443
+ reject(err);
444
+ });
445
+ stream.on("error", function handleStreamError(err) {
446
+ if (req.destroyed) return;
447
+ reject(AxiosError.from(err, null, config, lastRequest));
448
+ });
449
+ // 数据传输结束
450
+ stream.on("end", function handleStreamEnd() {
451
+ try {
452
+ let responseData = responseBuffer.length === 1 ? responseBuffer[0] : Buffer.concat(responseBuffer);
453
+ if (responseType !== "arraybuffer") {
454
+ responseData = responseData.toString(responseEncoding);
455
+ if (!responseEncoding || responseEncoding === "utf8") {
456
+ responseData = utils.stripBOM(responseData);
457
+ }
458
+ }
459
+ response.data = responseData;
460
+ settle(resolve, reject, response);
461
+ } catch (err) {
462
+ reject(AxiosError.from(err, null, config, response.request, response));
463
+ }
464
+ });
465
+ }
466
+ emitter.once("abort", (err)=>{
467
+ if (!stream.destroyed) {
468
+ stream.emit("error", err);
469
+ stream.destroy();
470
+ }
471
+ });
472
+ });
473
+ // 发送数据
474
+ if (utils.isStream(data)) {
475
+ // Send the request
476
+ let ended = false;
477
+ let errored = false;
478
+ data.on("end", ()=>{
479
+ ended = true;
480
+ });
481
+ data.once("error", /** @param {*} err */ (err)=>{
482
+ errored = true;
483
+ req.destroy(err);
484
+ });
485
+ data.on("close", ()=>{
486
+ if (!ended && !errored) {
487
+ abort(new CanceledError("Request stream has been aborted", config, req));
488
+ }
489
+ });
490
+ data.pipe(req); // stream 写入数据
491
+ } else req.end(data);
492
+ }
493
+ });
494
+ }
495
+ _.done(R);
496
+ } catch (e) {
497
+ log.error(e, "request");
498
+ _.done(e, true);
499
+ throw e;
500
+ }
501
+ return R;
502
+ }
503
+ };
504
+ /**
505
+ *
506
+ * @param {*} stream
507
+ * @param {*} param1
508
+ * @returns
509
+ */ const flushOnFinish = (stream, [throttled, flush])=>{
510
+ stream.on("end", flush).on("error", flush);
511
+ return throttled;
512
+ };
513
+ /** @typedef {import('../core/Axios').default} Axios */ /**
514
+ * If the proxy or config beforeRedirects functions are defined, call them with the options
515
+ * object.
516
+ *
517
+ * @param {Object<string, any>} options - The options object that was passed to the request.
518
+ * @param {*} responseDetails - The options object that was passed to the request.
519
+ *
520
+ */ function dispatchBeforeRedirect(options, responseDetails) {
521
+ log.debug("dispatchBeforeRedirect", {
522
+ opts: options.beforeRedirects
523
+ });
524
+ if (options.beforeRedirects.proxy) options.beforeRedirects.proxy(options);
525
+ if (options.beforeRedirects.config) options.beforeRedirects.config(options, responseDetails);
526
+ }
527
+ /**
528
+ *
529
+ * @param {{address: string, family: *}} param0
530
+ * @returns
531
+ */ function resolveFamily({ address, family }) {
532
+ if (!utils.isString(address)) {
533
+ throw TypeError("address must be a string");
534
+ }
535
+ return {
536
+ address,
537
+ family: family || (address.indexOf(".") < 0 ? 6 : 4)
538
+ };
539
+ }
540
+ /**
541
+ *
542
+ * @param {*} address
543
+ * @param {*} family
544
+ */ function buildAddressEntry(address, family) {
545
+ resolveFamily(utils.isObject(address) ? address : {
546
+ address,
547
+ family
548
+ });
549
+ }
550
+ /**
551
+ * null or funciton
552
+ */ export default isHttpAdapterSupported && HttpAdapter;