@wiajs/req 1.7.7 → 1.7.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/node/req.cjs CHANGED
@@ -1,21 +1,20 @@
1
1
  /*!
2
- * @wia/req v1.7.7
2
+ * @wia/req v1.7.10
3
3
  * (c) 2024 Sibyl Yu, Matt Zabriskie and contributors
4
4
  * Released under the MIT License.
5
5
  */
6
6
  'use strict';
7
7
 
8
8
  const FormData$1 = require('form-data');
9
- const url = require('url');
9
+ const url = require('node:url');
10
10
  const request = require('@wiajs/request');
11
11
  const Agent = require('@wiajs/agent');
12
12
  const log$1 = require('@wiajs/log');
13
- const util$1 = require('node:util');
13
+ const util = require('node:util');
14
14
  const zlib = require('node:zlib');
15
15
  const stream$1 = require('node:stream');
16
16
  const stream = require('stream');
17
17
  const node_events = require('node:events');
18
- const util = require('util');
19
18
 
20
19
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
21
20
  function bind(fn, thisArg) {
@@ -2596,15 +2595,14 @@ const asyncDecorator =
2596
2595
 
2597
2596
  // import Agent from '../fea/agent.js'
2598
2597
 
2599
- const log = log$1.log({ env: `wia:req:${log$1.name((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.src || new URL('req.cjs', document.baseURI).href)))}` });
2598
+ const log = log$1.log({env: `wia:req:${log$1.name((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.src || new URL('req.cjs', document.baseURI).href)))}`});
2600
2599
 
2601
2600
  const isBrotliSupported = utils$1.isFunction(zlib.createBrotliDecompress);
2602
2601
 
2603
2602
  const isHttps = /https:?/;
2604
2603
 
2605
- const supportedProtocols = platform.protocols.map((protocol) => `${protocol}:`);
2606
- const isHttpAdapterSupported =
2607
- typeof process !== "undefined" && utils$1.kindOf(process) === "process";
2604
+ const supportedProtocols = platform.protocols.map(protocol => `${protocol}:`);
2605
+ const isHttpAdapterSupported = typeof process !== 'undefined' && utils$1.kindOf(process) === 'process';
2608
2606
 
2609
2607
  /**
2610
2608
  * !+++
@@ -2612,739 +2610,650 @@ const isHttpAdapterSupported =
2612
2610
  * 如需重新发起请求时,无需重新初始化
2613
2611
  */
2614
2612
  class HttpAdapter {
2615
- isDone = false;
2616
- rejected = false;
2617
- /** @type {*} */
2618
- req = null;
2619
- /** @type {*} */
2620
- config = null;
2621
- /** @type {number} */
2622
- maxUploadRate;
2623
- /** @type {number} */
2624
- maxDownloadRate;
2625
- /** @type {*} */
2626
- data = null;
2627
- /** @type {*} */
2628
- transport = null;
2629
-
2630
- /**
2631
- *
2632
- * @param {*} config
2633
- */
2634
- constructor(config) {
2635
- this.config = config;
2636
- // temporary internal emitter until the AxiosRequest class will be implemented
2637
- this.emitter = new node_events.EventEmitter();
2638
- }
2639
-
2640
- /**
2641
- *
2642
- * @param {number} code
2643
- * @returns
2644
- */
2645
- noBody(code) {
2646
- return (
2647
- this.method === "HEAD" ||
2648
- // Informational
2649
- (code >= 100 && code < 200) ||
2650
- // No Content
2651
- code === 204 ||
2652
- // Not Modified
2653
- code === 304
2654
- );
2655
- }
2656
-
2657
- /**
2658
- * 发起终止事件
2659
- * @param {*} reason
2660
- */
2661
- abort(reason) {
2662
- this.emitter.emit(
2663
- "abort",
2664
- !reason || reason.type
2665
- ? new CanceledError(null, this.config, this.req)
2666
- : reason,
2667
- );
2668
- }
2669
-
2670
- onFinished() {
2671
- const { config, emitter, abort } = this;
2672
- config?.cancelToken?.unsubscribe(abort);
2673
-
2674
- config?.signal?.removeEventListener("abort", abort);
2675
-
2676
- emitter?.removeAllListeners();
2677
- }
2678
-
2679
- /**
2680
- *
2681
- * @param {*} value
2682
- * @param {*} isRejected
2683
- */
2684
- onDone(value, isRejected) {
2685
- this.isDone = true;
2686
- if (isRejected) {
2687
- this.rejected = true;
2688
- this.onFinished();
2689
- }
2690
- }
2691
-
2692
- /**
2693
- *
2694
- * @param {*} value
2695
- * @param {*} isRejected
2696
- * @returns
2697
- */
2698
- done(value, isRejected) {
2699
- if (this.isDone) return;
2700
- this.isDone = true;
2701
- this?.onDone(value, isRejected);
2702
- }
2703
-
2704
- /**
2705
- * 初始化,生成 options 供请求调用
2706
- * @returns {*} options
2707
- */
2708
- async init() {
2709
- // biome-ignore lint/complexity/noUselessThisAlias: <explanation>
2710
- const _ = this;
2711
- const { config } = _;
2712
-
2713
- let { data, lookup, family } = config;
2714
- const method = config.method.toUpperCase();
2715
- _.method = method;
2716
-
2717
- if (lookup) {
2718
- const _lookup = callbackify$1(
2719
- lookup,
2720
- /** @param {*} value */ (value) =>
2721
- utils$1.isArray(value) ? value : [value],
2722
- );
2723
- // hotfix to support opt.all option which is required for node 20.x
2724
- /**
2725
- * @param {string} hostname
2726
- * @param {*} opt
2727
- * @param {*} cb
2728
- */
2729
- lookup = (hostname, opt, cb) => {
2730
- _lookup(hostname, opt, (err, arg0, arg1) => {
2731
- if (err) return cb(err);
2732
-
2733
- const addresses = utils$1.isArray(arg0)
2734
- ? arg0.map((addr) => buildAddressEntry(addr))
2735
- : [buildAddressEntry(arg0, arg1)];
2736
-
2737
- opt.all
2738
- ? cb(err, addresses)
2739
- : cb(err, addresses[0].address, addresses[0].family);
2740
- });
2741
- };
2742
- }
2743
-
2744
- if (config.cancelToken || config.signal) {
2745
- config.cancelToken?.subscribe(_.abort);
2746
- if (config.signal) {
2747
- if (config.signal.aborted) _.abort();
2748
- else config.signal.addEventListener("abort", _.abort);
2749
- }
2750
- }
2751
-
2752
- // Parse url
2753
- const fullPath = buildFullPath(config.baseURL, config.url);
2754
- // 'https://user:pass@sub.host.com:8080/p/a/t/h?query=string#hash'
2755
- const parsed = new URL(
2756
- fullPath,
2757
- platform.hasBrowserEnv ? platform.origin : undefined,
2758
- );
2759
- // http: or https:
2760
- const protocol = parsed.protocol || supportedProtocols[0];
2761
- _.protocol = protocol;
2762
-
2763
- if (protocol === "data:" && method !== "GET") {
2764
- // throw error
2765
- const response = {
2766
- status: 405,
2767
- statusText: "method not allowed",
2768
- headers: {},
2769
- config,
2770
- };
2771
-
2772
- throw new AxiosError(
2773
- `Request failed with status code ${response.status}`,
2774
- [AxiosError.ERR_BAD_REQUEST, AxiosError.ERR_BAD_RESPONSE][
2775
- Math.floor(response.status / 100) - 4
2776
- ],
2777
- response.config,
2778
- response.request,
2779
- response,
2780
- );
2781
- }
2782
-
2783
- if (supportedProtocols.indexOf(protocol) === -1) {
2784
- throw new AxiosError(
2785
- `Unsupported protocol ${protocol}`,
2786
- AxiosError.ERR_BAD_REQUEST,
2787
- config,
2788
- );
2789
- }
2790
-
2791
- const headers = AxiosHeaders$1.from(config.headers).normalize();
2792
-
2793
- // Set User-Agent (required by some servers)
2794
- // See https://github.com/axios/axios/issues/69
2795
- // User-Agent is specified; handle case where no UA header is desired
2796
- // Only set header if it hasn't been set in config
2797
- // ! headers.set('User-Agent', 'axios/' + VERSION, false);
2798
- headers.set(
2799
- "User-Agent",
2800
- "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",
2801
- false,
2802
- );
2803
-
2804
- const { onDownloadProgress, onUploadProgress, maxRate } = config;
2805
-
2806
- // support for spec compliant FormData objects
2807
- if (utils$1.isSpecCompliantForm(data)) {
2808
- const userBoundary = headers.getContentType(
2809
- /boundary=([-_\w\d]{10,70})/i,
2810
- );
2811
-
2812
- data = formDataToStream$1(
2813
- data,
2814
- /** @param {*} formHeaders */ (formHeaders) => headers.set(formHeaders),
2815
- {
2816
- tag: `axios-${VERSION}-boundary`,
2817
- boundary: userBoundary?.[1] || undefined,
2818
- },
2819
- );
2820
- // support for https://www.npmjs.com/package/form-data api
2821
- } else if (utils$1.isFormData(data) && utils$1.isFunction(data.getHeaders)) {
2822
- headers.set(data.getHeaders());
2823
- if (!headers.hasContentLength()) {
2824
- try {
2825
- const knownLength = await util$1.promisify(data.getLength).call(data);
2826
- Number.isFinite(knownLength) &&
2827
- knownLength >= 0 &&
2828
- headers.setContentLength(knownLength);
2829
- /*eslint no-empty:0*/
2830
- } catch (e) {}
2831
- }
2832
- } else if (utils$1.isBlob(data)) {
2833
- data.size &&
2834
- headers.setContentType(data.type || "application/octet-stream");
2835
- headers.setContentLength(data.size || 0);
2836
- data = stream$1.Readable.from(readBlob$1(data));
2837
- } else if (data && !utils$1.isStream(data)) {
2838
- if (Buffer.isBuffer(data)) ; else if (utils$1.isArrayBuffer(data)) {
2839
- data = Buffer.from(new Uint8Array(data));
2840
- } else if (utils$1.isString(data)) {
2841
- data = Buffer.from(data, "utf-8");
2842
- } else {
2843
- throw new AxiosError(
2844
- "Data after transformation must be a string, an ArrayBuffer, a Buffer, or a Stream",
2845
- AxiosError.ERR_BAD_REQUEST,
2846
- config,
2847
- );
2848
- }
2849
-
2850
- // Add Content-Length header if data exists
2851
- headers.setContentLength(data.length, false);
2852
-
2853
- if (config.maxBodyLength > -1 && data.length > config.maxBodyLength) {
2854
- throw new AxiosError(
2855
- "Request body larger than maxBodyLength limit",
2856
- AxiosError.ERR_BAD_REQUEST,
2857
- config,
2858
- );
2859
- }
2860
- }
2861
-
2862
- const contentLength = utils$1.toFiniteNumber(headers.getContentLength());
2863
- let maxUploadRate;
2864
- let maxDownloadRate;
2865
- if (utils$1.isArray(maxRate)) [maxUploadRate, maxDownloadRate] = maxRate;
2866
- else {
2867
- maxUploadRate = maxRate;
2868
- maxDownloadRate = maxRate;
2869
- }
2870
-
2871
- _.maxUploadRate = maxUploadRate;
2872
- _.maxDownloadRate = maxDownloadRate;
2873
-
2874
- if (data && (onUploadProgress || maxUploadRate)) {
2875
- if (!utils$1.isStream(data)) {
2876
- data = stream$1.Readable.from(data, { objectMode: false });
2877
- }
2878
-
2879
- data = stream$1.pipeline(
2880
- [
2881
- data,
2882
- new AxiosTransformStream$1({
2883
- maxRate: utils$1.toFiniteNumber(maxUploadRate),
2884
- }),
2885
- ],
2886
- utils$1.noop,
2887
- );
2888
-
2889
- onUploadProgress &&
2890
- data.on(
2891
- "progress",
2892
- flushOnFinish(
2893
- data,
2894
- progressEventDecorator(
2895
- contentLength,
2896
- progressEventReducer(asyncDecorator(onUploadProgress), false, 3),
2897
- ),
2898
- ),
2899
- );
2900
- }
2901
-
2902
- // HTTP basic authentication
2903
- let auth;
2904
- if (config.auth) {
2905
- const username = config.auth.username || "";
2906
- const password = config.auth.password || "";
2907
- auth = `${username}:${password}`;
2908
- }
2909
-
2910
- if (!auth && parsed.username) {
2911
- const urlUsername = parsed.username;
2912
- const urlPassword = parsed.password;
2913
- auth = `${urlUsername}:${urlPassword}`;
2914
- }
2915
-
2916
- auth && headers.delete("authorization");
2917
-
2918
- let path;
2919
-
2920
- try {
2921
- path = buildURL(
2922
- parsed.pathname + parsed.search,
2923
- config.params,
2924
- config.paramsSerializer,
2925
- ).replace(/^\?/, "");
2926
- } catch (err) {
2927
- /** @type {*} */
2928
- const customErr = new Error(err.message);
2929
- customErr.config = config;
2930
- customErr.url = config.url;
2931
- customErr.exists = true;
2932
- throw customErr;
2933
- }
2934
-
2935
- headers.set(
2936
- "Accept-Encoding",
2937
- `gzip, compress, deflate${isBrotliSupported ? ", br" : ""}`,
2938
- false,
2939
- );
2940
-
2941
- /** @type {*} */
2942
- const options = {
2943
- path,
2944
- method,
2945
- headers: headers.toJSON(),
2946
- agents: { http: config.httpAgent, https: config.httpsAgent },
2947
- auth,
2948
- protocol,
2949
- family,
2950
- beforeRedirect: dispatchBeforeRedirect,
2951
- beforeRedirects: {},
2952
- };
2953
-
2954
- // cacheable-lookup integration hotfix
2955
- if (!utils$1.isUndefined(lookup)) options.lookup = lookup;
2956
-
2957
- if (config.socketPath) options.socketPath = config.socketPath;
2958
- else {
2959
- options.hostname = parsed.hostname.startsWith("[")
2960
- ? parsed.hostname.slice(1, -1)
2961
- : parsed.hostname;
2962
- options.port = parsed.port;
2963
- // ! proxy
2964
- if (config.agent) options.agents = new Agent(config.agent);
2965
- }
2966
-
2967
- // 执行请求的具体对象
2968
- _.transport = config.transport;
2969
-
2970
- const isHttpsRequest = isHttps.test(options.protocol);
2971
- options.agent = isHttpsRequest ? config.httpsAgent : config.httpAgent;
2972
-
2973
- if (config.maxBodyLength > -1) options.maxBodyLength = config.maxBodyLength;
2974
- // follow-redirects does not skip comparison, so it should always succeed for axios -1 unlimited
2975
- else options.maxBodyLength = Number.POSITIVE_INFINITY;
2976
-
2977
- // maxRedirects 缺省 21,不跳转,直接使用系统http or https,不支持 stream
2978
- // if (config.maxRedirects === 0 && !config.stream) transport = isHttpsRequest ? https : http;
2979
- // 自动跳转
2980
- // else {
2981
- // 支持跳转或stream,需使用 http、https 封装类
2982
- if (config.maxRedirects) options.maxRedirects = config.maxRedirects;
2983
- if (config.beforeRedirect)
2984
- options.beforeRedirects.config = config.beforeRedirect;
2985
-
2986
- if (config.insecureHTTPParser)
2987
- options.insecureHTTPParser = config.insecureHTTPParser;
2988
-
2989
- _.options = options;
2990
- _.data = data;
2991
-
2992
- log({ config }, "init");
2993
- return options;
2994
- }
2995
-
2996
- /**
2997
- * 执行请求
2998
- * 需抛出内部异常
2999
- * @param {Axios} axios 实例
3000
- * @returns {Promise<*>}
3001
- */
3002
- async request(axios) {
3003
- /** @type {*} */
3004
- // biome-ignore lint/style/useConst: <explanation>
3005
- let R;
3006
- // biome-ignore lint/complexity/noUselessThisAlias: <explanation>
3007
- const _ = this;
3008
-
3009
- try {
3010
- await _.init();
3011
-
3012
- const {
3013
- transport,
3014
- protocol,
3015
- config,
3016
- options,
3017
- data,
3018
- abort,
3019
- emitter,
3020
- maxDownloadRate,
3021
- } = _;
3022
- const { responseType, responseEncoding, onDownloadProgress } = config;
3023
-
3024
- if (protocol === "data:") {
3025
- /** @type {*} */
3026
- let convertedData;
3027
- try {
3028
- convertedData = fromDataURI(config.url, responseType === "blob", {
3029
- Blob: config.env?.Blob,
3030
- });
3031
- } catch (err) {
3032
- throw AxiosError.from(err, AxiosError.ERR_BAD_REQUEST, config);
3033
- }
3034
-
3035
- if (responseType === "text") {
3036
- convertedData = convertedData.toString(responseEncoding);
3037
-
3038
- if (!responseEncoding || responseEncoding === "utf8") {
3039
- convertedData = utils$1.stripBOM(convertedData);
3040
- }
3041
- } else if (responseType === "stream") {
3042
- convertedData = stream$1.Readable.from(convertedData);
3043
- }
3044
-
3045
- // 返回响应
3046
- R = {
3047
- data: convertedData,
3048
- status: 200,
3049
- statusText: "OK",
3050
- headers: new AxiosHeaders$1(),
3051
- config,
3052
- };
3053
- } else {
3054
- let transformStream;
3055
- if (onDownloadProgress || maxDownloadRate) {
3056
- transformStream = new AxiosTransformStream$1({
3057
- maxRate: utils$1.toFiniteNumber(maxDownloadRate),
3058
- });
3059
-
3060
- onDownloadProgress &&
3061
- transformStream.on(
3062
- "progress",
3063
- flushOnFinish(
3064
- transformStream,
3065
- progressEventDecorator(
3066
- transformStream.responseLength,
3067
- progressEventReducer(
3068
- asyncDecorator(onDownloadProgress),
3069
- true,
3070
- 3,
3071
- ),
3072
- ),
3073
- ),
3074
- );
3075
- }
3076
- options.transformStream = transformStream;
3077
-
3078
- // 发起异步请求
3079
- R = await new Promise((resolve, reject) => {
3080
- _.emitter.once("abort", reject);
3081
-
3082
- options.stream = config.stream;
3083
- options.decompress = config.decompress;
3084
- // Create the request,promise false: return stream
3085
- // log.debug('request', {options});
3086
- const req = transport ? transport.request(options) : request(options);
3087
-
3088
- if (!req)
3089
- return reject(
3090
- new AxiosError(
3091
- "Request failed.",
3092
- AxiosError.ERR_BAD_REQUEST,
3093
- config,
3094
- ),
3095
- );
3096
-
3097
- _.req = req;
3098
-
3099
- emitter.once("abort", (err) => {
3100
- log("onabort");
3101
- reject(err);
3102
- req.destroy(err);
3103
- });
3104
-
3105
- // Handle errors
3106
- req.on(
3107
- "error",
3108
- /** @param {*} err */ (err) => {
3109
- log("onerror");
3110
- // @todo remove
3111
- // if (req.aborted && err.code !== AxiosError.ERR_FR_TOO_MANY_REDIRECTS) return;
3112
- reject(AxiosError.from(err, null, config, req));
3113
- },
3114
- );
3115
-
3116
- // set tcp keep alive to prevent drop connection by peer
3117
- req.on(
3118
- "socket",
3119
- /** @param {*} socket */ (socket) => {
3120
- log("onsocket");
3121
- // default interval of sending ack packet is 1 minute
3122
- socket.setKeepAlive(true, 1000 * 60);
3123
- },
3124
- );
3125
-
3126
- // Handle request timeout
3127
- if (config.timeout) {
3128
- // This is forcing a int timeout to avoid problems if the `req` interface doesn't handle other types.
3129
- const timeout = Number.parseInt(config.timeout);
3130
-
3131
- if (Number.isNaN(timeout)) {
3132
- reject(
3133
- new AxiosError(
3134
- "error trying to parse `config.timeout` to int",
3135
- AxiosError.ERR_BAD_OPTION_VALUE,
3136
- config,
3137
- req,
3138
- ),
3139
- );
3140
- } else {
3141
- // Sometime, the response will be very slow, and does not respond, the connect event will be block by event loop system.
3142
- // And timer callback will be fired, and abort() will be invoked before connection, then get "socket hang up" and code ECONNRESET.
3143
- // 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.
3144
- // And then these socket which be hang up will devouring CPU little by little.
3145
- // ClientRequest.setTimeout will be fired on the specify milliseconds, and can make sure that abort() will be fired after connect.
3146
- req.setTimeout(timeout, () => {
3147
- if (_.isDone) return;
3148
-
3149
- let timeoutErrorMessage = config.timeout
3150
- ? `timeout of ${config.timeout}ms exceeded`
3151
- : "timeout exceeded";
3152
- const transitional =
3153
- config.transitional || transitionalDefaults;
3154
- if (config.timeoutErrorMessage) {
3155
- timeoutErrorMessage = config.timeoutErrorMessage;
3156
- }
3157
- reject(
3158
- new AxiosError(
3159
- timeoutErrorMessage,
3160
- transitional.clarifyTimeoutError
3161
- ? AxiosError.ETIMEDOUT
3162
- : AxiosError.ECONNABORTED,
3163
- config,
3164
- req,
3165
- ),
3166
- );
3167
- abort();
3168
- });
3169
- }
3170
- }
3171
-
3172
- // stream finished
3173
- req.on("finished", _.onFinished.bind(_));
3174
-
3175
- // ! stream 模式不等待响应数据,直接返回 req,建立pipe管道流
3176
- if (config.stream) resolve(req);
3177
- else {
3178
- // 非stream模式,等待响应数据,返回数据
3179
- req.on(
3180
- "response",
3181
- /**
3182
- * @param {*} res
3183
- * @param {*} stream
3184
- */
3185
- (res, stream) => {
3186
- if (req.destroyed) return;
3187
-
3188
- // 'transfer-encoding': 'chunked'时,无content-length,axios v1.2 不能自动解压
3189
- const responseLength = +res.headers["content-length"];
3190
-
3191
- log("onresponse", {
3192
- statusCode: res.statusCode,
3193
- responseLength,
3194
- headers: res.headers,
3195
- });
3196
-
3197
- // return the last request(ClientRequest) in case of redirects
3198
- const lastRequest = res.req || req;
3199
-
3200
- /** @type {*} */
3201
- const response = {
3202
- status: res.statusCode,
3203
- statusText: res.statusMessage,
3204
- headers: new AxiosHeaders$1(res.headers),
3205
- config,
3206
- request: lastRequest,
3207
- };
3208
-
3209
- // 直接返回 responseStream
3210
- if (responseType === "stream") {
3211
- response.data = stream;
3212
- settle(resolve, reject, response);
3213
- } else {
3214
- // 处理 responseStream
3215
- /** @type {*} */
3216
- const responseBuffer = [];
3217
- let totalResponseBytes = 0;
3218
-
3219
- // 处理数据
3220
- stream.on(
3221
- "data",
3222
- /** @param {*} chunk */ (chunk) => {
3223
- responseBuffer.push(chunk);
3224
- totalResponseBytes += chunk.length;
3225
-
3226
- // make sure the content length is not over the maxContentLength if specified
3227
- if (
3228
- config.maxContentLength > -1 &&
3229
- totalResponseBytes > config.maxContentLength
3230
- ) {
3231
- // stream.destroy() emit aborted event before calling reject() on Node.js v16
3232
- _.rejected = true;
3233
- stream.destroy();
3234
- reject(
3235
- new AxiosError(
3236
- `maxContentLength size of ${config.maxContentLength} exceeded`,
3237
- AxiosError.ERR_BAD_RESPONSE,
3238
- config,
3239
- lastRequest,
3240
- ),
3241
- );
3242
- }
3243
- },
3244
- );
3245
-
3246
- stream.on("aborted", function handlerStreamAborted() {
3247
- if (_.rejected) return;
3248
-
3249
- const err = new AxiosError(
3250
- `maxContentLength size of ${config.maxContentLength} exceeded`,
3251
- AxiosError.ERR_BAD_RESPONSE,
3252
- config,
3253
- lastRequest,
3254
- );
3255
- stream.destroy(err);
3256
- reject(err);
3257
- });
3258
-
3259
- stream.on("error", function handleStreamError(err) {
3260
- if (req.destroyed) return;
3261
- reject(AxiosError.from(err, null, config, lastRequest));
3262
- });
3263
-
3264
- // 数据传输结束
3265
- stream.on("end", function handleStreamEnd() {
3266
- try {
3267
- let responseData =
3268
- responseBuffer.length === 1
3269
- ? responseBuffer[0]
3270
- : Buffer.concat(responseBuffer);
3271
- if (responseType !== "arraybuffer") {
3272
- responseData = responseData.toString(responseEncoding);
3273
- if (!responseEncoding || responseEncoding === "utf8") {
3274
- responseData = utils$1.stripBOM(responseData);
3275
- }
3276
- }
3277
- response.data = responseData;
3278
- settle(resolve, reject, response);
3279
- } catch (err) {
3280
- reject(
3281
- AxiosError.from(
3282
- err,
3283
- null,
3284
- config,
3285
- response.request,
3286
- response,
3287
- ),
3288
- );
3289
- }
3290
- });
3291
- }
3292
-
3293
- emitter.once("abort", (err) => {
3294
- if (!stream.destroyed) {
3295
- stream.emit("error", err);
3296
- stream.destroy();
3297
- }
3298
- });
3299
- },
3300
- );
3301
-
3302
- // 发送数据
3303
- if (utils$1.isStream(data)) {
3304
- // Send the request
3305
- let ended = false;
3306
- let errored = false;
3307
-
3308
- data.on("end", () => {
3309
- ended = true;
3310
- });
3311
-
3312
- data.once(
3313
- "error",
3314
- /** @param {*} err */ (err) => {
3315
- errored = true;
3316
- req.destroy(err);
3317
- },
3318
- );
3319
-
3320
- data.on("close", () => {
3321
- if (!ended && !errored) {
3322
- abort(
3323
- new CanceledError(
3324
- "Request stream has been aborted",
3325
- config,
3326
- req,
3327
- ),
3328
- );
3329
- }
3330
- });
3331
-
3332
- data.pipe(req); // stream 写入数据
3333
- } else req.end(data);
3334
- }
3335
- });
3336
- }
3337
-
3338
- _.done(R);
3339
- } catch (e) {
3340
- log.error(e, "request");
3341
- _.done(e, true);
3342
- throw e;
3343
- }
3344
- return R;
3345
- }
2613
+ isDone = false;
2614
+ rejected = false;
2615
+ /** @type {*} */
2616
+ req = null;
2617
+ /** @type {*} */
2618
+ config = null;
2619
+ /** @type {number} */
2620
+ maxUploadRate;
2621
+ /** @type {number} */
2622
+ maxDownloadRate;
2623
+ /** @type {*} */
2624
+ data = null;
2625
+ /** @type {*} */
2626
+ transport = null;
2627
+
2628
+ /**
2629
+ *
2630
+ * @param {*} config
2631
+ */
2632
+ constructor(config) {
2633
+ this.config = config;
2634
+ // temporary internal emitter until the AxiosRequest class will be implemented
2635
+ this.emitter = new node_events.EventEmitter();
2636
+ }
2637
+
2638
+ /**
2639
+ *
2640
+ * @param {number} code
2641
+ * @returns
2642
+ */
2643
+ noBody(code) {
2644
+ return (
2645
+ this.method === 'HEAD' ||
2646
+ // Informational
2647
+ (code >= 100 && code < 200) ||
2648
+ // No Content
2649
+ code === 204 ||
2650
+ // Not Modified
2651
+ code === 304
2652
+ );
2653
+ }
2654
+
2655
+ /**
2656
+ * 发起终止事件
2657
+ * @param {*} reason
2658
+ */
2659
+ abort(reason) {
2660
+ this.emitter.emit('abort', !reason || reason.type ? new CanceledError(null, this.config, this.req) : reason);
2661
+ }
2662
+
2663
+ onFinished() {
2664
+ const {config, emitter, abort} = this;
2665
+ config?.cancelToken?.unsubscribe(abort);
2666
+
2667
+ config?.signal?.removeEventListener('abort', abort);
2668
+
2669
+ emitter?.removeAllListeners();
2670
+ }
2671
+
2672
+ /**
2673
+ *
2674
+ * @param {*} value
2675
+ * @param {*} isRejected
2676
+ */
2677
+ onDone(value, isRejected) {
2678
+ this.isDone = true;
2679
+ if (isRejected) {
2680
+ this.rejected = true;
2681
+ this.onFinished();
2682
+ }
2683
+ }
2684
+
2685
+ /**
2686
+ *
2687
+ * @param {*} value
2688
+ * @param {*} isRejected
2689
+ * @returns
2690
+ */
2691
+ done(value, isRejected) {
2692
+ if (this.isDone) return;
2693
+ this.isDone = true;
2694
+ this?.onDone(value, isRejected);
2695
+ }
2696
+
2697
+ /**
2698
+ * 初始化,生成 options 供请求调用
2699
+ * @returns {*} options
2700
+ */
2701
+ async init() {
2702
+ // biome-ignore lint/complexity/noUselessThisAlias: <explanation>
2703
+ const _ = this;
2704
+ const {config} = _;
2705
+
2706
+ let {data, lookup, family} = config;
2707
+ const method = config.method.toUpperCase();
2708
+ _.method = method;
2709
+
2710
+ if (lookup) {
2711
+ const _lookup = callbackify$1(lookup, /** @param {*} value */ value => (utils$1.isArray(value) ? value : [value]));
2712
+ // hotfix to support opt.all option which is required for node 20.x
2713
+ /**
2714
+ * @param {string} hostname
2715
+ * @param {*} opt
2716
+ * @param {*} cb
2717
+ */
2718
+ lookup = (hostname, opt, cb) => {
2719
+ _lookup(hostname, opt, (err, arg0, arg1) => {
2720
+ if (err) return cb(err);
2721
+
2722
+ const addresses = utils$1.isArray(arg0)
2723
+ ? arg0.map(addr => buildAddressEntry(addr))
2724
+ : [buildAddressEntry(arg0, arg1)];
2725
+
2726
+ opt.all ? cb(err, addresses) : cb(err, addresses[0].address, addresses[0].family);
2727
+ });
2728
+ };
2729
+ }
2730
+
2731
+ if (config.cancelToken || config.signal) {
2732
+ config.cancelToken?.subscribe(_.abort);
2733
+ if (config.signal) {
2734
+ if (config.signal.aborted) _.abort();
2735
+ else config.signal.addEventListener('abort', _.abort);
2736
+ }
2737
+ }
2738
+
2739
+ // Parse url
2740
+ const fullPath = buildFullPath(config.baseURL, config.url);
2741
+ // 'https://user:pass@sub.host.com:8080/p/a/t/h?query=string#hash'
2742
+ const parsed = new URL(fullPath, platform.hasBrowserEnv ? platform.origin : undefined);
2743
+ // http: or https:
2744
+ const protocol = parsed.protocol || supportedProtocols[0];
2745
+ _.protocol = protocol;
2746
+
2747
+ if (protocol === 'data:' && method !== 'GET') {
2748
+ // throw error
2749
+ const response = {
2750
+ status: 405,
2751
+ statusText: 'method not allowed',
2752
+ headers: {},
2753
+ config,
2754
+ };
2755
+
2756
+ throw new AxiosError(
2757
+ `Request failed with status code ${response.status}`,
2758
+ [AxiosError.ERR_BAD_REQUEST, AxiosError.ERR_BAD_RESPONSE][Math.floor(response.status / 100) - 4],
2759
+ response.config,
2760
+ response.request,
2761
+ response
2762
+ );
2763
+ }
2764
+
2765
+ if (supportedProtocols.indexOf(protocol) === -1) {
2766
+ throw new AxiosError(`Unsupported protocol ${protocol}`, AxiosError.ERR_BAD_REQUEST, config);
2767
+ }
2768
+
2769
+ const headers = AxiosHeaders$1.from(config.headers).normalize();
2770
+
2771
+ // Set User-Agent (required by some servers)
2772
+ // See https://github.com/axios/axios/issues/69
2773
+ // User-Agent is specified; handle case where no UA header is desired
2774
+ // Only set header if it hasn't been set in config
2775
+ // ! headers.set('User-Agent', 'axios/' + VERSION, false);
2776
+ headers.set(
2777
+ 'User-Agent',
2778
+ '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',
2779
+ false
2780
+ );
2781
+
2782
+ const {onDownloadProgress, onUploadProgress, maxRate} = config;
2783
+
2784
+ // support for spec compliant FormData objects
2785
+ if (utils$1.isSpecCompliantForm(data)) {
2786
+ const userBoundary = headers.getContentType(/boundary=([-_\w\d]{10,70})/i);
2787
+
2788
+ data = formDataToStream$1(data, /** @param {*} formHeaders */ formHeaders => headers.set(formHeaders), {
2789
+ tag: `axios-${VERSION}-boundary`,
2790
+ boundary: userBoundary?.[1] || undefined,
2791
+ });
2792
+ // support for https://www.npmjs.com/package/form-data api
2793
+ } else if (utils$1.isFormData(data) && utils$1.isFunction(data.getHeaders)) {
2794
+ headers.set(data.getHeaders());
2795
+ if (!headers.hasContentLength()) {
2796
+ try {
2797
+ const knownLength = await util.promisify(data.getLength).call(data);
2798
+ Number.isFinite(knownLength) && knownLength >= 0 && headers.setContentLength(knownLength);
2799
+ /*eslint no-empty:0*/
2800
+ } catch (e) {}
2801
+ }
2802
+ } else if (utils$1.isBlob(data)) {
2803
+ data.size && headers.setContentType(data.type || 'application/octet-stream');
2804
+ headers.setContentLength(data.size || 0);
2805
+ data = stream$1.Readable.from(readBlob$1(data));
2806
+ } else if (data && !utils$1.isStream(data)) {
2807
+ if (Buffer.isBuffer(data)) ; else if (utils$1.isArrayBuffer(data)) {
2808
+ data = Buffer.from(new Uint8Array(data));
2809
+ } else if (utils$1.isString(data)) {
2810
+ data = Buffer.from(data, 'utf-8');
2811
+ } else {
2812
+ throw new AxiosError(
2813
+ 'Data after transformation must be a string, an ArrayBuffer, a Buffer, or a Stream',
2814
+ AxiosError.ERR_BAD_REQUEST,
2815
+ config
2816
+ );
2817
+ }
2818
+
2819
+ // Add Content-Length header if data exists
2820
+ headers.setContentLength(data.length, false);
2821
+
2822
+ if (config.maxBodyLength > -1 && data.length > config.maxBodyLength) {
2823
+ throw new AxiosError('Request body larger than maxBodyLength limit', AxiosError.ERR_BAD_REQUEST, config);
2824
+ }
2825
+ }
2826
+
2827
+ const contentLength = utils$1.toFiniteNumber(headers.getContentLength());
2828
+ let maxUploadRate;
2829
+ let maxDownloadRate;
2830
+ if (utils$1.isArray(maxRate)) [maxUploadRate, maxDownloadRate] = maxRate;
2831
+ else {
2832
+ maxUploadRate = maxRate;
2833
+ maxDownloadRate = maxRate;
2834
+ }
2835
+
2836
+ _.maxUploadRate = maxUploadRate;
2837
+ _.maxDownloadRate = maxDownloadRate;
2838
+
2839
+ if (data && (onUploadProgress || maxUploadRate)) {
2840
+ if (!utils$1.isStream(data)) {
2841
+ data = stream$1.Readable.from(data, {objectMode: false});
2842
+ }
2843
+
2844
+ data = stream$1.pipeline(
2845
+ [
2846
+ data,
2847
+ new AxiosTransformStream$1({
2848
+ maxRate: utils$1.toFiniteNumber(maxUploadRate),
2849
+ }),
2850
+ ],
2851
+ utils$1.noop
2852
+ );
2853
+
2854
+ onUploadProgress &&
2855
+ data.on(
2856
+ 'progress',
2857
+ flushOnFinish(
2858
+ data,
2859
+ progressEventDecorator(contentLength, progressEventReducer(asyncDecorator(onUploadProgress), false, 3))
2860
+ )
2861
+ );
2862
+ }
2863
+
2864
+ // HTTP basic authentication
2865
+ let auth;
2866
+ if (config.auth) {
2867
+ const username = config.auth.username || '';
2868
+ const password = config.auth.password || '';
2869
+ auth = `${username}:${password}`;
2870
+ }
2871
+
2872
+ if (!auth && parsed.username) {
2873
+ const urlUsername = parsed.username;
2874
+ const urlPassword = parsed.password;
2875
+ auth = `${urlUsername}:${urlPassword}`;
2876
+ }
2877
+
2878
+ auth && headers.delete('authorization');
2879
+
2880
+ let path;
2881
+
2882
+ try {
2883
+ path = buildURL(parsed.pathname + parsed.search, config.params, config.paramsSerializer).replace(/^\?/, '');
2884
+ } catch (err) {
2885
+ /** @type {*} */
2886
+ const customErr = new Error(err.message);
2887
+ customErr.config = config;
2888
+ customErr.url = config.url;
2889
+ customErr.exists = true;
2890
+ throw customErr;
2891
+ }
2892
+
2893
+ headers.set('Accept-Encoding', `gzip, compress, deflate${isBrotliSupported ? ', br' : ''}`, false);
2894
+
2895
+ /** @type {*} */
2896
+ const options = {
2897
+ path,
2898
+ method,
2899
+ headers: headers.toJSON(),
2900
+ agents: {http: config.httpAgent, https: config.httpsAgent},
2901
+ auth,
2902
+ protocol,
2903
+ family,
2904
+ beforeRedirect: dispatchBeforeRedirect,
2905
+ beforeRedirects: {},
2906
+ };
2907
+
2908
+ // cacheable-lookup integration hotfix
2909
+ if (!utils$1.isUndefined(lookup)) options.lookup = lookup;
2910
+
2911
+ if (config.socketPath) options.socketPath = config.socketPath;
2912
+ else {
2913
+ options.hostname = parsed.hostname.startsWith('[') ? parsed.hostname.slice(1, -1) : parsed.hostname;
2914
+ options.port = parsed.port;
2915
+ // ! proxy 配置了 agent,否则使用缺省 agent
2916
+ if (config.agent) options.agents = new Agent(config.agent);
2917
+ }
2918
+
2919
+ // 执行请求的具体对象
2920
+ _.transport = config.transport;
2921
+
2922
+ const isHttpsRequest = isHttps.test(options.protocol);
2923
+ options.agent = isHttpsRequest ? config.httpsAgent : config.httpAgent;
2924
+
2925
+ if (config.maxBodyLength > -1) options.maxBodyLength = config.maxBodyLength;
2926
+ // follow-redirects does not skip comparison, so it should always succeed for axios -1 unlimited
2927
+ else options.maxBodyLength = Number.POSITIVE_INFINITY;
2928
+
2929
+ // maxRedirects 缺省 21,不跳转,直接使用系统http or https,不支持 stream
2930
+ // if (config.maxRedirects === 0 && !config.stream) transport = isHttpsRequest ? https : http;
2931
+ // 自动跳转
2932
+ // else {
2933
+ // 支持跳转或stream,需使用 http、https 封装类
2934
+ if (config.maxRedirects) options.maxRedirects = config.maxRedirects;
2935
+ if (config.beforeRedirect) options.beforeRedirects.config = config.beforeRedirect;
2936
+
2937
+ if (config.insecureHTTPParser) options.insecureHTTPParser = config.insecureHTTPParser;
2938
+
2939
+ _.options = options;
2940
+ _.data = data;
2941
+
2942
+ log({config}, 'init');
2943
+ return options;
2944
+ }
2945
+
2946
+ /**
2947
+ * 执行请求
2948
+ * 需抛出内部异常
2949
+ * @param {Axios} axios 实例
2950
+ * @returns {Promise<*>}
2951
+ */
2952
+ async request(axios) {
2953
+ /** @type {*} */
2954
+ // biome-ignore lint/style/useConst: <explanation>
2955
+ let R;
2956
+ // biome-ignore lint/complexity/noUselessThisAlias: <explanation>
2957
+ const _ = this;
2958
+
2959
+ try {
2960
+ await _.init();
2961
+
2962
+ const {transport, protocol, config, options, data, abort, emitter, maxDownloadRate} = _;
2963
+ const {responseType, responseEncoding, onDownloadProgress} = config;
2964
+
2965
+ if (protocol === 'data:') {
2966
+ /** @type {*} */
2967
+ let convertedData;
2968
+ try {
2969
+ convertedData = fromDataURI(config.url, responseType === 'blob', {
2970
+ Blob: config.env?.Blob,
2971
+ });
2972
+ } catch (err) {
2973
+ throw AxiosError.from(err, AxiosError.ERR_BAD_REQUEST, config);
2974
+ }
2975
+
2976
+ if (responseType === 'text') {
2977
+ convertedData = convertedData.toString(responseEncoding);
2978
+
2979
+ if (!responseEncoding || responseEncoding === 'utf8') {
2980
+ convertedData = utils$1.stripBOM(convertedData);
2981
+ }
2982
+ } else if (responseType === 'stream') {
2983
+ convertedData = stream$1.Readable.from(convertedData);
2984
+ }
2985
+
2986
+ // 返回响应
2987
+ R = {
2988
+ data: convertedData,
2989
+ status: 200,
2990
+ statusText: 'OK',
2991
+ headers: new AxiosHeaders$1(),
2992
+ config,
2993
+ };
2994
+ } else {
2995
+ let transformStream;
2996
+ if (onDownloadProgress || maxDownloadRate) {
2997
+ transformStream = new AxiosTransformStream$1({
2998
+ maxRate: utils$1.toFiniteNumber(maxDownloadRate),
2999
+ });
3000
+
3001
+ onDownloadProgress &&
3002
+ transformStream.on(
3003
+ 'progress',
3004
+ flushOnFinish(
3005
+ transformStream,
3006
+ progressEventDecorator(
3007
+ transformStream.responseLength,
3008
+ progressEventReducer(asyncDecorator(onDownloadProgress), true, 3)
3009
+ )
3010
+ )
3011
+ );
3012
+ }
3013
+ options.transformStream = transformStream;
3014
+
3015
+ // 发起异步请求
3016
+ R = await new Promise((resolve, reject) => {
3017
+ _.emitter.once('abort', reject);
3018
+
3019
+ options.stream = config.stream;
3020
+ options.decompress = config.decompress;
3021
+ // Create the request,promise false: return stream
3022
+ // log.debug('request', {options});
3023
+ const req = transport ? transport.request(options) : request(options);
3024
+
3025
+ if (!req) return reject(new AxiosError('Request failed.', AxiosError.ERR_BAD_REQUEST, config));
3026
+
3027
+ _.req = req;
3028
+
3029
+ emitter.once('abort', err => {
3030
+ log('onabort');
3031
+ reject(err);
3032
+ req.destroy(err);
3033
+ });
3034
+
3035
+ // Handle errors
3036
+ req.on(
3037
+ 'error',
3038
+ /** @param {*} err */ err => {
3039
+ log('onerror');
3040
+ // @todo remove
3041
+ // if (req.aborted && err.code !== AxiosError.ERR_FR_TOO_MANY_REDIRECTS) return;
3042
+ reject(AxiosError.from(err, null, config, req));
3043
+ }
3044
+ );
3045
+
3046
+ // set tcp keep alive to prevent drop connection by peer
3047
+ req.on(
3048
+ 'socket',
3049
+ /** @param {*} socket */ socket => {
3050
+ log('onsocket');
3051
+ // default interval of sending ack packet is 1 minute
3052
+ socket.setKeepAlive(true, 1000 * 60);
3053
+ }
3054
+ );
3055
+
3056
+ // Handle request timeout
3057
+ if (config.timeout) {
3058
+ // This is forcing a int timeout to avoid problems if the `req` interface doesn't handle other types.
3059
+ const timeout = Number.parseInt(config.timeout);
3060
+
3061
+ if (Number.isNaN(timeout)) {
3062
+ reject(
3063
+ new AxiosError(
3064
+ 'error trying to parse `config.timeout` to int',
3065
+ AxiosError.ERR_BAD_OPTION_VALUE,
3066
+ config,
3067
+ req
3068
+ )
3069
+ );
3070
+ } else {
3071
+ // Sometime, the response will be very slow, and does not respond, the connect event will be block by event loop system.
3072
+ // And timer callback will be fired, and abort() will be invoked before connection, then get "socket hang up" and code ECONNRESET.
3073
+ // 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.
3074
+ // And then these socket which be hang up will devouring CPU little by little.
3075
+ // ClientRequest.setTimeout will be fired on the specify milliseconds, and can make sure that abort() will be fired after connect.
3076
+ req.setTimeout(timeout, () => {
3077
+ if (_.isDone) return;
3078
+
3079
+ let timeoutErrorMessage = config.timeout
3080
+ ? `timeout of ${config.timeout}ms exceeded`
3081
+ : 'timeout exceeded';
3082
+ const transitional = config.transitional || transitionalDefaults;
3083
+ if (config.timeoutErrorMessage) {
3084
+ timeoutErrorMessage = config.timeoutErrorMessage;
3085
+ }
3086
+ reject(
3087
+ new AxiosError(
3088
+ timeoutErrorMessage,
3089
+ transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED,
3090
+ config,
3091
+ req
3092
+ )
3093
+ );
3094
+ abort();
3095
+ });
3096
+ }
3097
+ }
3098
+
3099
+ // stream finished
3100
+ req.on('finished', _.onFinished.bind(_));
3101
+
3102
+ // ! stream 模式不等待响应数据,直接返回 req,建立pipe管道流
3103
+ if (config.stream) resolve(req);
3104
+ else {
3105
+ // 非stream模式,等待响应数据,返回数据
3106
+ req.on(
3107
+ 'response',
3108
+ /**
3109
+ * @param {*} res
3110
+ * @param {*} stream
3111
+ */
3112
+ (res, stream) => {
3113
+ if (req.destroyed) return;
3114
+
3115
+ // 'transfer-encoding': 'chunked'时,无content-length,axios v1.2 不能自动解压
3116
+ const responseLength = +res.headers['content-length'];
3117
+
3118
+ log('onresponse', {
3119
+ statusCode: res.statusCode,
3120
+ responseLength,
3121
+ headers: res.headers,
3122
+ });
3123
+
3124
+ // return the last request(ClientRequest) in case of redirects
3125
+ const lastRequest = res.req || req;
3126
+
3127
+ /** @type {*} */
3128
+ const response = {
3129
+ status: res.statusCode,
3130
+ statusText: res.statusMessage,
3131
+ headers: new AxiosHeaders$1(res.headers),
3132
+ config,
3133
+ request: lastRequest,
3134
+ };
3135
+
3136
+ // 直接返回 responseStream
3137
+ if (responseType === 'stream') {
3138
+ response.data = stream;
3139
+ settle(resolve, reject, response);
3140
+ } else {
3141
+ // 处理 responseStream
3142
+ /** @type {*} */
3143
+ const responseBuffer = [];
3144
+ let totalResponseBytes = 0;
3145
+
3146
+ // 处理数据
3147
+ stream.on(
3148
+ 'data',
3149
+ /** @param {*} chunk */ chunk => {
3150
+ responseBuffer.push(chunk);
3151
+ totalResponseBytes += chunk.length;
3152
+
3153
+ // make sure the content length is not over the maxContentLength if specified
3154
+ if (config.maxContentLength > -1 && totalResponseBytes > config.maxContentLength) {
3155
+ // stream.destroy() emit aborted event before calling reject() on Node.js v16
3156
+ _.rejected = true;
3157
+ stream.destroy();
3158
+ reject(
3159
+ new AxiosError(
3160
+ `maxContentLength size of ${config.maxContentLength} exceeded`,
3161
+ AxiosError.ERR_BAD_RESPONSE,
3162
+ config,
3163
+ lastRequest
3164
+ )
3165
+ );
3166
+ }
3167
+ }
3168
+ );
3169
+
3170
+ stream.on('aborted', function handlerStreamAborted() {
3171
+ if (_.rejected) return;
3172
+
3173
+ const err = new AxiosError(
3174
+ `maxContentLength size of ${config.maxContentLength} exceeded`,
3175
+ AxiosError.ERR_BAD_RESPONSE,
3176
+ config,
3177
+ lastRequest
3178
+ );
3179
+ stream.destroy(err);
3180
+ reject(err);
3181
+ });
3182
+
3183
+ stream.on('error', function handleStreamError(err) {
3184
+ if (req.destroyed) return;
3185
+ reject(AxiosError.from(err, null, config, lastRequest));
3186
+ });
3187
+
3188
+ // 数据传输结束
3189
+ stream.on('end', function handleStreamEnd() {
3190
+ try {
3191
+ let responseData =
3192
+ responseBuffer.length === 1 ? responseBuffer[0] : Buffer.concat(responseBuffer);
3193
+ if (responseType !== 'arraybuffer') {
3194
+ responseData = responseData.toString(responseEncoding);
3195
+ if (!responseEncoding || responseEncoding === 'utf8') {
3196
+ responseData = utils$1.stripBOM(responseData);
3197
+ }
3198
+ }
3199
+ response.data = responseData;
3200
+ settle(resolve, reject, response);
3201
+ } catch (err) {
3202
+ reject(AxiosError.from(err, null, config, response.request, response));
3203
+ }
3204
+ });
3205
+ }
3206
+
3207
+ emitter.once('abort', err => {
3208
+ if (!stream.destroyed) {
3209
+ stream.emit('error', err);
3210
+ stream.destroy();
3211
+ }
3212
+ });
3213
+ }
3214
+ );
3215
+
3216
+ // 发送数据
3217
+ if (utils$1.isStream(data)) {
3218
+ // Send the request
3219
+ let ended = false;
3220
+ let errored = false;
3221
+
3222
+ data.on('end', () => {
3223
+ ended = true;
3224
+ });
3225
+
3226
+ data.once(
3227
+ 'error',
3228
+ /** @param {*} err */ err => {
3229
+ errored = true;
3230
+ req.destroy(err);
3231
+ }
3232
+ );
3233
+
3234
+ data.on('close', () => {
3235
+ if (!ended && !errored) {
3236
+ abort(new CanceledError('Request stream has been aborted', config, req));
3237
+ }
3238
+ });
3239
+
3240
+ data.pipe(req); // stream 写入数据
3241
+ } else req.end(data);
3242
+ }
3243
+ });
3244
+ }
3245
+
3246
+ _.done(R);
3247
+ } catch (e) {
3248
+ log.error(e, 'request');
3249
+ _.done(e, true);
3250
+ throw e;
3251
+ }
3252
+ return R;
3253
+ }
3346
3254
  }
3347
3255
 
3256
+
3348
3257
  /**
3349
3258
  *
3350
3259
  * @param {*} stream
@@ -3352,9 +3261,9 @@ class HttpAdapter {
3352
3261
  * @returns
3353
3262
  */
3354
3263
  const flushOnFinish = (stream, [throttled, flush]) => {
3355
- stream.on("end", flush).on("error", flush);
3264
+ stream.on('end', flush).on('error', flush);
3356
3265
 
3357
- return throttled;
3266
+ return throttled;
3358
3267
  };
3359
3268
 
3360
3269
  /** @typedef {import('../core/Axios').default} Axios */
@@ -3368,11 +3277,10 @@ const flushOnFinish = (stream, [throttled, flush]) => {
3368
3277
  *
3369
3278
  */
3370
3279
  function dispatchBeforeRedirect(options, responseDetails) {
3371
- log.debug("dispatchBeforeRedirect", { opts: options.beforeRedirects });
3280
+ log.debug('dispatchBeforeRedirect', {opts: options.beforeRedirects});
3372
3281
 
3373
- if (options.beforeRedirects.proxy) options.beforeRedirects.proxy(options);
3374
- if (options.beforeRedirects.config)
3375
- options.beforeRedirects.config(options, responseDetails);
3282
+ if (options.beforeRedirects.proxy) options.beforeRedirects.proxy(options);
3283
+ if (options.beforeRedirects.config) options.beforeRedirects.config(options, responseDetails);
3376
3284
  }
3377
3285
 
3378
3286
  /**
@@ -3380,15 +3288,15 @@ function dispatchBeforeRedirect(options, responseDetails) {
3380
3288
  * @param {{address: string, family: *}} param0
3381
3289
  * @returns
3382
3290
  */
3383
- function resolveFamily({ address, family }) {
3384
- if (!utils$1.isString(address)) {
3385
- throw TypeError("address must be a string");
3386
- }
3387
-
3388
- return {
3389
- address,
3390
- family: family || (address.indexOf(".") < 0 ? 6 : 4),
3391
- };
3291
+ function resolveFamily({address, family}) {
3292
+ if (!utils$1.isString(address)) {
3293
+ throw TypeError('address must be a string');
3294
+ }
3295
+
3296
+ return {
3297
+ address,
3298
+ family: family || (address.indexOf('.') < 0 ? 6 : 4),
3299
+ };
3392
3300
  }
3393
3301
 
3394
3302
  /**
@@ -3397,7 +3305,7 @@ function resolveFamily({ address, family }) {
3397
3305
  * @param {*} family
3398
3306
  */
3399
3307
  function buildAddressEntry(address, family) {
3400
- resolveFamily(utils$1.isObject(address) ? address : { address, family });
3308
+ resolveFamily(utils$1.isObject(address) ? address : {address, family});
3401
3309
  }
3402
3310
 
3403
3311
  /**