All checks were successful
Build & Deploy / 🔍 Prepare (push) Successful in 12s
Build & Deploy / 🧪 QA (push) Successful in 1m54s
Build & Deploy / 🏗️ Build (push) Successful in 7m44s
Build & Deploy / 🚀 Deploy (push) Successful in 30s
Build & Deploy / 🧪 Smoke Test (push) Successful in 1m2s
Build & Deploy / ⚡ Lighthouse (push) Successful in 3m17s
Build & Deploy / 🔔 Notify (push) Successful in 1s
73 lines
2.4 KiB
TypeScript
73 lines
2.4 KiB
TypeScript
/**
|
|
* 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:<type>:<width>:<height>:<enlarge>/g:<gravity>
|
|
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}`;
|
|
}
|