@apifuse/provider-sdk 2.1.0-beta.19 → 2.1.0-beta.20

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/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # @apifuse/provider-sdk Changelog
2
2
 
3
+ ## 2.1.0-beta.20
4
+
5
+ - Release candidate for main commit 2a07cc5aef0d517c3b01d20445105f1669446bd3.
6
+
3
7
  ## 2.1.0-beta.19
4
8
 
5
9
  - Release candidate for main commit 71d76385f722b1202880f26b14ea3916a07852eb.
@@ -477,12 +477,18 @@ function isAbsoluteUrl(url) {
477
477
  function resolveHttpUrl(baseUrl, url) {
478
478
  return new URL(url, baseUrl ?? DEFAULT_HTTP_BASE_URL).toString();
479
479
  }
480
- async function resolveNativeProxy(options, clientOptions, warn) {
480
+ async function resolveNativeProxy(options, clientOptions, warn, proxyAttemptOffset = 0) {
481
+ const baseProxyAttempt = clientOptions.proxyAttempt === undefined ||
482
+ !Number.isFinite(clientOptions.proxyAttempt)
483
+ ? 0
484
+ : Math.max(0, Math.floor(clientOptions.proxyAttempt));
481
485
  const resolvedProxy = await resolveProxyConfigAsync({
482
486
  proxy: options.proxy ?? clientOptions.proxy,
483
487
  upstream: clientOptions.upstream,
484
488
  apifuseConfig: clientOptions.apifuseConfig,
489
+ proxyPolicy: clientOptions.proxyPolicy,
485
490
  affinityKey: clientOptions.affinityKey,
491
+ proxyAttempt: baseProxyAttempt + proxyAttemptOffset,
486
492
  telemetry: clientOptions.telemetry,
487
493
  });
488
494
  if (resolvedProxy.shouldWarn) {
@@ -504,14 +510,15 @@ function normalizeNativeFetchBody(body) {
504
510
  copied.set(normalized);
505
511
  return copied.buffer;
506
512
  }
507
- async function fetchNativeHttp(baseUrl, url, method, options, clientOptions, warn, statusRetryCodes) {
513
+ async function fetchNativeHttp(baseUrl, url, method, options, clientOptions, warn, statusRetryCodes, proxyAttemptOffset = 0) {
508
514
  const requestUrl = appendQueryParams(resolveHttpUrl(baseUrl, url), options.params);
509
515
  const controller = options.timeout ? new AbortController() : undefined;
510
516
  const timeoutHandle = options.timeout
511
517
  ? setTimeout(() => controller?.abort(), options.timeout)
512
518
  : undefined;
519
+ let proxy;
513
520
  try {
514
- const proxy = await resolveNativeProxy(options, clientOptions, warn);
521
+ proxy = await resolveNativeProxy(options, clientOptions, warn, proxyAttemptOffset);
515
522
  const requestInit = {
516
523
  headers: options.headers,
517
524
  method,
@@ -532,6 +539,7 @@ async function fetchNativeHttp(baseUrl, url, method, options, clientOptions, war
532
539
  status: response.status,
533
540
  headers,
534
541
  retryable: statusRetryCodes.includes(response.status),
542
+ proxyUsed: Boolean(proxy),
535
543
  };
536
544
  }
537
545
  if (response.status >= 400 && options.throwOnHttpError !== false) {
@@ -547,7 +555,9 @@ async function fetchNativeHttp(baseUrl, url, method, options, clientOptions, war
547
555
  if (error instanceof SyntaxError) {
548
556
  throw error;
549
557
  }
550
- throw toHttpTransportError(error);
558
+ const transportError = toHttpTransportError(error);
559
+ transportError.proxyUsed = Boolean(proxy);
560
+ throw transportError;
551
561
  }
552
562
  finally {
553
563
  if (timeoutHandle)
@@ -611,20 +621,25 @@ export function createHttpClient(baseUrl, clientOptions = {}) {
611
621
  assertNoHttpTransportOverrides(options);
612
622
  const headersOptions = withClientHeaders(options, clientOptions, options.body);
613
623
  const methodName = normalizeHttpMethod(method);
614
- const retryOptions = normalizeRetryOptions(headersOptions.retry);
624
+ const explicitRetry = headersOptions.retry !== undefined;
625
+ const retryOptions = normalizeRetryOptions(headersOptions.retry) ??
626
+ (explicitRetry
627
+ ? undefined
628
+ : createRetryOptions(HttpRetryPreset.TransportTransient));
615
629
  if (retryOptions)
616
630
  validateUnsafeRetryMethods(retryOptions);
617
631
  const retryEnabled = Boolean(retryOptions &&
618
632
  retryOptions.attempts > 1 &&
619
633
  isMethodRetryable(methodName, retryOptions));
620
634
  const statusRetryEnabled = Boolean(retryEnabled &&
635
+ explicitRetry &&
621
636
  retryOptions &&
622
637
  retryOptions.statusCodes.length > 0 &&
623
638
  headersOptions.throwOnHttpError !== false);
624
639
  const attemptOptions = statusRetryEnabled
625
640
  ? { ...headersOptions, throwOnHttpError: false }
626
641
  : headersOptions;
627
- const executeOnce = () => fetchNativeHttp(baseUrl, url, methodName, attemptOptions, clientOptions, warnOnce, statusRetryEnabled ? retryOptions?.statusCodes : undefined);
642
+ const executeOnce = (proxyAttemptOffset = 0) => fetchNativeHttp(baseUrl, url, methodName, attemptOptions, clientOptions, warnOnce, statusRetryEnabled ? retryOptions?.statusCodes : undefined, proxyAttemptOffset);
628
643
  if (!retryEnabled || !retryOptions) {
629
644
  const outcome = await executeOnce();
630
645
  if (isHttpStatusOutcome(outcome)) {
@@ -636,7 +651,7 @@ export function createHttpClient(baseUrl, clientOptions = {}) {
636
651
  let lastStatus;
637
652
  for (let attempt = 1; attempt <= retryOptions.attempts; attempt += 1) {
638
653
  try {
639
- const outcome = await executeOnce();
654
+ const outcome = await executeOnce(attempt - 1);
640
655
  if (isHttpStatusOutcome(outcome)) {
641
656
  lastStatus = outcome.status;
642
657
  if (outcome.retryable && attempt < retryOptions.attempts) {
@@ -666,7 +681,9 @@ export function createHttpClient(baseUrl, clientOptions = {}) {
666
681
  catch (error) {
667
682
  lastErrorCode = retryErrorCode(error);
668
683
  lastStatus = retryErrorStatus(error);
684
+ const proxyUsed = Boolean(error.proxyUsed);
669
685
  if (attempt < retryOptions.attempts &&
686
+ (explicitRetry || proxyUsed) &&
670
687
  shouldRetryTransportError(error, retryOptions)) {
671
688
  await sleep(computeRetryDelayMs(retryOptions, attempt));
672
689
  continue;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.1.0-beta.19",
2
+ "version": "2.1.0-beta.20",
3
3
  "name": "@apifuse/provider-sdk",
4
4
  "private": false,
5
5
  "type": "module",
@@ -58,8 +58,13 @@ type HttpStatusOutcome = {
58
58
  status: number;
59
59
  headers: Record<string, string>;
60
60
  retryable: boolean;
61
+ proxyUsed: boolean;
61
62
  };
62
63
 
64
+ type NativeHttpAttemptOutcome = HttpResponse | HttpStatusOutcome;
65
+
66
+ type NativeHttpAttemptError = TransportError & { proxyUsed?: boolean };
67
+
63
68
  function isHttpStatusOutcome(
64
69
  outcome: HttpResponse | HttpStatusOutcome,
65
70
  ): outcome is HttpStatusOutcome {
@@ -685,12 +690,20 @@ async function resolveNativeProxy(
685
690
  options: RequestOptions,
686
691
  clientOptions: HttpClientOptions,
687
692
  warn: (message: string) => void,
693
+ proxyAttemptOffset = 0,
688
694
  ): Promise<string | undefined> {
695
+ const baseProxyAttempt =
696
+ clientOptions.proxyAttempt === undefined ||
697
+ !Number.isFinite(clientOptions.proxyAttempt)
698
+ ? 0
699
+ : Math.max(0, Math.floor(clientOptions.proxyAttempt));
689
700
  const resolvedProxy = await resolveProxyConfigAsync({
690
701
  proxy: options.proxy ?? clientOptions.proxy,
691
702
  upstream: clientOptions.upstream,
692
703
  apifuseConfig: clientOptions.apifuseConfig,
704
+ proxyPolicy: clientOptions.proxyPolicy,
693
705
  affinityKey: clientOptions.affinityKey,
706
+ proxyAttempt: baseProxyAttempt + proxyAttemptOffset,
694
707
  telemetry: clientOptions.telemetry,
695
708
  });
696
709
  if (resolvedProxy.shouldWarn) {
@@ -730,7 +743,8 @@ async function fetchNativeHttp(
730
743
  clientOptions: HttpClientOptions,
731
744
  warn: (message: string) => void,
732
745
  statusRetryCodes?: readonly number[],
733
- ): Promise<HttpResponse | HttpStatusOutcome> {
746
+ proxyAttemptOffset = 0,
747
+ ): Promise<NativeHttpAttemptOutcome> {
734
748
  const requestUrl = appendQueryParams(
735
749
  resolveHttpUrl(baseUrl, url),
736
750
  options.params,
@@ -740,8 +754,14 @@ async function fetchNativeHttp(
740
754
  ? setTimeout(() => controller?.abort(), options.timeout)
741
755
  : undefined;
742
756
 
757
+ let proxy: string | undefined;
743
758
  try {
744
- const proxy = await resolveNativeProxy(options, clientOptions, warn);
759
+ proxy = await resolveNativeProxy(
760
+ options,
761
+ clientOptions,
762
+ warn,
763
+ proxyAttemptOffset,
764
+ );
745
765
  const requestInit: NativeFetchInit = {
746
766
  headers: options.headers,
747
767
  method,
@@ -763,6 +783,7 @@ async function fetchNativeHttp(
763
783
  status: response.status,
764
784
  headers,
765
785
  retryable: statusRetryCodes.includes(response.status),
786
+ proxyUsed: Boolean(proxy),
766
787
  };
767
788
  }
768
789
 
@@ -782,7 +803,9 @@ async function fetchNativeHttp(
782
803
  if (error instanceof SyntaxError) {
783
804
  throw error;
784
805
  }
785
- throw toHttpTransportError(error);
806
+ const transportError = toHttpTransportError(error) as NativeHttpAttemptError;
807
+ transportError.proxyUsed = Boolean(proxy);
808
+ throw transportError;
786
809
  } finally {
787
810
  if (timeoutHandle) clearTimeout(timeoutHandle);
788
811
  }
@@ -874,7 +897,12 @@ export function createHttpClient(
874
897
  options.body,
875
898
  );
876
899
  const methodName = normalizeHttpMethod(method);
877
- const retryOptions = normalizeRetryOptions(headersOptions.retry);
900
+ const explicitRetry = headersOptions.retry !== undefined;
901
+ const retryOptions =
902
+ normalizeRetryOptions(headersOptions.retry) ??
903
+ (explicitRetry
904
+ ? undefined
905
+ : createRetryOptions(HttpRetryPreset.TransportTransient));
878
906
  if (retryOptions) validateUnsafeRetryMethods(retryOptions);
879
907
  const retryEnabled = Boolean(
880
908
  retryOptions &&
@@ -883,6 +911,7 @@ export function createHttpClient(
883
911
  );
884
912
  const statusRetryEnabled = Boolean(
885
913
  retryEnabled &&
914
+ explicitRetry &&
886
915
  retryOptions &&
887
916
  retryOptions.statusCodes.length > 0 &&
888
917
  headersOptions.throwOnHttpError !== false,
@@ -892,7 +921,9 @@ export function createHttpClient(
892
921
  ? { ...headersOptions, throwOnHttpError: false }
893
922
  : headersOptions;
894
923
 
895
- const executeOnce = (): Promise<HttpResponse | HttpStatusOutcome> =>
924
+ const executeOnce = (
925
+ proxyAttemptOffset = 0,
926
+ ): Promise<NativeHttpAttemptOutcome> =>
896
927
  fetchNativeHttp(
897
928
  baseUrl,
898
929
  url,
@@ -901,6 +932,7 @@ export function createHttpClient(
901
932
  clientOptions,
902
933
  warnOnce,
903
934
  statusRetryEnabled ? retryOptions?.statusCodes : undefined,
935
+ proxyAttemptOffset,
904
936
  );
905
937
 
906
938
  if (!retryEnabled || !retryOptions) {
@@ -915,7 +947,7 @@ export function createHttpClient(
915
947
  let lastStatus: number | undefined;
916
948
  for (let attempt = 1; attempt <= retryOptions.attempts; attempt += 1) {
917
949
  try {
918
- const outcome = await executeOnce();
950
+ const outcome = await executeOnce(attempt - 1);
919
951
  if (isHttpStatusOutcome(outcome)) {
920
952
  lastStatus = outcome.status;
921
953
  if (outcome.retryable && attempt < retryOptions.attempts) {
@@ -950,8 +982,10 @@ export function createHttpClient(
950
982
  } catch (error) {
951
983
  lastErrorCode = retryErrorCode(error);
952
984
  lastStatus = retryErrorStatus(error);
985
+ const proxyUsed = Boolean((error as NativeHttpAttemptError).proxyUsed);
953
986
  if (
954
987
  attempt < retryOptions.attempts &&
988
+ (explicitRetry || proxyUsed) &&
955
989
  shouldRetryTransportError(error, retryOptions)
956
990
  ) {
957
991
  await sleep(computeRetryDelayMs(retryOptions, attempt));