const fs = require("fs"); const http = require("http"); const path = require("path"); const root = path.resolve(__dirname, ".."); const port = Number(process.env.PORT || process.env.CONFIG_SMS_FRIEND_BRIDGE_PORT || 5174); function normalizeText(value) { return typeof value === "string" ? value.trim() : value ? String(value).trim() : ""; } function parseEnvValue(value) { const text = normalizeText(value); if ( (text.startsWith('"') && text.endsWith('"')) || (text.startsWith("'") && text.endsWith("'")) ) { return text.slice(1, -1); } return text; } function loadEnvFile(fileName) { const filePath = path.join(root, fileName); if (!fs.existsSync(filePath)) return {}; const env = {}; const content = fs.readFileSync(filePath, "utf8"); for (const line of content.split(/\r?\n/)) { const trimmed = line.trim(); if (!trimmed || trimmed.startsWith("#")) continue; const index = trimmed.indexOf("="); if (index <= 0) continue; env[trimmed.slice(0, index).trim()] = parseEnvValue(trimmed.slice(index + 1)); } return env; } const fileEnv = { ...loadEnvFile(".env"), ...loadEnvFile(".env.development"), }; const mimeTypes = { ".html": "text/html; charset=utf-8", ".css": "text/css; charset=utf-8", ".js": "application/javascript; charset=utf-8", ".json": "application/json; charset=utf-8", ".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".svg": "image/svg+xml", }; function sendText(res, text, contentType) { res.writeHead(200, { "Content-Type": contentType, }); res.end(text); } function sendFile(res, filePath) { const ext = path.extname(filePath); res.writeHead(200, { "Content-Type": mimeTypes[ext] || "application/octet-stream", }); fs.createReadStream(filePath).pipe(res); } function resolveAssetPath(urlPath) { const cleanPath = decodeURIComponent(urlPath.split("?")[0]); const assetPath = cleanPath.replace(/^\/sms\//, "/"); const candidate = path.resolve(root, assetPath.replace(/^\/+/, "")); if (!candidate.startsWith(root)) return ""; return candidate; } const server = http.createServer((req, res) => { const urlPath = (req.url || "/").split("?")[0]; if (urlPath === "/config.js" || urlPath === "/sms/config.js") { const apiBase = process.env.api_url || fileEnv.api_url || ""; sendText( res, `window.api_url=${JSON.stringify(apiBase)};\n`, "application/javascript; charset=utf-8", ); return; } const assetPath = resolveAssetPath(req.url || "/"); if (assetPath && fs.existsSync(assetPath) && fs.statSync(assetPath).isFile()) { sendFile(res, assetPath); return; } sendFile(res, path.join(root, "index.html")); }); server.listen(port, () => { console.log(`Friend bridge H5 running at http://localhost:${port}/sms/{id}`); });