diff --git a/public/iframe.html b/public/iframe.html
new file mode 100644
index 0000000..93638c6
--- /dev/null
+++ b/public/iframe.html
@@ -0,0 +1,135 @@
+
+
+
+
+
+Авторизация и регистрация
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/server.js b/server.js
index 542c733..b86feb5 100644
--- a/server.js
+++ b/server.js
@@ -137,4 +137,44 @@ app.post('/api/chat', async (req, res) => {
}
});
+// ── iframe proxy: fetch student.sechenov.ru, strip X-Frame-Options, rewrite URLs ──
+app.get('/proxy/*', async (req, res) => {
+ const upstreamPath = req.url.replace(/^\/proxy/, '') || '/';
+ const upstreamUrl = 'https://student.sechenov.ru' + upstreamPath;
+
+ try {
+ const r = await fetch(upstreamUrl, {
+ headers: {
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
+ 'Accept': req.headers.accept || '*/*',
+ 'Accept-Language': req.headers['accept-language'] || 'ru,en;q=0.9',
+ },
+ });
+
+ const ct = r.headers.get('content-type') || 'application/octet-stream';
+ res.status(r.status);
+ res.setHeader('Content-Type', ct);
+ // strip framing restrictions
+ res.removeHeader('X-Frame-Options');
+ res.removeHeader('Content-Security-Policy');
+
+ if (ct.includes('text/html')) {
+ let html = await r.text();
+ // rewrite relative URLs to absolute so browser loads assets directly
+ html = html
+ .replace(/(href|src|action)="\/(?!\/)/g, '$1="https://student.sechenov.ru/')
+ .replace(/url\(["']?\/(?!\/)/g, 'url(https://student.sechenov.ru/')
+ // neutralize meta CSP if present
+ .replace(/]+http-equiv=["']?Content-Security-Policy["']?[^>]*>/gi, '');
+ res.send(html);
+ } else {
+ // stream binary/text as-is
+ const buf = Buffer.from(await r.arrayBuffer());
+ res.send(buf);
+ }
+ } catch (e) {
+ res.status(502).send('proxy error: ' + e.message);
+ }
+});
+
app.listen(8108, () => console.log('sechenov :8108'));