@ai-sdk/provider-utils 4.0.59 → 4.0.61

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/index.mjs CHANGED
@@ -499,8 +499,45 @@ function getCurrentModulePath() {
499
499
  }
500
500
  }
501
501
 
502
+ // src/sanitize-request-headers.ts
503
+ var BLOCKED_REQUEST_HEADERS = [
504
+ // Hop-by-hop / transport (RFC 7230 §6.1)
505
+ "connection",
506
+ "keep-alive",
507
+ "te",
508
+ "trailer",
509
+ "transfer-encoding",
510
+ "upgrade",
511
+ // Host / virtual-host routing
512
+ "host",
513
+ // Proxy / origin spoofing
514
+ "forwarded",
515
+ "proxy-authorization",
516
+ "via",
517
+ "x-forwarded-for",
518
+ "x-forwarded-host",
519
+ "x-forwarded-proto",
520
+ "x-real-ip",
521
+ // Cloud metadata (GCP, AWS IMDSv1/v2, Azure, Alibaba, DigitalOcean)
522
+ "metadata",
523
+ "metadata-flavor",
524
+ "x-aws-ec2-metadata-token",
525
+ "x-metadata-token",
526
+ // Session / cookie
527
+ "cookie",
528
+ "set-cookie"
529
+ ];
530
+ function sanitizeRequestHeaders(input) {
531
+ const headers = new Headers(input);
532
+ for (const name2 of BLOCKED_REQUEST_HEADERS) {
533
+ headers.delete(name2);
534
+ }
535
+ return headers;
536
+ }
537
+
502
538
  // src/fetch-with-validated-redirects.ts
503
539
  var MAX_DOWNLOAD_REDIRECTS = 10;
540
+ var REDIRECT_STATUS_CODES = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
504
541
  async function getValidatedFetch(customFetch) {
505
542
  return customFetch == null || customFetch === globalThis.fetch ? await getDefaultDownloadFetch() : customFetch;
506
543
  }
@@ -531,10 +568,14 @@ async function fetchWithValidatedRedirects({
531
568
  trustedOrigin
532
569
  }) {
533
570
  var _a2;
534
- const baseInit = { signal: abortSignal };
535
- if (headers !== void 0) {
536
- baseInit.headers = headers;
537
- }
571
+ let currentHeaders = headers === void 0 ? void 0 : sanitizeRequestHeaders(headers);
572
+ const perHopInit = (redirect) => {
573
+ const init = { signal: abortSignal, redirect };
574
+ if (currentHeaders !== void 0) {
575
+ init.headers = new Headers(currentHeaders);
576
+ }
577
+ return init;
578
+ };
538
579
  let currentUrl = url;
539
580
  for (let redirectCount = 0; redirectCount <= maxRedirects; redirectCount++) {
540
581
  const isTrustedHop = trustedOrigin !== void 0 && isSameOrigin(currentUrl, trustedOrigin);
@@ -542,10 +583,7 @@ async function fetchWithValidatedRedirects({
542
583
  validateDownloadUrl(currentUrl);
543
584
  }
544
585
  const fetch = isTrustedHop && customFetch != null ? customFetch : isTrustedHop ? globalThis.fetch : await getValidatedFetch(customFetch);
545
- const response = await fetch(currentUrl, {
546
- ...baseInit,
547
- redirect: "manual"
548
- });
586
+ const response = await fetch(currentUrl, perHopInit("manual"));
549
587
  if (response.type === "opaqueredirect") {
550
588
  if (!isBrowserRuntime()) {
551
589
  throw new DownloadError({
@@ -553,12 +591,19 @@ async function fetchWithValidatedRedirects({
553
591
  message: `Redirect from ${currentUrl} could not be validated and was blocked`
554
592
  });
555
593
  }
556
- return await fetch(currentUrl, { ...baseInit, redirect: "follow" });
594
+ return await fetch(currentUrl, perHopInit("follow"));
557
595
  }
558
596
  const location = (_a2 = response.headers) == null ? void 0 : _a2.get("location");
559
- if (response.status >= 300 && response.status < 400 && location) {
560
- await cancelResponseBody(response);
561
- currentUrl = new URL(location, currentUrl).toString();
597
+ if (REDIRECT_STATUS_CODES.has(response.status) && location) {
598
+ void cancelResponseBody(response);
599
+ const nextUrl = new URL(location, currentUrl).toString();
600
+ if (currentHeaders !== void 0 && !isSameOrigin(nextUrl, currentUrl)) {
601
+ const userAgent = currentHeaders.get("user-agent");
602
+ currentHeaders = new Headers(
603
+ userAgent == null ? void 0 : { "user-agent": userAgent }
604
+ );
605
+ }
606
+ currentUrl = nextUrl;
562
607
  continue;
563
608
  }
564
609
  return response;
@@ -848,7 +893,7 @@ function withUserAgentSuffix(headers, ...userAgentSuffixParts) {
848
893
  }
849
894
 
850
895
  // src/version.ts
851
- var VERSION = true ? "4.0.59" : "0.0.0-test";
896
+ var VERSION = true ? "4.0.61" : "0.0.0-test";
852
897
 
853
898
  // src/get-from-api.ts
854
899
  var getOriginalFetch = () => globalThis.fetch;
@@ -858,16 +903,28 @@ var getFromApi = async ({
858
903
  successfulResponseHandler,
859
904
  failedResponseHandler,
860
905
  abortSignal,
861
- fetch = getOriginalFetch()
906
+ fetch,
907
+ validateUrl,
908
+ credentialedOrigin,
909
+ trustedOrigin
862
910
  }) => {
863
911
  try {
864
- const response = await fetch(url, {
912
+ const requestFetch = fetch != null ? fetch : getOriginalFetch();
913
+ const outgoingHeaders = credentialedOrigin !== void 0 && !isSameOrigin(url, credentialedOrigin) ? {} : headers;
914
+ const requestHeaders = withUserAgentSuffix(
915
+ outgoingHeaders,
916
+ `ai-sdk/provider-utils/${VERSION}`,
917
+ getRuntimeEnvironmentUserAgent()
918
+ );
919
+ const response = validateUrl ? await fetchWithValidatedRedirects({
920
+ url,
921
+ headers: requestHeaders,
922
+ abortSignal,
923
+ fetch,
924
+ trustedOrigin
925
+ }) : await requestFetch(url, {
865
926
  method: "GET",
866
- headers: withUserAgentSuffix(
867
- headers,
868
- `ai-sdk/provider-utils/${VERSION}`,
869
- getRuntimeEnvironmentUserAgent()
870
- ),
927
+ headers: requestHeaders,
871
928
  signal: abortSignal
872
929
  });
873
930
  const responseHeaders = extractResponseHeaders(response);