hyperttp 0.1.9 → 0.2.1

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.
@@ -1,69 +1,55 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  const tough_cookie_1 = require("tough-cookie");
4
37
  const undici_1 = require("undici");
5
38
  const undici_2 = require("http-cookie-agent/undici");
39
+ const zlib = __importStar(require("zlib"));
40
+ const util_1 = require("util");
6
41
  const fast_xml_parser_1 = require("fast-xml-parser");
7
- const url_1 = require("url");
8
- const crypto_1 = require("crypto");
9
42
  const CacheManager_1 = require("./CacheManager");
10
43
  const QueueManager_1 = require("./QueueManager");
11
44
  const RateLimiter_1 = require("./RateLimiter");
12
45
  const Types_1 = require("../../Types");
13
- let defaultClient = null;
46
+ const RequestBuilder_1 = require("./RequestBuilder");
47
+ const gunzip = (0, util_1.promisify)(zlib.gunzip);
48
+ const inflate = (0, util_1.promisify)(zlib.inflate);
49
+ const brotliDecompress = (0, util_1.promisify)(zlib.brotliDecompress);
14
50
  /**
15
- * @ru
16
- * Улучшенный HTTP-клиент с кэшированием, ограничением скорости, логикой повторных попыток и расширенными функциями.
17
- * Предоставляет надежный интерфейс для выполнения HTTP-запросов с автоматической обработкой
18
- * распространенных паттернов, таких как повторные попытки, кэширование и перехват запросов/ответов.
19
- * @en
20
- * Enhanced HTTP client with caching, rate limiting, retry logic, and advanced features.
21
- * Provides a robust interface for making HTTP requests with automatic handling of
22
- * common patterns like retries, caching, and request/response interception.
23
- *
24
- * @example
25
- * ```ts
26
- * const client = new HttpClientImproved({
27
- * timeout: 10000,
28
- * maxRetries: 3,
29
- * cacheTTL: 300000,
30
- * rateLimit: { maxRequests: 100, windowMs: 60000 }
31
- * });
32
- *
33
- * const response = await client.get('https://api.example.com/data');
34
- * ```
35
- *
36
- * @example
37
- * ```ts
38
- * // Using the fluent request builder
39
- * const client = new HttpClientImproved();
40
- * const response = await client.request('https://api.example.com/data')
41
- * .headers({ 'Authorization': 'Bearer token' })
42
- * .json()
43
- * .send();
44
- * ```
45
- *
46
- * @example
47
- * ```ts
48
- * // Using RequestInterface for complex requests
49
- * import { RequestInterface } from './src';
50
- *
51
- * class ApiRequest implements RequestInterface {
52
- * constructor(
53
- * private url: string,
54
- * private headers: Record<string, string> = {},
55
- * private body?: any
56
- * ) {}
57
- *
58
- * getURL(): string { return this.url; }
59
- * getHeaders(): Record<string, string> { return this.headers; }
60
- * getBodyData(): any { return this.body; }
61
- * }
62
- *
63
- * const client = new HttpClientImproved();
64
- * const request = new ApiRequest('https://api.example.com/data');
65
- * const response = await client.get(request);
66
- * ```
51
+ * Advanced HTTP client with built-in caching, rate limiting, request queuing,
52
+ * automatic retries, cookie management, and response decompression.
67
53
  */
