From 8a7247d80c7450e1fb21eb0b8b501dbe31933ee9 Mon Sep 17 00:00:00 2001 From: Marc Mintel Date: Thu, 19 Feb 2026 15:07:20 +0100 Subject: [PATCH] fix(imgproxy): switch from base64 to plain URL format Use plain/ source URL format instead of base64 encoding. Base64 was causing 404 errors from imgproxy. Plain format verified working via direct curl tests. --- docker-compose.yml | 3 +-- lib/imgproxy.ts | 24 ++++-------------------- 2 files changed, 5 insertions(+), 22 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index ad1c9887..7b97e2c5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -32,7 +32,7 @@ services: - "traefik.http.routers.${PROJECT_NAME:-klz}.middlewares=${AUTH_MIDDLEWARE:-klz-ratelimit,klz-forward,klz-compress}" # Public Router (Whitelist for OG Images, Sitemaps, Health) - - "traefik.http.routers.${PROJECT_NAME:-klz}-public.rule=(${TRAEFIK_HOST_RULE:-Host(`${TRAEFIK_HOST:-klz-cables.com}`)}) && (PathPrefix(`/health`) || PathPrefix(`/sitemap.xml`) || PathPrefix(`/robots.txt`) || PathPrefix(`/manifest.webmanifest`) || PathPrefix(`/_img`) || PathPrefix(`/api/og`) || PathPrefix(`/de/api/og`) || PathPrefix(`/en/api/og`) || PathPrefix(`/opengraph-image`) || PathPrefix(`/de/opengraph-image`) || PathPrefix(`/en/opengraph-image`) || PathPrefix(`/blog/opengraph-image`) || PathPrefix(`/de/blog/opengraph-image`) || PathPrefix(`/en/blog/opengraph-image`) || PathRegexp(`^/sitemap(-[0-9]+)?\\.xml$`) || PathRegexp(`^/.*\\.(svg|png|jpg|jpeg|gif|webp|ico)$`))" + - "traefik.http.routers.${PROJECT_NAME:-klz}-public.rule=(${TRAEFIK_HOST_RULE:-Host(`${TRAEFIK_HOST:-klz-cables.com}`)}) && (PathPrefix(`/health`) || PathPrefix(`/sitemap.xml`) || PathPrefix(`/robots.txt`) || PathPrefix(`/manifest.webmanifest`) || PathPrefix(`/_img`) || PathPrefix(`/api/og`) || PathPrefix(`/de/api/og`) || PathPrefix(`/en/api/og`) || PathPrefix(`/logo-white.svg`) || PathPrefix(`/icon-white.svg`) || PathPrefix(`/opengraph-image`) || PathPrefix(`/de/opengraph-image`) || PathPrefix(`/en/opengraph-image`) || PathPrefix(`/blog/opengraph-image`) || PathPrefix(`/de/blog/opengraph-image`) || PathPrefix(`/en/blog/opengraph-image`) || PathRegexp(`^/sitemap(-[0-9]+)?\\.xml$`) || PathRegexp(`.*\\.(svg|png|jpg|jpeg|gif|webp|ico)$`))" - "traefik.http.routers.${PROJECT_NAME:-klz}-public.entrypoints=${TRAEFIK_ENTRYPOINT:-web}" - "traefik.http.routers.${PROJECT_NAME:-klz}-public.tls.certresolver=${TRAEFIK_CERT_RESOLVER:-}" - "traefik.http.routers.${PROJECT_NAME:-klz}-public.tls=${TRAEFIK_TLS:-false}" @@ -168,7 +168,6 @@ services: IMGPROXY_URL_MAPPING: "${IMGPROXY_URL_MAPPING:-http://klz.localhost/:http://klz-app:3000/,http://cms.klz.localhost/:http://klz-cms:8055/}" IMGPROXY_USE_ETAG: "true" IMGPROXY_MAX_SRC_RESOLUTION: 20 - IMGPROXY_ALLOWED_NETWORKS: "10.0.0.0/8,172.16.0.0/12,192.168.0.0/16" IMGPROXY_IGNORE_SSL_ERRORS: "true" IMGPROXY_DEBUG: "true" labels: diff --git a/lib/imgproxy.ts b/lib/imgproxy.ts index cebb4364..1ae07ab6 100644 --- a/lib/imgproxy.ts +++ b/lib/imgproxy.ts @@ -13,22 +13,6 @@ interface ImgproxyOptions { extension?: string; } -/** - * Encodes a string to Base64 (URL-safe) - */ -function encodeBase64(str: string): string { - if (typeof Buffer !== 'undefined') { - return Buffer.from(str) - .toString('base64') - .replace(/\+/g, '-') - .replace(/\//g, '_') - .replace(/=+$/, ''); - } else { - // Fallback for browser environment if Buffer is not available - return window.btoa(str).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); - } -} - export function getImgproxyUrl(src: string, options: ImgproxyOptions = {}): string { // Use local proxy path which is rewritten in next.config.mjs const baseUrl = '/_img'; @@ -71,10 +55,10 @@ export function getImgproxyUrl(src: string, options: ImgproxyOptions = {}): stri `g:${gravity}`, ].join('/'); - // Using /unsafe/ for now as we don't handle signatures yet - // Format: /unsafe// + // Using /unsafe/ with plain/ source URL format + // plain/ format works reliably with imgproxy URL mapping + // Format: /unsafe//plain/[@] const suffix = extension ? `@${extension}` : ''; - const encodedSrc = encodeBase64(absoluteSrc + suffix); - return `${baseUrl}/unsafe/${processingOptions}/${encodedSrc}`; + return `${baseUrl}/unsafe/${processingOptions}/plain/${absoluteSrc}${suffix}`; }