summaryrefslogtreecommitdiff
path: root/packages/core/src/utils/fetch.ts
diff options
context:
space:
mode:
authorAllen Hutchison <[email protected]>2025-06-13 17:44:14 -0700
committerGitHub <[email protected]>2025-06-13 17:44:14 -0700
commit31b28ade010711c578d4be58c0dc439badebe000 (patch)
treecdddcfb73285697dc9d1a79363f52f07ccaa63e1 /packages/core/src/utils/fetch.ts
parent8eb505fbba664d32c4f5ed94485cc219f2db3e20 (diff)
Improvements to web-fetch tool (#1030)
Diffstat (limited to 'packages/core/src/utils/fetch.ts')
-rw-r--r--packages/core/src/utils/fetch.ts57
1 files changed, 57 insertions, 0 deletions
diff --git a/packages/core/src/utils/fetch.ts b/packages/core/src/utils/fetch.ts
new file mode 100644
index 00000000..e78a3247
--- /dev/null
+++ b/packages/core/src/utils/fetch.ts
@@ -0,0 +1,57 @@
+/**
+ * @license
+ * Copyright 2025 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { getErrorMessage, isNodeError } from './errors.js';
+import { URL } from 'url';
+
+const PRIVATE_IP_RANGES = [
+ /^10\./,
+ /^127\./,
+ /^172\.(1[6-9]|2[0-9]|3[0-1])\./,
+ /^192\.168\./,
+ /^::1$/,
+ /^fc00:/,
+ /^fe80:/,
+];
+
+export class FetchError extends Error {
+ constructor(
+ message: string,
+ public code?: string,
+ ) {
+ super(message);
+ this.name = 'FetchError';
+ }
+}
+
+export function isPrivateIp(url: string): boolean {
+ try {
+ const hostname = new URL(url).hostname;
+ return PRIVATE_IP_RANGES.some((range) => range.test(hostname));
+ } catch (_e) {
+ return false;
+ }
+}
+
+export async function fetchWithTimeout(
+ url: string,
+ timeout: number,
+): Promise<Response> {
+ const controller = new AbortController();
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
+
+ try {
+ const response = await fetch(url, { signal: controller.signal });
+ return response;
+ } catch (error) {
+ if (isNodeError(error) && error.code === 'ABORT_ERR') {
+ throw new FetchError(`Request timed out after ${timeout}ms`, 'ETIMEDOUT');
+ }
+ throw new FetchError(getErrorMessage(error));
+ } finally {
+ clearTimeout(timeoutId);
+ }
+}