| /** | |
| * Helper functions for API calls | |
| * Handles both server-side and client-side URL construction | |
| * | |
| * IMPORTANT: We cannot import 'next/headers' at top level because it breaks client-side usage. | |
| * We use dynamic import only when needed on server-side. | |
| */ | |
| /** | |
| * Get the base URL for API calls | |
| * For server-side, we need absolute URLs | |
| * For client-side, we can use relative URLs | |
| */ | |
| export async function getApiBaseUrl(): Promise<string> { | |
| // Server-side: need absolute URL | |
| if (typeof window === 'undefined') { | |
| try { | |
| // Dynamically import headers only when server-side (avoids client-side import error) | |
| const { headers } = await import('next/headers'); | |
| const headersList = await headers(); | |
| const host = headersList.get('host'); | |
| const protocol = headersList.get('x-forwarded-proto') || 'https'; | |
| if (host) { | |
| return `${protocol}://${host}`; | |
| } | |
| } catch (error) { | |
| // headers() might not be available in all contexts (e.g., during build) | |
| // Fall through to environment variables | |
| } | |
| // Fallback: try environment variables | |
| const spaceUrl = | |
| process.env.SPACE_URL || | |
| process.env.NEXT_PUBLIC_APP_URL || | |
| process.env.VERCEL_URL || | |
| process.env.HF_SPACE_URL; | |
| if (spaceUrl) { | |
| // Ensure it has protocol | |
| if (spaceUrl.startsWith('http://') || spaceUrl.startsWith('https://')) { | |
| // Remove trailing slash | |
| return spaceUrl.endsWith('/') ? spaceUrl.slice(0, -1) : spaceUrl; | |
| } | |
| return `https://${spaceUrl}`; | |
| } | |
| // Last resort: use relative URL (Next.js should handle this for same-origin) | |
| return ''; | |
| } | |
| // Client-side: use relative URL (empty string) | |
| return ''; | |
| } | |
| /** | |
| * Build proxy URL for Hugging Face requests | |
| * Automatically handles server-side vs client-side | |
| * Note: This is async because getApiBaseUrl() is async (needed for server-side) | |
| */ | |
| export async function buildProxyUrl(targetUrl: string): Promise<string> { | |
| const apiBase = await getApiBaseUrl(); | |
| const encodedUrl = encodeURIComponent(targetUrl); | |
| return `${apiBase}/api/hf-proxy?url=${encodedUrl}`; | |
| } | |