const http = require('http'); const httpProxy = require('http-proxy'); const fs = require('fs'); const path = require('path'); const APP_URL = process.env.MAIN_URL || "http://localhost:3000"; const UPLOAD_DIR = process.env.UPLOAD_DIRECTORY || "/app/uploads"; // ------------------------------------------------------------------- // DÉTECTION DYNAMIQUE DU DOSSIER STATIC (Vérifié pour Hugging Face) // ------------------------------------------------------------------- const possiblePaths = [ path.join(__dirname, 'app', 'static'), path.join(__dirname, 'static'), '/app/app/static', '/app/static' ]; let foundPath = ''; for (const p of possiblePaths) { try { if (fs.existsSync(p) && fs.readdirSync(p).includes('terms.html')) { foundPath = p; break; } } catch (e) { // Dossier non accessible ou n'existe pas } } const STATIC_DIR = foundPath || possiblePaths[0]; // ------------------------------------------------------------------- // MVEMBA SYSTEM CONFIGURATION: PROXY v5.2.1 (Fix Double Declaration) // ------------------------------------------------------------------- const proxyOptions = { ws: true, xfwd: true, cookieDomainRewrite: "", secure: false, changeOrigin: true }; const backendProxy = httpProxy.createProxyServer({ target: 'http://127.0.0.1:4000', ...proxyOptions }); const frontendProxy = httpProxy.createProxyServer({ target: 'http://127.0.0.1:4200', ...proxyOptions }); const errorHandler = (err, req, res) => { console.error(`[ERROR] ${new Date().toISOString()} : ${err.message}`); if (!res.headersSent) { res.writeHead(500, { 'Content-Type': 'text/plain' }); res.end('MVEMBA_SYSTEM: Service temporarily unavailable.'); } }; backendProxy.on('error', errorHandler); frontendProxy.on('error', errorHandler); const setCacheHeaders = (res, ext) => { const oneDay = 24 * 60 * 60; if (['.mp4', '.webm', '.mov'].includes(ext)) { res.setHeader('Cache-Control', `public, max-age=${oneDay}`); } else { res.setHeader('Cache-Control', 'no-cache'); } }; const serveStaticFile = (res, filePath, contentType = 'text/html') => { if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) { res.writeHead(200, { 'Content-Type': contentType }); fs.createReadStream(filePath).pipe(res); } else { console.error(`[404] File not found at: ${filePath}`); res.writeHead(404); res.end('File not found'); } }; // ------------------------------------------------------------------- // HTTP SERVER // ------------------------------------------------------------------- const server = http.createServer((req, res) => { // TikTok Domain Verification if (req.url === '/tiktokPNM40yS7EF2dkzSNfJclFifdnpalsOMm.txt') { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('tiktok-developers-site-verification=PNM40yS7EF2dkzSNfJclFifdnpalsOMm'); return; } // Static pages if (req.url === '/privacy') return serveStaticFile(res, path.join(STATIC_DIR, 'privacy.html')); if (req.url === '/terms') return serveStaticFile(res, path.join(STATIC_DIR, 'terms.html')); if (req.url === '/deletion') return serveStaticFile(res, path.join(STATIC_DIR, 'deletion.html')); req.headers['x-forwarded-proto'] = 'https'; req.headers['x-forwarded-port'] = '443'; if (req.headers.host) req.headers['x-forwarded-host'] = req.headers.host; if (req.url.startsWith('/uploads/')) { const filePath = path.join(UPLOAD_DIR, decodeURIComponent(req.url.replace('/uploads/', ''))); if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) { setCacheHeaders(res, path.extname(filePath)); fs.createReadStream(filePath).pipe(res); return; } else { res.writeHead(404); res.end('File not found'); return; } } if (req.url.startsWith('/api') || req.url.startsWith('/public') || req.url.startsWith('/webhooks') || req.url.startsWith('/v1')) { if (req.url.startsWith('/api')) req.url = req.url.replace(/^\/api/, '') || '/'; backendProxy.web(req, res); } else { frontendProxy.web(req, res); } }); server.on('upgrade', (req, socket, head) => { if (req.url.startsWith('/api') || req.url.startsWith('/socket.io')) { if (req.url.startsWith('/api')) req.url = req.url.replace(/^\/api/, '') || '/'; backendProxy.ws(req, socket, head); } else { frontendProxy.ws(req, socket, head); } }); server.listen(3000, () => { console.log('------------------------------------------------------------'); console.log('[STATUS] MVEMBA SECURE PROXY ENGINE v5.2.1 DEPLOYED'); if (foundPath) { console.log(`[SUCCESS] Static files matched at: ${STATIC_DIR}`); } else { console.log(`[WARNING] Static directory not confirmed, using: ${STATIC_DIR}`); } console.log(`[TARGET] ${APP_URL}`); console.log('------------------------------------------------------------'); });