mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-01-12 00:28:31 -05:00
Compare commits
6 Commits
dev
...
fix/proxy-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c6c539e48e | ||
|
|
8bbd2a8125 | ||
|
|
5b4ce4c93f | ||
|
|
1210e8ef04 | ||
|
|
dc84b777c0 | ||
|
|
bed812d7a5 |
@@ -1,23 +1,5 @@
|
||||
import { FC, useEffect, useMemo, useState } from "react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import SchemaTooltip from "@/components/SchemaTooltip";
|
||||
import useCredentials from "@/hooks/useCredentials";
|
||||
import { NotionLogoIcon } from "@radix-ui/react-icons";
|
||||
import {
|
||||
FaDiscord,
|
||||
FaGithub,
|
||||
FaTwitter,
|
||||
FaGoogle,
|
||||
FaMedium,
|
||||
FaKey,
|
||||
FaHubspot,
|
||||
} from "react-icons/fa";
|
||||
import {
|
||||
BlockIOCredentialsSubSchema,
|
||||
CredentialsMetaInput,
|
||||
CredentialsProviderName,
|
||||
} from "@/lib/autogpt-server-api/types";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { IconKey, IconKeyPlus, IconUserPlus } from "@/components/ui/icons";
|
||||
import {
|
||||
Select,
|
||||
@@ -27,12 +9,30 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import useCredentials from "@/hooks/useCredentials";
|
||||
import { useBackendAPI } from "@/lib/autogpt-server-api/context";
|
||||
import {
|
||||
BlockIOCredentialsSubSchema,
|
||||
CredentialsMetaInput,
|
||||
CredentialsProviderName,
|
||||
} from "@/lib/autogpt-server-api/types";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { getHostFromUrl } from "@/lib/utils/url";
|
||||
import { NotionLogoIcon } from "@radix-ui/react-icons";
|
||||
import { FC, useEffect, useMemo, useState } from "react";
|
||||
import {
|
||||
FaDiscord,
|
||||
FaGithub,
|
||||
FaGoogle,
|
||||
FaHubspot,
|
||||
FaKey,
|
||||
FaMedium,
|
||||
FaTwitter,
|
||||
} from "react-icons/fa";
|
||||
import { APIKeyCredentialsModal } from "./api-key-credentials-modal";
|
||||
import { UserPasswordCredentialsModal } from "./user-password-credentials-modal";
|
||||
import { HostScopedCredentialsModal } from "./host-scoped-credentials-modal";
|
||||
import { OAuth2FlowWaitingModal } from "./oauth2-flow-waiting-modal";
|
||||
import { getHostFromUrl } from "@/lib/utils/url";
|
||||
import { UserPasswordCredentialsModal } from "./user-password-credentials-modal";
|
||||
|
||||
const fallbackIcon = FaKey;
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ import { getWebSocketToken } from "@/lib/supabase/actions";
|
||||
import { getServerSupabase } from "@/lib/supabase/server/getServerSupabase";
|
||||
import { createBrowserClient } from "@supabase/ssr";
|
||||
import type { SupabaseClient } from "@supabase/supabase-js";
|
||||
import { proxyApiRequest, proxyFileUpload } from "./proxy-action";
|
||||
import type {
|
||||
AddUserCreditsResponse,
|
||||
AnalyticsDetails,
|
||||
@@ -27,6 +26,7 @@ import type {
|
||||
GraphID,
|
||||
GraphMeta,
|
||||
GraphUpdateable,
|
||||
HostScopedCredentials,
|
||||
LibraryAgent,
|
||||
LibraryAgentID,
|
||||
LibraryAgentPreset,
|
||||
@@ -62,7 +62,6 @@ import type {
|
||||
User,
|
||||
UserOnboarding,
|
||||
UserPasswordCredentials,
|
||||
HostScopedCredentials,
|
||||
UsersBalanceHistoryResponse,
|
||||
} from "./types";
|
||||
|
||||
@@ -521,8 +520,6 @@ export default class BackendAPI {
|
||||
}
|
||||
|
||||
uploadStoreSubmissionMedia(file: File): Promise<string> {
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
return this._uploadFile("/store/submissions/media", file);
|
||||
}
|
||||
|
||||
@@ -813,8 +810,48 @@ export default class BackendAPI {
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
|
||||
// Use proxy server action for secure file upload
|
||||
return await proxyFileUpload(path, formData, this.baseUrl);
|
||||
if (isClient) {
|
||||
return this._makeClientFileUpload(path, formData);
|
||||
} else {
|
||||
return this._makeServerFileUpload(path, formData);
|
||||
}
|
||||
}
|
||||
|
||||
private async _makeClientFileUpload(
|
||||
path: string,
|
||||
formData: FormData,
|
||||
): Promise<string> {
|
||||
// Dynamic import is required even for client-only functions because helpers.ts
|
||||
// has server-only imports (like getServerSupabase) at the top level. Static imports
|
||||
// would bundle server-only code into the client bundle, causing runtime errors.
|
||||
const { buildClientUrl, parseErrorResponse, handleFetchError } =
|
||||
await import("./helpers");
|
||||
|
||||
const uploadUrl = buildClientUrl(path);
|
||||
|
||||
const response = await fetch(uploadUrl, {
|
||||
method: "POST",
|
||||
body: formData,
|
||||
credentials: "include",
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await parseErrorResponse(response);
|
||||
throw handleFetchError(response, errorData);
|
||||
}
|
||||
|
||||
return await response.text();
|
||||
}
|
||||
|
||||
private async _makeServerFileUpload(
|
||||
path: string,
|
||||
formData: FormData,
|
||||
): Promise<string> {
|
||||
const { makeAuthenticatedFileUpload, buildServerUrl } = await import(
|
||||
"./helpers"
|
||||
);
|
||||
const url = buildServerUrl(path);
|
||||
return await makeAuthenticatedFileUpload(url, formData);
|
||||
}
|
||||
|
||||
private async _request(
|
||||
@@ -826,13 +863,62 @@ export default class BackendAPI {
|
||||
console.debug(`${method} ${path} payload:`, payload);
|
||||
}
|
||||
|
||||
// Always use proxy server action to not expose any auth tokens to the browser
|
||||
return await proxyApiRequest({
|
||||
if (isClient) {
|
||||
return this._makeClientRequest(method, path, payload);
|
||||
} else {
|
||||
return this._makeServerRequest(method, path, payload);
|
||||
}
|
||||
}
|
||||
|
||||
private async _makeClientRequest(
|
||||
method: string,
|
||||
path: string,
|
||||
payload?: Record<string, any>,
|
||||
) {
|
||||
// Dynamic import is required even for client-only functions because helpers.ts
|
||||
// has server-only imports (like getServerSupabase) at the top level. Static imports
|
||||
// would bundle server-only code into the client bundle, causing runtime errors.
|
||||
const {
|
||||
buildClientUrl,
|
||||
buildUrlWithQuery,
|
||||
parseErrorResponse,
|
||||
handleFetchError,
|
||||
} = await import("./helpers");
|
||||
|
||||
const payloadAsQuery = ["GET", "DELETE"].includes(method);
|
||||
let url = buildClientUrl(path);
|
||||
|
||||
if (payloadAsQuery && payload) {
|
||||
url = buildUrlWithQuery(url, payload);
|
||||
}
|
||||
|
||||
const response = await fetch(url, {
|
||||
method,
|
||||
path,
|
||||
payload,
|
||||
baseUrl: this.baseUrl,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: !payloadAsQuery && payload ? JSON.stringify(payload) : undefined,
|
||||
credentials: "include",
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await parseErrorResponse(response);
|
||||
throw handleFetchError(response, errorData);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
private async _makeServerRequest(
|
||||
method: string,
|
||||
path: string,
|
||||
payload?: Record<string, any>,
|
||||
) {
|
||||
const { makeAuthenticatedRequest, buildServerUrl } = await import(
|
||||
"./helpers"
|
||||
);
|
||||
const url = buildServerUrl(path);
|
||||
return await makeAuthenticatedRequest(method, url, payload);
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
@@ -29,6 +29,42 @@ export function buildRequestUrl(
|
||||
return url;
|
||||
}
|
||||
|
||||
export function buildClientUrl(path: string): string {
|
||||
return `/api/proxy/api${path}`;
|
||||
}
|
||||
|
||||
export function buildServerUrl(path: string): string {
|
||||
const baseUrl =
|
||||
process.env.NEXT_PUBLIC_AGPT_SERVER_URL || "http://localhost:8006/api";
|
||||
return `${baseUrl}${path}`;
|
||||
}
|
||||
|
||||
export function buildUrlWithQuery(
|
||||
url: string,
|
||||
payload?: Record<string, any>,
|
||||
): string {
|
||||
if (!payload) return url;
|
||||
|
||||
const queryParams = new URLSearchParams(payload);
|
||||
return `${url}?${queryParams.toString()}`;
|
||||
}
|
||||
|
||||
export function handleFetchError(response: Response, errorData: any): ApiError {
|
||||
return new ApiError(
|
||||
errorData?.error || "Request failed",
|
||||
response.status,
|
||||
errorData,
|
||||
);
|
||||
}
|
||||
|
||||
export async function parseErrorResponse(response: Response): Promise<any> {
|
||||
try {
|
||||
return await response.json();
|
||||
} catch {
|
||||
return { error: response.statusText };
|
||||
}
|
||||
}
|
||||
|
||||
export async function getServerAuthToken(): Promise<string> {
|
||||
const supabase = await getServerSupabase();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user