From 2f274df5f8e1aa6394ac4ea9f032850479bbfd91 Mon Sep 17 00:00:00 2001 From: Alexandre KIENTZ Date: Wed, 3 Dec 2025 21:10:55 +0100 Subject: [PATCH] first commit --- config.json | 4 ++-- server.js | 49 +++++++++++++++++++++++++++++++++++++++++ views/admin/index.ejs | 1 + views/admin/preview.ejs | 12 ++++++++++ 4 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 views/admin/preview.ejs diff --git a/config.json b/config.json index 1938590..5f0ac32 100644 --- a/config.json +++ b/config.json @@ -2,12 +2,12 @@ { "id": "radarr", "pathPrefix": "/radarr", - "upstream": "http://10.1.4.2:7878", + "upstream": "http://google.fr:7878", "oidc": { "issuer": "https://sso.leskientz.ovh/realms/master", "client_id": "proxyopenid", "client_secret": "biM7eaxeCrzI2OnAoVHOAWe1n2ptAdhz", - "redirect_uri": "https://secure.k2r.ovh/callback/app1" + "redirect_uri": "https://secure.k2r.ovh/callback/radarr" } } ] diff --git a/server.js b/server.js index 0119d5b..e1978e8 100644 --- a/server.js +++ b/server.js @@ -128,6 +128,55 @@ app.post('/admin/reload', ensureAdmin, async (req, res) => { } }); +// Admin preview page (iframe) — keep user on proxy domain while showing upstream +app.get('/admin/preview/:id', ensureAdmin, (req, res) => { + const host = HOSTS.find(h => h.id === req.params.id); + if (!host) return res.status(404).send('Not found'); + res.render('admin/preview', { host }); +}); + +// Proxy used by the preview iframe; strips headers that prevent embedding. +app.use('/preview-proxy/:id', ensureAdmin, (req, res, next) => { + const id = req.params.id; + const host = HOSTS.find(h => h.id === id); + if (!host) return res.status(404).send('Unknown host'); + + // Create a proxy middleware tailored to this host + const proxy = createProxyMiddleware({ + target: host.upstream, + changeOrigin: true, + selfHandleResponse: false, + proxyTimeout: 15000, + pathRewrite: (path, req2) => { + // path starts with /preview-proxy/:id + const prefix = `/preview-proxy/${id}`; + let newPath = path.replace(prefix, '') || '/'; + // ensure upstream receives the host's pathPrefix if configured + if (host.pathPrefix && host.pathPrefix !== '/') { + // avoid double slashes + newPath = host.pathPrefix.replace(/\/$/, '') + newPath; + } + return newPath; + }, + onProxyReq(proxyReq, req2, res2) { + // pass admin identity header for upstream if desired + if (req.session && req.session.isAdmin) proxyReq.setHeader('X-Admin-User', req.session.username || 'admin'); + }, + onProxyRes(proxyRes, req2, res2) { + // Remove headers that would prevent embedding in an iframe + try { + delete proxyRes.headers['x-frame-options']; + delete proxyRes.headers['x-content-security-policy']; + delete proxyRes.headers['content-security-policy']; + delete proxyRes.headers['frame-options']; + } catch (e) { + // ignore + } + } + }); + return proxy(req, res, next); +}); + // Load hosts configuration. If `config.json` exists, use it; otherwise fallback to UPSTREAM env. let HOSTS = []; const cfgPath = path.join(__dirname, 'config.json'); diff --git a/views/admin/index.ejs b/views/admin/index.ejs index 39b6db4..57284b6 100644 --- a/views/admin/index.ejs +++ b/views/admin/index.ejs @@ -25,6 +25,7 @@ <%= h.oidc ? 'yes' : 'no' %> Edit + Preview
diff --git a/views/admin/preview.ejs b/views/admin/preview.ejs new file mode 100644 index 0000000..1ba006b --- /dev/null +++ b/views/admin/preview.ejs @@ -0,0 +1,12 @@ + + + + + + Preview <%= host.id %> + + + + + +