68
54
  class HttpClientImproved {
69
55
  cookieJar = new tough_cookie_1.CookieJar();
@@ -73,14 +59,15 @@ class HttpClientImproved {
73
59
  limiter;
74
60
  inflight = new Map();
75
61
  retryOptions;
76
- baseHeaders = Object.freeze({
77
- Accept: "application/json, text/plain, */*",
78
- "User-Agent": "Hyperttp/0.1.0 Node.js",
79
- });
62
+ defaultHeaders = {};
80
63
  options;
81
64
  requestInterceptors = [];
82
65
  responseInterceptors = [];
83
66
  requestMetrics = new Map();
67
+ /**
68
+ * Creates a new instance of HttpClientImproved.
69
+ * @param options Optional configuration options for the HTTP client
70
+ */
84
71
  constructor(options) {
85
72
  this.options = {
86
73
  timeout: options?.timeout ?? 15000,
@@ -126,7 +113,7 @@ class HttpClientImproved {
126
113
  this.limiter = new RateLimiter_1.RateLimiter(this.options.rateLimit);
127
114
  }
128
115
  this.retryOptions = {
129
- maxRetries: this.options.maxRetries,
116
+ maxRetries: this.options.maxRetries ?? 5,
130
117
  baseDelay: this.options.retryOptions?.baseDelay ?? 1000,
131
118
  maxDelay: this.options.retryOptions?.maxDelay ?? 30000,
132
119
  retryStatusCodes: this.options.retryOptions?.retryStatusCodes ?? [
@@ -134,6 +121,11 @@ class HttpClientImproved {
134
121
  ],
135
122
  jitter: this.options.retryOptions?.jitter ?? true,
136
123
  };
124
+ this.defaultHeaders = {
125
+ Accept: "application/json, text/plain, */*",
126
+ "Accept-Encoding": "gzip, deflate, br",
127
+ "User-Agent": this.options.userAgent ?? "Hyperttp/0.1.0 Node.js",
128
+ };
137
129
  this.agent = new undici_1.Agent({
138
130
  connections: 1000,
139
131
  pipelining: 10,
@@ -144,97 +136,85 @@ class HttpClientImproved {
144
136
  },
145
137
  });
146
138
  }
147
- log(level, msg, meta) {
148
- if (!this.options.logger)
149
- return;
150
- const minLevel = process.env.NODE_ENV === "production" ? "warn" : "info";
151
- const levels = ["debug", "info", "warn", "error"];
152
- const currentLevelIndex = levels.indexOf(level);
153
- const minLevelIndex = levels.indexOf(minLevel);
154
- if (currentLevelIndex < minLevelIndex)
155
- return;
156
- if (this.options.verbose || level !== "info") {
157
- this.options.logger(level, msg, meta);
158
- }
139
+ /**
140
+ * Sets default headers that will be applied to all outgoing requests.
141
+ * @param headers An object containing header names and values
142
+ */
143
+ setDefaultHeaders(headers) {
144
+ Object.assign(this.defaultHeaders, headers);
159
145
  }
160
146
  /**
161
- * Creates a hash of the request body for cache key generation.
162
- * @param body - Request body (string or Buffer)
163
- * @returns SHA1 hash of the body, truncated to 8 characters
147
+ * Returns the cookie jar used for managing HTTP cookies.
148
+ * @returns The CookieJar instance
164
149
  */
165
- hashBody(body) {
166
- if (!body)
167
- return "";
168
- if (typeof body === "string")
169
- body = Buffer.from(body, "utf-8");
170
- return (0, crypto_1.createHash)("sha1").update(body).digest("hex").slice(0, 8);
150
+ getCookieJar() {
151
+ return this.cookieJar;
171
152
  }
172
153
  /**
173
- * Calculates the delay for retry attempts using exponential backoff.
174
- * @param attempt - Current retry attempt number (0-based)
175
- * @returns Delay in milliseconds
154
+ * Adds a request interceptor to modify requests before they are sent.
155
+ * @param interceptor The interceptor function to add
176
156
  */
157
+ addRequestInterceptor(interceptor) {
158
+ this.requestInterceptors.push(interceptor);
159
+ }
160
+ /**
161
+ * Adds a response interceptor to modify responses after they are received.
162
+ * @param interceptor The interceptor function to add
163
+ */
164
+ addResponseInterceptor(interceptor) {
165
+ this.responseInterceptors.push(interceptor);
166
+ }
167
+ /** Closes the HTTP agent to properly terminate keep-alive connections. */
168
+ close() {
169
+ this.agent.close();
170
+ }
171
+ log(level, msg, meta) {
172
+ if (this.options.verbose) {
173
+ if (this.options.logger)
174
+ this.options.logger(level, msg, meta);
175
+ }
176
+ }
177
+ async decompress(buf, enc, charset = "utf-8") {
178
+ if (!enc)
179
+ return buf.toString(charset);
180
+ try {
181
+ switch (enc.toLowerCase()) {
182
+ case "gzip":
183
+ return (await gunzip(buf)).toString(charset);
184
+ case "deflate":
185
+ return (await inflate(buf)).toString(charset);
186
+ case "br":
187
+ return (await brotliDecompress(buf)).toString(charset);
188
+ default:
189
+ return buf.toString(charset);
190
+ }
191
+ }
192
+ catch (error) {
193
+ this.log("error", `Decompression failed for encoding ${enc}`, error);
194
+ return buf.toString(charset);
195
+ }
196
+ }
177
197
  calcDelay(attempt) {
178
198
  const base = Math.min(this.retryOptions.baseDelay * 2 ** attempt, this.retryOptions.maxDelay);
179
199
  return this.retryOptions.jitter
180
200
  ? base * (0.75 + Math.random() * 0.5)
181
201
  : base;
182
202
  }
183
- /**
184
- * Creates a promise that resolves after the specified delay.
185
- * @param ms - Delay in milliseconds
186
- * @returns Promise that resolves after the delay
187
- */
188
203
  sleep(ms) {
189
204
  return new Promise((resolve) => setTimeout(resolve, ms));
190
205
  }
191
- /**
192
- * Applies all registered request interceptors to modify the request configuration.
193
- * Interceptors are executed in sequence, with each one receiving the output of the previous.
194
- * @param config - Original request configuration
195
- * @returns Modified request configuration
196
- */
197
206
  async applyRequestInterceptors(config) {
198
- if (!this.requestInterceptors.length)
199
- return config;
200
207
  let result = config;
201
- for (const interceptor of this.requestInterceptors) {
202
- try {
203
- result = await interceptor(result);
204
- }
205
- catch (error) {
206
- this.log("error", "Request interceptor failed", { error });
207
- throw error;
208
- }
209
- }
208
+ for (const interceptor of this.requestInterceptors)
209
+ result = await interceptor(result);
210
210
  return result;
211
211
  }
212
- /**
213
- * Applies all registered response interceptors to modify the response data.
214
- * Interceptors are executed in sequence, with each one receiving the output of the previous.
215
- * @param response - Original response data
216
- * @returns Modified response data
217
- */
218
212
  async applyResponseInterceptors(response) {
219
213
  let result = response;
220
- for (const interceptor of this.responseInterceptors) {
221
- try {
222
- result = await interceptor(result);
223
- }
224
- catch (error) {
225
- this.log("error", "Response interceptor failed", { error });
226
- throw error;
227
- }
228
- }
214
+ for (const interceptor of this.responseInterceptors)
215
+ result = await interceptor(result);
229
216
  return result;
230
217
  }
231
- /**
232
- * Resolves a redirect location relative to the base URL.
233
- * Handles both absolute and relative redirect URLs.
234
- * @param location - The redirect location from the response
235
- * @param baseUrl - The original request URL
236
- * @returns The resolved absolute URL
237
- */
238
218
  resolveRedirect(location, baseUrl) {
239
219
  try {
240
220
  return new URL(location, baseUrl).toString();
@@ -243,12 +223,6 @@ class HttpClientImproved {
243
223
  return location;
244
224
  }
245
225
  }
246
- /**
247
- * Parses the Retry-After header to determine when to retry a request.
248
- * Supports both seconds and HTTP date formats.
249
- * @param retryAfterHeader - The Retry-After header value
250
- * @returns Delay in milliseconds, or undefined if not parseable
251
- */
252
226
  parseRetryAfterMs(retryAfterHeader) {
253
227
  if (!retryAfterHeader)
254
228
  return undefined;
@@ -263,159 +237,16 @@ class HttpClientImproved {
263
237
  return Math.max(0, asDate - Date.now());
264
238
  return undefined;
265
239
  }
266
- /**
267
- * Reads response body with size limit enforcement.
268
- * Collects chunks until the response is complete or the limit is exceeded.
269
- * @param body - Async iterable of response chunks
270
- * @returns Complete response body as a Buffer
271
- */
272
- async readBodyWithLimit(body, maxBytes = this.options.maxResponseBytes) {
273
- if (!body)
274
- return Buffer.alloc(0);
275
- // ⚡ максимально быстрый парсинг через arrayBuffer
276
- if (body?.arrayBuffer) {
277
- const arrayBuffer = await body.arrayBuffer();
278
- return Buffer.from(arrayBuffer);
279
- }
280
- if (body[Symbol.asyncIterator]) {
281
- const chunks = [];
282
- let total = 0;
283
- for await (const chunk of body) {
284
- chunks.push(Buffer.from(chunk));
285
- total += chunk.length;
286
- if (total > maxBytes)
287
- break;
288
- }
289
- return Buffer.concat(chunks);
290
- }
291
- if (Buffer.isBuffer(body))
292
- return body.subarray(0, maxBytes);
293
- if (typeof body === "string")
294
- return Buffer.from(body);
295
- throw new TypeError(`Unsupported body type: ${typeof body}`);
296
- }
297
- /**
298
- * Removes old metrics entries to prevent memory leaks.
299
- * Keeps only metrics from the last 24 hours.
300
- */
301
- trimMetrics() {
302
- const cutoff = Date.now() - 24 * 60 * 60 * 1000;
303
- for (const [key, metrics] of this.requestMetrics) {
304
- if (metrics.endTime && metrics.endTime < cutoff) {
305
- this.requestMetrics.delete(key);
306
- }
307
- }
308
- for (const key of this.inflight.keys()) {
309
- if (this.inflight.size > 1000) {
310
- this.inflight.delete(key);
311
- }
312
- }
313
- }
314
- /**
315
- * Sends an HTTP request with retry logic and rate limiting.
316
- * Handles timeouts, redirects, and various retry scenarios.
317
- * @param method - HTTP method (GET, POST, etc.)
318
- * @param url - Target URL
319
- * @param headers - HTTP headers
320
- * @param body - Request body (optional)
321
- * @param metrics - Optional metrics object to track request details
322
- * @param redirects - Number of redirects followed so far
323
- * @returns Promise resolving to the response data
324
- */
325
- async sendOnce(method, url, headers, body, metrics, redirects = 0) {
326
- let lastError;
327
- try {
328
- if (this.limiter && this.options.enableRateLimit) {
329
- await this.limiter.wait();
330
- }
331
- const finalConfig = await this.applyRequestInterceptors({
332
- url,
333
- method,
334
- headers,
335
- body,
336
- });
337
- const controller = new AbortController();
338
- const timeout = this.options.timeout;
339
- const timer = setTimeout(() => controller.abort(), timeout);
340
- try {
341
- const res = await (0, undici_1.request)(finalConfig.url, {
342
- method: finalConfig.method,
343
- headers: finalConfig.headers,
344
- body: finalConfig.body,
345
- dispatcher: this.agent,
346
- signal: controller.signal,
347
- });
348
- if (method === "HEAD") {
349
- clearTimeout(timer);
350
- return {
351
- status: res.statusCode,
352
- headers: res.headers,
353
- body: Buffer.alloc(0),
354
- url: finalConfig.url,
355
- };
356
- }
357
- clearTimeout(timer);
358
- const buf = await this.readBodyWithLimit(res.body);
359
- let response = await this.applyResponseInterceptors({
360
- status: res.statusCode,
361
- headers: res.headers,
362
- body: buf,
363
- url: finalConfig.url,
364
- });
365
- if (!this.options.validateStatus(response.status)) {
366
- throw new Types_1.HttpClientError(`Request failed with status ${response.status}`, response.status, undefined, finalConfig.url, finalConfig.method);
367
- }
368
- if (this.options.followRedirects &&
369
- [301, 302, 303, 307, 308].includes(response.status) &&
370
- redirects < (this.options.maxRedirects ?? 5)) {
371
- const location = response.headers.location;
372
- if (location) {
373
- const nextUrl = this.resolveRedirect(location, finalConfig.url);
374
- const redirectMethod = response.status === 303 ? "GET" : method;
375
- const nextHeaders = { ...headers };
376
- let nextBody = body;
377
- if (redirectMethod === "GET") {
378
- nextBody = undefined;
379
- delete nextHeaders["content-type"];
380
- delete nextHeaders["Content-Type"];
381
- delete nextHeaders["content-length"];
382
- delete nextHeaders["Content-Length"];
383
- }
384
- this.log("debug", `Redirecting to ${nextUrl}`, {
385
- originalUrl: finalConfig.url,
386
- status: response.status,
387
- });
388
- return this.sendOnce(redirectMethod, nextUrl, nextHeaders, nextBody, metrics, redirects + 1);
389
- }
390
- }
391
- return response;
392
- }
393
- catch (timeoutErr) {
394
- clearTimeout(timer);
395
- if (timeoutErr?.name === "AbortError")
396
- throw new Types_1.TimeoutError(url, timeout);
397
- throw timeoutErr;
398
- }
399
- finally {
400
- clearTimeout(timer);
401
- }
240
+ async readBodyWithLimit(body) {
241
+ const buf = Buffer.from(await body.arrayBuffer());
242
+ const limit = this.options.maxResponseBytes;
243
+ if (typeof limit === "number" && limit > 0 && buf.length > limit) {
244
+ throw new Types_1.HttpClientError(`Response too large (${buf.length} bytes), limit is ${limit}`, 0);
402
245
  }
403
- catch (err) {
404
- lastError = err;
405
- this.log("error", `Request error ${method} ${url}: ${err?.message ?? String(err)}`, {
406
- error: err,
407
- });
408
- metrics && (metrics.retries += 1);
409
- }
410
- if (lastError instanceof Types_1.HttpClientError)
411
- throw lastError;
412
- throw new Types_1.HttpClientError(`Request failed after 1 attempt`, undefined, lastError instanceof Error ? lastError : undefined, url, method);
246
+ return buf;
413
247
  }
414
248
  async sendWithRetry(method, url, headers, body, metrics, redirects = 0) {
415
249
  let lastError;
416
- if (this.retryOptions.maxRetries === 0) {
417
- return this.sendOnce(method, url, headers, body, metrics, redirects);
418
- }
419
250
  for (let attempt = 0; attempt <= this.retryOptions.maxRetries; attempt++) {
420
251
  try {
421
252
  if (this.limiter && this.options.enableRateLimit) {
@@ -428,7 +259,7 @@ class HttpClientImproved {
428
259
  body,
429
260
  });
430
261
  const controller = new AbortController();
431
- const timeout = this.options.timeout;
262
+ const timeout = this.options.timeout ?? 15000;
432
263
  const timer = setTimeout(() => controller.abort(), timeout);
433
264
  try {
434
265
  const res = await (0, undici_1.request)(finalConfig.url, {
@@ -438,15 +269,6 @@ class HttpClientImproved {
438
269
  dispatcher: this.agent,
439
270
  signal: controller.signal,
440
271
  });
441
- if (method === "HEAD") {
442
- clearTimeout(timer);
443
- return {
444
- status: res.statusCode,
445
- headers: res.headers,
446
- body: Buffer.alloc(0),
447
- url: finalConfig.url,
448
- };
449
- }
450
272
  clearTimeout(timer);
451
273
  const buf = await this.readBodyWithLimit(res.body);
452
274
  let response = await this.applyResponseInterceptors({
@@ -455,9 +277,7 @@ class HttpClientImproved {
455
277
  body: buf,
456
278
  url: finalConfig.url,
457
279
  });
458
- if (!this.options.validateStatus(response.status)) {
459
- throw new Types_1.HttpClientError(`Request failed with status ${response.status}`, response.status, undefined, finalConfig.url, finalConfig.method);
460
- }
280
+ // Redirects
461
281
  if (this.options.followRedirects &&
462
282
  [301, 302, 303, 307, 308].includes(response.status) &&
463
283
  redirects < (this.options.maxRedirects ?? 5)) {
@@ -467,6 +287,7 @@ class HttpClientImproved {
467
287
  const redirectMethod = response.status === 303 ? "GET" : method;
468
288
  const nextHeaders = { ...headers };
469
289
  let nextBody = body;
290
+ // If switching to GET, drop body-related headers.
470
291
  if (redirectMethod === "GET") {
471
292
  nextBody = undefined;
472
293
  delete nextHeaders["content-type"];
@@ -481,6 +302,7 @@ class HttpClientImproved {
481
302
  return this.sendWithRetry(redirectMethod, nextUrl, nextHeaders, nextBody, metrics, redirects + 1);
482
303
  }
483
304
  }
305
+ // Retry by status
484
306
  if (this.retryOptions.retryStatusCodes.includes(response.status)) {
485
307
  metrics && (metrics.retries += 1);
486
308
  if (response.status === 429) {
@@ -532,11 +354,6 @@ class HttpClientImproved {
532
354
  throw lastError;
533
355
  throw new Types_1.HttpClientError(`Request failed after ${this.retryOptions.maxRetries + 1} attempts`, undefined, lastError instanceof Error ? lastError : undefined, url, method);
534
356
  }
535
- /**
536
- * Parses the Content-Type header to extract MIME type and character encoding.
537
- * @param contentType - Content-Type header value
538
- * @returns Object containing type and charset information
539
- */
540
357
  parseContentType(contentType) {
541
358
  if (!contentType)
542
359
  return { type: "text/plain", charset: "utf-8" };
@@ -560,180 +377,69 @@ class HttpClientImproved {
560
377
  "base64",
561
378
  "hex",
562
379
  ];
563
- return {
564
- type,
565
- charset: allowed.includes(normalized)
566
- ? normalized
567
- : "utf-8",
568
- };
569
- }
570
- /**
571
- * Parses the HTTP response body based on content type and requested response type.
572
- * Handles JSON, XML, text, and buffer responses with fallback parsing.
573
- * @param res - HTTP response object
574
- * @param responseType - Desired response type
575
- * @returns Parsed response data
576
- */
380
+ const charset = (allowed.includes(normalized)
381
+ ? normalized
382
+ : "utf-8");
383
+ return { type, charset };
384
+ }
385
+ xmlParser = new fast_xml_parser_1.XMLParser({
386
+ ignoreAttributes: false,
387
+ allowBooleanAttributes: true,
388
+ });
577
389
  async parseResponse(res, responseType) {
578
- const { type } = this.parseContentType(res.headers["content-type"]);
579
- const finalType = responseType ?? (type.includes("application/json") ? "json" : "text");
580
390
  try {
391
+ const contentType = res.headers["content-type"] || "";
392
+ const text = await this.decompress(res.body, res.headers["content-encoding"]);
393
+ const finalType = responseType ?? "json";
581
394
  switch (finalType) {
582
- case "json":
583
- return JSON.parse(res.body.toString("utf8"));
395
+ case "json": {
396
+ if (contentType.includes("json")) {
397
+ return JSON.parse(text);
398
+ }
399
+ if (text.trim().startsWith("<")) {
400
+ return this.xmlParser.parse(text);
401
+ }
402
+ return { text };
403
+ }
584
404
  case "xml": {
405
+ const text = await this.decompress(res.body, res.headers["content-encoding"]);
406
+ if (text.trim().startsWith("<")) {
407
+ return text;
408
+ }
585
409
  try {
586
- const jsonData = JSON.parse(res.body.toString("utf8"));
587
- return new fast_xml_parser_1.XMLBuilder({ format: true }).build({ root: jsonData });
410
+ const json = JSON.parse(text);
411
+ return new fast_xml_parser_1.XMLBuilder({ format: true }).build({ root: json });
588
412
  }
589
413
  catch {
590
- return res.body.toString("utf8");
414
+ return String(text);
591
415
  }
592
416
  }
593
417
  case "text":
594
- return res.body.toString("utf8");
418
+ return text;
595
419
  case "buffer":
596
420
  return res.body;
597
421
  case "stream":
598
- throw new Error("Stream mode requires raw response. Use stream() method.");
422
+ return res.body;
599
423
  default:
600
- return res.body.toString("utf8");
424
+ return text;
601
425
  }
602
426
  }
603
- catch (err) {
604
- throw new Types_1.HttpClientError(`Parsing failed: ${err?.message ?? String(err)}`, res.status);
605
- }
606
- }
607
- /**
608
- * Makes an HTTP request without using the cache.
609
- * Used for methods that shouldn't be cached or when caching is disabled.
610
- * @param method - HTTP method
611
- * @param req - Request configuration
612
- * @param responseType - Expected response type
613
- * @returns Promise resolving to the response data
614
- */
615
- async requestInternalWithoutCache(method, req, responseType) {
616
- const url = req.getURL();
617
- const rawBody = req.getBodyData();
618
- const headers = Object.assign({}, this.baseHeaders, req.getHeaders());
619
- const isBodyAllowed = ["POST", "PUT", "PATCH", "DELETE"].includes(method);
620
- let body;
621
- const contentType = headers["content-type"] || headers["Content-Type"] || "";
622
- if (isBodyAllowed && rawBody !== undefined && rawBody !== null) {
623
- if (Buffer.isBuffer(rawBody)) {
624
- body = rawBody;
625
- }
626
- else if (typeof rawBody === "string") {
627
- body = rawBody;
628
- }
629
- else if (contentType.includes("application/x-www-form-urlencoded")) {
630
- body = new url_1.URLSearchParams(rawBody).toString();
631
- }
632
- else {
633
- body = JSON.stringify(rawBody);
634
- if (!contentType)
635
- headers["Content-Type"] = "application/json; charset=utf-8";
636
- }
637
- }
638
- const metrics = {
639
- startTime: Date.now(),
640
- endTime: 0,
641
- duration: 0,
642
- bytesReceived: 0,
643
- bytesSent: 0,
644
- retries: 0,
645
- cached: false,
646
- url,
647
- method,
648
- };
649
- const result = await (this.queue && this.options.enableQueue
650
- ? this.queue.enqueue(async () => {
651
- const res = await this.sendWithRetry(method, url, headers, body, metrics);
652
- metrics.statusCode = res.status;
653
- metrics.bytesReceived = res.body.length;
654
- metrics.bytesSent =
655
- body instanceof Buffer
656
- ? body.length
657
- : Buffer.byteLength(body || "");
658
- if (method === "HEAD") {
659
- return { status: res.status, headers: res.headers };
660
- }
661
- const parsed = await this.parseResponse(res, responseType);
662
- return parsed;
663
- })
664
- : (async () => {
665
- const res = await this.sendWithRetry(method, url, headers, body, metrics);
666
- metrics.statusCode = res.status;
667
- metrics.bytesReceived = res.body.length;
668
- metrics.bytesSent =
669
- body instanceof Buffer
670
- ? body.length
671
- : Buffer.byteLength(body || "");
672
- if (method === "HEAD") {
673
- return { status: res.status, headers: res.headers };
674
- }
675
- const parsed = await this.parseResponse(res, responseType);
676
- return parsed;
677
- })());
678
- metrics.endTime = Date.now();
679
- metrics.duration = metrics.endTime - metrics.startTime;
680
- this.requestMetrics.set(url, metrics);
681
- this.trimMetrics();
682
- return result;
683
- }
684
- /**
685
- * Makes an HTTP request with caching support.
686
- * Handles cache lookups, request deduplication, and automatic cache storage.
687
- * @param method - HTTP method
688
- * @param req - Request configuration
689
- * @param useCache - Whether to use caching (default: true)
690
- * @param responseType - Expected response type
691
- * @returns Promise resolving to the response data
692
- */
693
- async fastRequest(method, req, responseType) {
694
- const url = req.getURL();
695
- const headers = Object.assign({}, this.baseHeaders, req.getHeaders());
696
- const body = req.getBodyData();
697
- let finalBody;
698
- if (body == null) {
699
- finalBody = undefined;
700
- }
701
- else if (typeof body === "string" || Buffer.isBuffer(body)) {
702
- finalBody = body;
703
- }
704
- else {
705
- finalBody = JSON.stringify(body);
706
- }
707
- const res = await (0, undici_1.request)(url, {
708
- method,
709
- headers,
710
- body: finalBody,
711
- dispatcher: this.agent,
712
- });
713
- if (responseType === "json") {
714
- return res.body.json();
715
- }
716
- if (responseType === "text") {
717
- const text = await res.body.text();
718
- return text;
427
+ catch (error) {
428
+ this.log("error", "Failed to parse response", {
429
+ error,
430
+ status: res.status,
431
+ contentType: res.headers["content-type"],
432
+ });
433
+ throw new Types_1.HttpClientError(`Response parsing failed: ${error instanceof Error ? error.message : String(error)}`, res.status);
719
434
  }
720
- return Buffer.from(await res.body.arrayBuffer());
721
435
  }
722
436
  async requestInternal(method, req, useCache = true, responseType) {
723
- if (!this.cache &&
724
- !this.options.enableQueue &&
725
- !this.options.enableRateLimit &&
726
- this.retryOptions.maxRetries === 0 &&
727
- this.requestInterceptors.length === 0 &&
728
- this.responseInterceptors.length === 0) {
729
- return this.fastRequest(method, req, responseType);
730
- }
731
- if (this.options.cacheTTL === 0 || this.options.enableCache === false) {
732
- return this.requestInternalWithoutCache(method, req, responseType);
733
- }
734
437
  const url = req.getURL();
735
438
  const rawBody = req.getBodyData();
736
- const headers = Object.assign({}, this.baseHeaders, req.getHeaders());
439
+ const headers = {
440
+ ...this.defaultHeaders,
441
+ ...req.getHeaders(),
442
+ };
737
443
  const isBodyAllowed = ["POST", "PUT", "PATCH", "DELETE"].includes(method);
738
444
  let body;
739
445
  const contentType = headers["content-type"] || headers["Content-Type"] || "";
@@ -745,31 +451,26 @@ class HttpClientImproved {
745
451
  body = rawBody;
746
452
  }
747
453
  else if (contentType.includes("application/x-www-form-urlencoded")) {
748
- body = new url_1.URLSearchParams(rawBody).toString();
454
+ body = new URLSearchParams(rawBody).toString();
749
455
  }
750
456
  else {
751
457
  body = JSON.stringify(rawBody);
752
- if (!contentType)
458
+ if (!contentType) {
753
459
  headers["Content-Type"] = "application/json; charset=utf-8";
460
+ }
754
461
  }
755
462
  }
756
- let cacheKey;
757
- if (this.cache && useCache) {
758
- const bodyHash = this.hashBody(body);
759
- cacheKey = (0, crypto_1.createHash)("sha1")
760
- .update(method + url + bodyHash + responseType)
761
- .digest("hex");
762
- }
763
- if (cacheKey && this.options.cacheMethods.includes(method) && useCache && this.cache) {
764
- const cached = await this.cache.get(cacheKey);
765
- if (cached != null) {
463
+ const key = `${method}:${url}:${body ?? ""}`;
464
+ if (method === "GET" && useCache && this.cache) {
465
+ const cached = await this.cache.get(key);
466
+ if (cached) {
766
467
  this.log("debug", `Cache hit for ${url}`);
767
468
  return cached;
768
469
  }
769
470
  }
770
- if (cacheKey && this.inflight.has(cacheKey)) {
471
+ if (this.inflight.has(key)) {
771
472
  this.log("debug", `Deduplicating request for ${url}`);
772
- return this.inflight.get(cacheKey);
473
+ return this.inflight.get(key);
773
474
  }
774
475
  const promise = (async () => {
775
476
  const metrics = {
@@ -784,80 +485,53 @@ class HttpClientImproved {
784
485
  method,
785
486
  };
786
487
  try {
787
- this.log("debug", `Starting request: ${method} ${url}`);
788
- const result = await (this.queue && this.options.enableQueue
789
- ? this.queue.enqueue(async () => {
790
- const res = await this.sendWithRetry(method, url, headers, body, metrics);
791
- metrics.statusCode = res.status;
792
- metrics.bytesReceived = res.body.length;
793
- metrics.bytesSent =
794
- body instanceof Buffer
795
- ? body.length
796
- : Buffer.byteLength(body || "");
797
- if (method === "HEAD") {
798
- return { status: res.status, headers: res.headers };
799
- }
800
- const parsed = await this.parseResponse(res, responseType);
801
- if (cacheKey &&
802
- this.options.cacheMethods.includes(method) &&
803
- useCache &&
804
- this.cache) {
805
- this.cache.set(cacheKey, parsed);
806
- metrics.cached = true;
807
- }
808
- return parsed;
809
- })
810
- : (async () => {
811
- const res = await this.sendWithRetry(method, url, headers, body, metrics);
812
- metrics.statusCode = res.status;
813
- metrics.bytesReceived = res.body.length;
814
- metrics.bytesSent =
815
- body instanceof Buffer
816
- ? body.length
817
- : Buffer.byteLength(body || "");
818
- if (method === "HEAD") {
819
- return { status: res.status, headers: res.headers };
820
- }
821
- const parsed = await this.parseResponse(res, responseType);
822
- if (cacheKey &&
823
- this.options.cacheMethods.includes(method) &&
824
- useCache &&
825
- this.cache) {
826
- await this.cache.set(cacheKey, parsed);
827
- metrics.cached = true;
828
- }
829
- return parsed;
830
- })());
488
+ let result;
489
+ const res = await this.sendWithRetry(method, url, headers, body, metrics);
490
+ metrics.statusCode = res.status;
491
+ metrics.bytesReceived = res.body.length;
492
+ metrics.bytesSent =
493
+ body instanceof Buffer ? body.length : Buffer.byteLength(body || "");
494
+ if (method === "HEAD") {
495
+ metrics.endTime = Date.now();
496
+ metrics.duration = metrics.endTime - metrics.startTime;
497
+ this.requestMetrics.set(key, metrics);
498
+ this.log("info", `${method} ${url} completed in ${metrics.duration}ms`, metrics);
499
+ return {
500
+ status: res.status,
501
+ headers: res.headers,
502
+ };
503
+ }
504
+ const parsed = await this.parseResponse(res, responseType);
505
+ if (method === "GET" && useCache && this.cache) {
506
+ this.cache.set(key, parsed);
507
+ metrics.cached = true;
508
+ }
509
+ result = parsed;
831
510
  metrics.endTime = Date.now();
832
511
  metrics.duration = metrics.endTime - metrics.startTime;
833
- this.requestMetrics.set(cacheKey || url, metrics);
834
- this.trimMetrics();
512
+ this.requestMetrics.set(key, metrics);
835
513
  this.log("info", `${method} ${url} completed in ${metrics.duration}ms`, metrics);
836
514
  return result;
837
515
  }
838
516
  catch (error) {
839
517
  metrics.endTime = Date.now();
840
518
  metrics.duration = metrics.endTime - metrics.startTime;
841
- this.requestMetrics.set(cacheKey || url, metrics);
842
- this.trimMetrics();
519
+ this.requestMetrics.set(key, metrics);
843
520
  throw error;
844
521
  }
845
522
  finally {
846
- if (cacheKey)
847
- this.inflight.delete(cacheKey);
523
+ this.inflight.delete(key);
848
524
  }
849
525
  })();
850
- if (cacheKey)
851
- this.inflight.set(cacheKey, promise);
526
+ this.inflight.set(key, promise);
852
527
  return promise;
853
528
  }
854
529
  /**
855
- * Makes an HTTP GET request.
856
- * Supports both RequestInterface objects and direct URL strings.
857
- * GET requests are cached by default unless caching is disabled.
858
- * @param req - Request configuration or URL string
859
- * @param responseType - Expected response type (default: "json")
860
- * @returns Promise resolving to the response data
530
+ * Performs an HTTP GET request.
531
+ * @param req The request object containing URL and headers
532
+ * @param responseType Optional response parsing type
533
+ * @returns A promise that resolves to the parsed response
534
+ * @template T The expected response type
861
535
  */
862
536
  get(req, responseType = "json") {
863
537
  if (typeof req === "string") {
@@ -873,13 +547,11 @@ class HttpClientImproved {
873
547
  }
874
548
  }
875
549
  /**
876
- * Makes an HTTP POST request.
877
- * Supports both RequestInterface objects and direct URL strings with body data.
878
- * POST requests are not cached by default due to their side effects.
879
- * @param req - Request configuration or URL string
880
- * @param body - Request body data (optional)
881
- * @param responseType - Expected response type (default: "json")
882
- * @returns Promise resolving to the response data
550
+ * Performs an HTTP POST request.
551
+ * @param req The request object containing URL, body, and headers
552
+ * @param responseType Optional response parsing type
553
+ * @returns A promise that resolves to the parsed response
554
+ * @template T The expected response type
883
555
  */
884
556
  post(req, body, responseType = "json") {
885
557
  if (typeof req === "string") {
@@ -895,13 +567,11 @@ class HttpClientImproved {
895
567
  }
896
568
  }
897
569
  /**
898
- * Makes an HTTP PUT request.
899
- * Supports both RequestInterface objects and direct URL strings with body data.
900
- * PUT requests are not cached by default due to their side effects.
901
- * @param req - Request configuration or URL string
902
- * @param body - Request body data (optional)
903
- * @param responseType - Expected response type (default: "json")
904
- * @returns Promise resolving to the response data
570
+ * Performs an HTTP PUT request.
571
+ * @param req The request object containing URL, body, and headers
572
+ * @param responseType Optional response parsing type
573
+ * @returns A promise that resolves to the parsed response
574
+ * @template T The expected response type
905
575
  */
906
576
  put(req, body, responseType = "json") {
907
577
  if (typeof req === "string") {
@@ -914,6 +584,43 @@ class HttpClientImproved {
914
584
  }
915
585
  return this.requestInternal("PUT", req, false, responseType);
916
586
  }
587
+ /**
588
+ * Performs an HTTP DELETE request.
589
+ * @param req The request object containing URL and headers
590
+ * @param responseType Optional response parsing type
591
+ * @returns A promise that resolves to the parsed response
592
+ * @template T The expected response type
593
+ */
594
+ delete(req, responseType = "json") {
595
+ if (typeof req === "string") {
596
+ const client = new HttpClientImproved();
597
+ const simpleReq = {
598
+ getURL: () => req,
599
+ getBodyData: () => undefined,
600
+ getHeaders: () => ({}),
601
+ };
602
+ return client.delete(simpleReq, responseType);
603
+ }
604
+ return this.requestInternal("DELETE", req, false, responseType);
605
+ }
606
+ /**
607
+ * Performs an HTTP PATCH request.
608
+ * @param req The request object containing URL, body, and headers
609
+ * @param responseType Optional response parsing type
610
+ * @returns A promise that resolves to the parsed response
611
+ * @template T The expected response type
612
+ */
613
+ patch(req, body, responseType = "json") {
614
+ if (typeof req === "string") {
615
+ const simpleReq = {
616
+ getURL: () => req,
617
+ getBodyData: () => body,
618
+ getHeaders: () => ({ "Content-Type": "application/json" }),
619
+ };
620
+ return this.requestInternal("PATCH", simpleReq, false, responseType);
621
+ }
622
+ return this.requestInternal("PATCH", req, false, responseType);
623
+ }
917
624
  /**
918
625
  * @ru Получает потоковый ответ (для SSE, больших файлов).
919
626
  * @en Gets streaming response (for SSE, large files).
@@ -930,7 +637,10 @@ class HttpClientImproved {
930
637
  return (this.queue && this.options.enableQueue
931
638
  ? this.queue.enqueue(async function () {
932
639
  const url = req.getURL();
933
- const headers = Object.assign({}, this.baseHeaders, req.getHeaders());
640
+ const headers = {
641
+ ...this.defaultHeaders,
642
+ ...req.getHeaders(),
643
+ };
934
644
  const response = await (0, undici_1.request)(url, {
935
645
  method: "GET",
936
646
  headers,
@@ -945,7 +655,7 @@ class HttpClientImproved {
945
655
  }.bind(this))
946
656
  : async function () {
947
657
  const url = req.getURL();
948
- const headers = Object.assign({}, this.baseHeaders, req.getHeaders());
658
+ const headers = Object.assign({}, this.defaultHeaders, req.getHeaders());
949
659
  const response = await (0, undici_1.request)(url, {
950
660
  method: "GET",
951
661
  headers,
@@ -960,49 +670,9 @@ class HttpClientImproved {
960
670
  }.bind(this)());
961
671
  }
962
672
  /**
963
- * Makes an HTTP DELETE request.
964
- * Supports both RequestInterface objects and direct URL strings.
965
- * DELETE requests are not cached by default due to their side effects.
966
- * @param req - Request configuration or URL string
967
- * @param responseType - Expected response type (default: "json")
968
- * @returns Promise resolving to the response data
969
- */
970
- delete(req, responseType = "json") {
971
- if (typeof req === "string") {
972
- const client = defaultClient ?? (defaultClient = new HttpClientImproved());
973
- const simpleReq = {
974
- getURL: () => req,
975
- getBodyData: () => undefined,
976
- getHeaders: () => ({}),
977
- };
978
- return client.delete(simpleReq, responseType);
979
- }
980
- return this.requestInternal("DELETE", req, false, responseType);
981
- }
982
- /**
983
- * Makes an HTTP PATCH request.
984
- * PATCH requests are not cached by default due to their side effects.
985
- * @param req - Request configuration
986
- * @param responseType - Expected response type (default: "json")
987
- * @returns Promise resolving to the response data
988
- */
989
- patch(req, body, responseType = "json") {
990
- if (typeof req === "string") {
991
- const simpleReq = {
992
- getURL: () => req,
993
- getBodyData: () => body,
994
- getHeaders: () => ({ "Content-Type": "application/json" }),
995
- };
996
- return this.requestInternal("PATCH", simpleReq, false, responseType);
997
- }
998
- return this.requestInternal("PATCH", req, false, responseType);
999
- }
1000
- /**
1001
- * Makes an HTTP HEAD request.
1002
- * Returns only the status code and headers without the response body.
1003
- * HEAD requests are not cached by default.
1004
- * @param req - Request configuration or URL string
1005
- * @returns Promise resolving to status and headers
673
+ * Performs an HTTP HEAD request.
674
+ * @param req The request object containing URL and headers
675
+ * @returns A promise that resolves when the request completes
1006
676
  */
1007
677
  async head(req) {
1008
678
  if (typeof req === "string") {
@@ -1016,8 +686,7 @@ class HttpClientImproved {
1016
686
  return this.requestInternal("HEAD", req, false);
1017
687
  }
1018
688
  /**
1019
- * Clears the internal cache of the HTTP client.
1020
- * Removes all cached responses and resets the cache state.
689
+ * Clears the request cache.
1021
690
  */
1022
691
  async clearCache() {
1023
692
  if (this.cache) {
@@ -1055,12 +724,11 @@ class HttpClientImproved {
1055
724
  * @returns RequestBuilder instance for chaining
1056
725
  */
1057
726
  request(url) {
1058
- return new RequestBuilder(url);
727
+ return new RequestBuilder_1.RequestBuilder(url);
1059
728
  }
1060
729
  /**
1061
730
  * Returns current statistics about the HTTP client's state.
1062
- * Useful for monitoring and debugging performance.
1063
- * @returns Object containing various client statistics
731
+ * @returns An object containing cache size, request counts, and rate limit information
1064
732
  */
1065
733
  getStats() {
1066
734
  return {
@@ -1075,173 +743,8 @@ class HttpClientImproved {
1075
743
  currentRateLimit: this.limiter && this.options.enableRateLimit
1076
744
  ? (this.limiter.currentCount ?? 0)
1077
745
  : 0,
1078
- metricsSize: this.requestMetrics.size,
1079
746
  };
1080
747
  }
1081
748
  }
1082
749
  exports.default = HttpClientImproved;
1083
- /**
1084
- * Fluent request builder for making HTTP requests with a chainable API.
1085
- * Provides a convenient way to build and send HTTP requests with various options.
1086
- *
1087
- * @example
1088
- * ```ts
1089
- * const client = new HttpClientImproved();
1090
- * const response = await client.request('https://api.example.com/data')
1091
- * .headers({ 'Authorization': 'Bearer token' })
1092
- * .query({ limit: 10, offset: 0 })
1093
- * .json()
1094
- * .send();
1095
- * ```
1096
- */
1097
- class RequestBuilder {
1098
- _url;
1099
- _method = "GET";
1100
- _headers = {};
1101
- _body;
1102
- _responseType = "json";
1103
- /**
1104
- * Creates a new request builder for the specified URL.
1105
- * @param url - The target URL for the request
1106
- */
1107
- constructor(url) {
1108
- this._url = url;
1109
- }
1110
- /**
1111
- * Sets HTTP headers for the request.
1112
- * @param headers - Object containing header key-value pairs
1113
- * @returns The builder instance for chaining
1114
- */
1115
- headers(headers) {
1116
- this._headers = headers;
1117
- return this;
1118
- }
1119
- /**
1120
- * Sets the request body data.
1121
- * @param bodyData - The body data to send with the request
1122
- * @returns The builder instance for chaining
1123
- */
1124
- body(bodyData) {
1125
- this._body = bodyData;
1126
- return this;
1127
- }
1128
- /**
1129
- * Sets the response type to JSON.
1130
- * @returns The builder instance for chaining
1131
- */
1132
- json() {
1133
- this._responseType = "json";
1134
- return this;
1135
- }
1136
- /**
1137
- * Sets the response type to plain text.
1138
- * @returns The builder instance for chaining
1139
- */
1140
- text() {
1141
- this._responseType = "text";
1142
- return this;
1143
- }
1144
- /**
1145
- * Sets the response type to XML.
1146
- * @returns The builder instance for chaining
1147
- */
1148
- xml() {
1149
- this._responseType = "xml";
1150
- return this;
1151
- }
1152
- /**
1153
- * Sets the HTTP method to POST.
1154
- * @returns The builder instance for chaining
1155
- */
1156
- post() {
1157
- this._method = "POST";
1158
- return this;
1159
- }
1160
- /**
1161
- * @ru Устанавливает потоковый режим ответа.
1162
- * @en Sets streaming response mode.
1163
- */
1164
- stream() {
1165
- this._responseType = "stream";
1166
- return this;
1167
- }
1168
- /**
1169
- * Sets the HTTP method to PUT.
1170
- * @returns The builder instance for chaining
1171
- */
1172
- put() {
1173
- this._method = "PUT";
1174
- return this;
1175
- }
1176
- /**
1177
- * Sets the HTTP method to PATCH.
1178
- * @returns The builder instance for chaining
1179
- */
1180
- patch() {
1181
- this._method = "PATCH";
1182
- return this;
1183
- }
1184
- /**
1185
- * Sets the HTTP method to DELETE.
1186
- * @returns The builder instance for chaining
1187
- */
1188
- delete() {
1189
- this._method = "DELETE";
1190
- return this;
1191
- }
1192
- /**
1193
- * Adds query parameters to the URL.
1194
- * @param params - Object containing query parameter key-value pairs
1195
- * @returns The builder instance for chaining
1196
- */
1197
- query(params) {
1198
- const urlObj = new URL(this._url);
1199
- Object.entries(params).forEach(([k, v]) => urlObj.searchParams.set(k, String(v)));
1200
- this._url = urlObj.toString();
1201
- return this;
1202
- }
1203
- /**
1204
- * Sets a JSON body for the request.
1205
- * Automatically sets the Content-Type header to application/json.
1206
- * @param body - The JSON body data
1207
- * @returns The builder instance for chaining
1208
- */
1209
- jsonBody(body) {
1210
- this._body = body;
1211
- this._headers["Content-Type"] = "application/json; charset=utf-8";
1212
- return this;
1213
- }
1214
- /**
1215
- * Sends the HTTP request and returns the response.
1216
- * @returns Promise resolving to the response data
1217
- */
1218
- async send() {
1219
- const client = defaultClient ?? (defaultClient = new HttpClientImproved());
1220
- const req = {
1221
- getURL: () => this._url,
1222
- getBodyData: () => this._body,
1223
- getHeaders: () => this._headers,
1224
- };
1225
- switch (this._method) {
1226
- case "GET":
1227
- if (this._responseType === "stream") {
1228
- return client.stream(req);
1229
- }
1230
- return client.get(req, this._responseType);
1231
- case "POST":
1232
- return client.post(req, this._body, this._responseType);
1233
- case "PUT":
1234
- return client.put(req, this._body, this._responseType);
1235
- case "DELETE":
1236
- return client.delete(req, this._responseType);
1237
- case "PATCH":
1238
- return client.patch(req, this._body, this._responseType);
1239
- default:
1240
- if (this._responseType === "stream") {
1241
- return client.stream(req);
1242
- }
1243
- return client.get(req, this._responseType);
1244
- }
1245
- }
1246
- }
1247
750
  //# sourceMappingURL=HttpClientImproved.js.map