* Serve an HTML file with APP_CONFIG injected. * This ensures clean URL routes (like /membership) get the same config injection * as .html file requests handled by the middleware.
(req: express.Request, res: express.Response, htmlFile: string)
| 868 | * as .html file requests handled by the middleware. |
| 869 | */ |
| 870 | private async serveHtmlWithConfig(req: express.Request, res: express.Response, htmlFile: string): Promise<void> { |
| 871 | const publicPath = process.env.NODE_ENV === 'production' |
| 872 | ? path.join(__dirname, "../server/public") |
| 873 | : path.join(__dirname, "../public"); |
| 874 | const filePath = path.join(publicPath, htmlFile); |
| 875 | |
| 876 | try { |
| 877 | // Cross-domain session bridge for AdCP pages |
| 878 | if (this.bridgeIfNeeded(req, res)) return; |
| 879 | |
| 880 | // Get user from session (if authenticated), passing res to update cookie if session is refreshed |
| 881 | const user = await getUserFromRequest(req, res); |
| 882 | await enrichUserWithMembership(user); |
| 883 | await enrichUserWithAdmin(user); |
| 884 | |
| 885 | // Read and inject config |
| 886 | let html = await fs.readFile(filePath, 'utf-8'); |
| 887 | const configScript = getAppConfigScript(user); |
| 888 | |
| 889 | // Inject before </head> |
| 890 | if (html.includes('</head>')) { |
| 891 | html = html.replace('</head>', `${configScript}\n</head>`); |
| 892 | } else { |
| 893 | // Fallback: inject at start of body |
| 894 | html = html.replace('<body', `${configScript}\n<body`); |
| 895 | } |
| 896 | |
| 897 | res.setHeader('Content-Type', 'text/html'); |
| 898 | res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate'); |
| 899 | res.setHeader('Pragma', 'no-cache'); |
| 900 | res.setHeader('Expires', '0'); |
| 901 | res.send(html); |
| 902 | } catch (error) { |
| 903 | const nodeError = error as NodeJS.ErrnoException; |
| 904 | if (nodeError.code === 'ENOENT') { |
| 905 | logger.warn({ htmlFile }, 'HTML file not found'); |
| 906 | res.status(404).send('Not Found'); |
| 907 | } else { |
| 908 | logger.error({ error, htmlFile }, 'Failed to serve HTML with config'); |
| 909 | res.status(500).send('Internal Server Error'); |
| 910 | } |
| 911 | } |
| 912 | } |
| 913 | |
| 914 | private setupRoutes(): void { |
| 915 | // Authentication routes (only if configured) |
no test coverage detected