/** * Generates an imgproxy URL for a given source image and options. * * Documentation: https://docs.imgproxy.net/usage/processing */ interface ImgproxyOptions { width?: number; height?: number; resizing_type?: 'fit' | 'fill' | 'fill-down' | 'force' | 'auto'; gravity?: string; enlarge?: boolean; extension?: string; } export function getImgproxyUrl(src: string, options: ImgproxyOptions = {}): string { // Use local proxy path which is rewritten in next.config.mjs const baseUrl = '/_img'; // Handle local paths or relative URLs let absoluteSrc = src; if (src.startsWith('/')) { const baseUrlForSrc = process.env.NEXT_PUBLIC_BASE_URL || (typeof window !== 'undefined' ? window.location.origin : 'https://klz-cables.com'); if (baseUrlForSrc) { absoluteSrc = `${baseUrlForSrc.replace(/\/$/, '')}${src}`; } } // Development mapping: Map local domains to internal Docker hostnames // so imgproxy can fetch images without SSL issues or external routing if (process.env.NODE_ENV === 'development') { if (absoluteSrc.includes('klz.localhost')) { absoluteSrc = absoluteSrc.replace(/^https?:\/\/klz\.localhost/, 'http://klz-app:3000'); } else if (absoluteSrc.includes('cms.klz.localhost')) { absoluteSrc = absoluteSrc.replace(/^https?:\/\/cms\.klz\.localhost/, 'http://klz-cms:8055'); } // Also handle direct container names if needed } const { width = 0, height = 0, resizing_type = 'fit', gravity = 'sm', // Default to smart gravity enlarge = false, extension = '', } = options; // Processing options // Format: /rs::::/g: const processingOptions = [ `rs:${resizing_type}:${width}:${height}:${enlarge ? 1 : 0}`, `g:${gravity}`, ].join('/'); // Using Base64 encoding for the source URL. // This completely eliminates any risk of intermediate proxies (Traefik/Next.js) // URL-decoding the path, which corrupts the double-slash (// to /) and causes 403 errors. // Imgproxy expects URL-safe Base64 (RFC 4648) without padding. const b64 = typeof window === 'undefined' ? Buffer.from(absoluteSrc).toString('base64') : btoa(unescape(encodeURIComponent(absoluteSrc))); const urlSafeB64 = b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, ''); const suffix = extension ? `.${extension}` : ''; return `${baseUrl}/unsafe/${processingOptions}/${urlSafeB64}${suffix}`; }