/** * imageProxy.ts * * Utility function to proxy external image URLs through the backend * to avoid hotlinking issues and blocked images. * * Many institution websites and image hosts block direct embedding * (hotlinking) of their images. This utility routes image requests * through our backend proxy which fetches the image server-side. */ /** * Convert an external image URL to use the backend image proxy. * * The proxy endpoint caches images for 1 hour and adds appropriate * headers to bypass hotlink detection. * * @param url - The external image URL to proxy * @returns Proxied URL via /api/geo/image-proxy, or the original URL if local * * @example * // External image - will be proxied * proxyImageUrl('https://example.com/logo.png') * // Returns: '/api/geo/image-proxy?url=https%3A%2F%2Fexample.com%2Flogo.png' * * // Local image - returned as-is * proxyImageUrl('/images/local-logo.png') * // Returns: '/images/local-logo.png' * * // Data URL - returned as-is * proxyImageUrl('data:image/png;base64,...') * // Returns: 'data:image/png;base64,...' */ export function proxyImageUrl(url: string | undefined | null): string | undefined { // Return undefined for null/undefined if (!url) return undefined; // Don't proxy local URLs (relative paths) if (url.startsWith('/')) return url; // Don't proxy data URLs (inline base64 images) if (url.startsWith('data:')) return url; // Don't proxy blob URLs if (url.startsWith('blob:')) return url; // Proxy all other (external) URLs return `/api/geo/image-proxy?url=${encodeURIComponent(url)}`; } /** * Check if a URL is an external URL that would benefit from proxying. * * @param url - URL to check * @returns true if external, false if local/data/blob */ export function isExternalUrl(url: string | undefined | null): boolean { if (!url) return false; if (url.startsWith('/')) return false; if (url.startsWith('data:')) return false; if (url.startsWith('blob:')) return false; return true; } export default proxyImageUrl;