@ai-sdk/provider-utils 4.0.60 → 4.0.62

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
@@ -284,7 +284,7 @@ function validateDownloadUrl(url) {
284
284
  message: `URL must have a hostname`
285
285
  });
286
286
  }
287
- if (hostname === "localhost" || hostname.endsWith(".local") || hostname.endsWith(".localhost")) {
287
+ if (hostname === "localhost" || hostname.endsWith(".local") || hostname.endsWith(".localhost") || hostname.endsWith(".internal")) {
288
288
  throw new DownloadError({
289
289
  url,
290
290
  message: `URL with hostname ${hostname} is not allowed`
@@ -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;
@@ -694,6 +739,12 @@ var createIdGenerator = ({
694
739
  };
695
740
  var generateId = createIdGenerator();
696
741
 
742
+ // src/encode-path-segment.ts
743
+ function encodePathSegment(value) {
744
+ const encodedValue = encodeURIComponent(value);
745
+ return encodedValue === "." ? "%252E" : encodedValue === ".." ? "%252E%252E" : encodedValue;
746
+ }
747
+
697
748
  // src/get-error-message.ts
698
749
  function getErrorMessage(error) {
699
750
  if (error == null) {
@@ -848,7 +899,7 @@ function withUserAgentSuffix(headers, ...userAgentSuffixParts) {
848
899
  }
849
900
 
850
901
  // src/version.ts
851
- var VERSION = true ? "4.0.60" : "0.0.0-test";
902
+ var VERSION = true ? "4.0.62" : "0.0.0-test";
852
903
 
853
904
  // src/get-from-api.ts
854
905
  var getOriginalFetch = () => globalThis.fetch;
@@ -858,16 +909,28 @@ var getFromApi = async ({
858
909
  successfulResponseHandler,
859
910
  failedResponseHandler,
860
911
  abortSignal,
861
- fetch = getOriginalFetch()
912
+ fetch,
913
+ validateUrl,
914
+ credentialedOrigin,
915
+ trustedOrigin
862
916
  }) => {
863
917
  try {
864
- const response = await fetch(url, {
918
+ const requestFetch = fetch != null ? fetch : getOriginalFetch();
919
+ const outgoingHeaders = credentialedOrigin !== void 0 && !isSameOrigin(url, credentialedOrigin) ? {} : headers;
920
+ const requestHeaders = withUserAgentSuffix(
921
+ outgoingHeaders,
922
+ `ai-sdk/provider-utils/${VERSION}`,
923
+ getRuntimeEnvironmentUserAgent()
924
+ );
925
+ const response = validateUrl ? await fetchWithValidatedRedirects({
926
+ url,
927
+ headers: requestHeaders,
928
+ abortSignal,
929
+ fetch,
930
+ trustedOrigin
931
+ }) : await requestFetch(url, {
865
932
  method: "GET",
866
- headers: withUserAgentSuffix(
867
- headers,
868
- `ai-sdk/provider-utils/${VERSION}`,
869
- getRuntimeEnvironmentUserAgent()
870
- ),
933
+ headers: requestHeaders,
871
934
  signal: abortSignal
872
935
  });
873
936
  const responseHeaders = extractResponseHeaders(response);
@@ -3524,6 +3587,7 @@ export {
3524
3587
  delay,
3525
3588
  downloadBlob,
3526
3589
  dynamicTool,
3590
+ encodePathSegment,
3527
3591
  executeTool,
3528
3592
  extractResponseHeaders,
3529
3593
  fetchWithValidatedEndpoint,