diff --git a/backend/src/app.js b/backend/src/app.js index e0eec60..b6c1bf2 100644 --- a/backend/src/app.js +++ b/backend/src/app.js @@ -328,19 +328,44 @@ if (fs.existsSync(frontendDistPath)) { }); } - // If the request is HTTPS (via reverse proxy), rewrite HTTP asset URLs to HTTPS - // This fixes mixed content issues - const protocol = req.protocol; // Will be 'https' if X-Forwarded-Proto is set correctly + // Rewrite relative asset URLs to absolute URLs based on request protocol + // This fixes mixed content issues when page is loaded via HTTPS but assets are relative + // Check X-Forwarded-Proto first (set by reverse proxy), then fall back to req.protocol + const forwardedProto = req.get('X-Forwarded-Proto'); + const protocol = forwardedProto || req.protocol; // Prefer X-Forwarded-Proto from reverse proxy + const forwardedHost = req.get('X-Forwarded-Host') || req.get('host'); + const baseUrl = `${protocol}://${forwardedHost}`; + + logger.info(`HTML rewrite: protocol=${protocol}, host=${forwardedHost}, baseUrl=${baseUrl}`); + + // Replace relative URLs (starting with /) in src and href attributes with absolute URLs + // This ensures assets are loaded with the same protocol as the page + html = html.replace(/src="\/([^"]+)"/g, (match, path) => { + // Only rewrite asset paths, not API paths + if (path.startsWith('assets/') || path.startsWith('vite.svg') || path.match(/\.(js|css|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot)$/)) { + return `src="${baseUrl}/${path}"`; + } + return match; + }); + + html = html.replace(/href="\/([^"]+)"/g, (match, path) => { + // Only rewrite asset paths, not API paths + if (path.startsWith('assets/') || path.startsWith('vite.svg') || path.match(/\.(css|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot)$/)) { + return `href="${baseUrl}/${path}"`; + } + return match; + }); + + // Also replace any absolute HTTP URLs with HTTPS if request is HTTPS if (protocol === 'https') { - // Replace absolute HTTP URLs with HTTPS (but keep relative URLs as-is) html = html.replace(/href="http:\/\/([^"]+)"/g, (match, url) => { - if (url.includes(req.get('host'))) { + if (url.includes(host)) { return `href="https://${url}"`; } return match; }); html = html.replace(/src="http:\/\/([^"]+)"/g, (match, url) => { - if (url.includes(req.get('host'))) { + if (url.includes(host)) { return `src="https://${url}"`; } return match;