105 lines
2.9 KiB
JavaScript
105 lines
2.9 KiB
JavaScript
const express = require('express');
|
|
const cors = require('cors');
|
|
const path = require('path');
|
|
const fs = require('fs').promises;
|
|
const { createProxyMiddleware, fixRequestBody } = require('http-proxy-middleware');
|
|
const app = express();
|
|
|
|
app.use(cors());
|
|
app.use(express.json()); // Add JSON body parser
|
|
|
|
// Helpers
|
|
function normalizeUrl(u) {
|
|
try {
|
|
return new URL(u);
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Env-configurable allowed origins for proxying
|
|
const RAW_ALLOWED = process.env.ALLOWED_PROXY_ORIGINS || '*';
|
|
const ALLOW_ANY = RAW_ALLOWED.trim() === '*';
|
|
const allowedOrigins = ALLOW_ANY
|
|
? ['*']
|
|
: RAW_ALLOWED.split(',')
|
|
.map((s) => s.trim())
|
|
.filter(Boolean);
|
|
|
|
if (ALLOW_ANY) {
|
|
console.log('[proxy] ALLOWED_PROXY_ORIGINS="*" (allow any http/https target)');
|
|
} else {
|
|
console.log('[proxy] Allowed proxy origins:', allowedOrigins);
|
|
}
|
|
|
|
// Generic proxy endpoint
|
|
app.use(
|
|
'/proxy',
|
|
(req, res, next) => {
|
|
const targetUrlString = req.get('x-proxy-target');
|
|
if (!targetUrlString) {
|
|
return res.status(400).send('Missing x-proxy-target header');
|
|
}
|
|
|
|
const targetUrl = normalizeUrl(targetUrlString);
|
|
if (!targetUrl) {
|
|
return res.status(400).send('Invalid x-proxy-target URL');
|
|
}
|
|
|
|
if (!ALLOW_ANY && !allowedOrigins.includes(targetUrl.origin)) {
|
|
return res.status(403).send(`Proxy target origin "${targetUrl.origin}" not allowed.`);
|
|
}
|
|
|
|
// Pass the full URL to the proxy middleware
|
|
req._proxyTarget = targetUrlString;
|
|
next();
|
|
},
|
|
createProxyMiddleware({
|
|
router: (req) => new URL(req._proxyTarget).origin,
|
|
changeOrigin: true,
|
|
pathRewrite: (_path, req) => {
|
|
const targetUrl = new URL(req._proxyTarget);
|
|
return `${targetUrl.pathname}${targetUrl.search}`;
|
|
},
|
|
secure: false,
|
|
logLevel: 'debug',
|
|
onProxyReq: fixRequestBody, // Fixes body for POST/PUT requests
|
|
})
|
|
);
|
|
|
|
// API endpoint to save config
|
|
app.post('/api/save-config', async (req, res) => {
|
|
try {
|
|
const configPath = path.join(__dirname, 'main_web/src/assets/config.json');
|
|
const configData = JSON.stringify(req.body, null, 2);
|
|
|
|
await fs.writeFile(configPath, configData, 'utf8');
|
|
|
|
console.log('Config saved successfully to:', configPath);
|
|
res.json({ success: true, message: 'Configuration saved successfully' });
|
|
} catch (error) {
|
|
console.error('Error saving config:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
message: 'Failed to save configuration',
|
|
error: error.message
|
|
});
|
|
}
|
|
});
|
|
|
|
const distPath = path.join(__dirname, 'dist');
|
|
app.use(express.static(distPath));
|
|
|
|
// Simple health check
|
|
app.get('/__health', (req, res) => res.json({ ok: true }));
|
|
|
|
// SPA fallback
|
|
app.get('*', (req, res) => {
|
|
res.sendFile(path.join(distPath, 'index.html'));
|
|
});
|
|
|
|
const port = process.env.PORT || 8080;
|
|
app.listen(port, () => {
|
|
console.log(`Server running on http://localhost:${port}`);
|
|
});
|