feat(clickTtHttpPageRoutes): add meta-refresh URL rewriting for proxy handling
- Implemented a new function to rewrite meta-refresh URLs in HTML, ensuring redirects after login are routed through the proxy while maintaining session integrity. - Updated the proxy GET and POST endpoints to include the new meta-refresh handling, enhancing the overall functionality of the proxy interactions. - Improved error handling in the new function to ensure robustness in processing HTML content.
This commit is contained in:
@@ -85,6 +85,38 @@ function rewriteLinksInHtml(html, proxyBaseUrl, pageBaseUrl, sid) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Schreibt meta-refresh-URLs um, damit Redirects nach Login über unseren Proxy laufen (Session bleibt erhalten).
|
||||
*/
|
||||
function rewriteMetaRefreshInHtml(html, proxyBaseUrl, pageBaseUrl, sid) {
|
||||
if (!html || !proxyBaseUrl || !pageBaseUrl || !sid) return html;
|
||||
try {
|
||||
const base = new URL(pageBaseUrl);
|
||||
return html.replace(
|
||||
/<meta\s[^>]*(?:http-equiv\s*=\s*["']refresh["'][^>]*content\s*=\s*["']([^"']+)["']|content\s*=\s*["']([^"']+)["'][^>]*http-equiv\s*=\s*["']refresh["'])[^>]*>/gi,
|
||||
(match, content1, content2) => {
|
||||
const content = content1 || content2;
|
||||
if (!content) return match;
|
||||
const urlMatch = content.match(/^\s*\d+\s*;\s*url\s*=\s*(.+)$/i);
|
||||
if (!urlMatch) return match;
|
||||
let targetUrl = urlMatch[1].trim();
|
||||
if ((targetUrl.startsWith("'") && targetUrl.endsWith("'")) || (targetUrl.startsWith('"') && targetUrl.endsWith('"'))) {
|
||||
targetUrl = targetUrl.slice(1, -1);
|
||||
}
|
||||
if (targetUrl.startsWith('/') || !targetUrl.startsWith('http')) {
|
||||
targetUrl = new URL(targetUrl, base.origin + base.pathname).href;
|
||||
}
|
||||
if (!shouldProxyUrl(targetUrl)) return match;
|
||||
const proxyUrl = buildProxyUrl(proxyBaseUrl, targetUrl, sid);
|
||||
const newContent = content.replace(/url\s*=\s*.+$/i, `url=${proxyUrl}`);
|
||||
return match.replace(content, newContent);
|
||||
}
|
||||
);
|
||||
} catch {
|
||||
return html;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Schreibt Formular-Actions um, sodass Submissions über unseren Proxy laufen (Login etc. wird geloggt).
|
||||
*/
|
||||
@@ -198,6 +230,7 @@ router.get('/proxy', async (req, res, next) => {
|
||||
const proxyBase = baseUrl.replace(/\/$/, '') + '/api/clicktt/proxy';
|
||||
html = rewriteLinksInHtml(html, proxyBase, targetUrl, sid);
|
||||
html = rewriteFormActionsInHtml(html, proxyBase, targetUrl, sid);
|
||||
html = rewriteMetaRefreshInHtml(html, proxyBase, targetUrl, sid);
|
||||
|
||||
res.set({
|
||||
'Content-Type': 'text/html; charset=utf-8',
|
||||
@@ -258,8 +291,14 @@ router.post('/proxy', async (req, res, next) => {
|
||||
}
|
||||
(Array.isArray(setCookies) ? setCookies : [setCookies]).forEach(c => res.append('Set-Cookie', c));
|
||||
}
|
||||
const location = responseHeaders.get?.('location') ?? responseHeaders['location'];
|
||||
let location = responseHeaders.get?.('location') ?? responseHeaders['location'];
|
||||
if (location && (result.status >= 301 && result.status <= 308)) {
|
||||
if (location.startsWith('/')) {
|
||||
try {
|
||||
const base = new URL(targetUrl);
|
||||
location = base.origin + location;
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
const baseUrl = process.env.BACKEND_BASE_URL || process.env.BASE_URL
|
||||
|| `${req.protocol || 'http'}://${req.get('host') || 'localhost:' + (process.env.PORT || 3005)}`;
|
||||
const proxyBase = baseUrl.replace(/\/$/, '') + '/api/clicktt/proxy';
|
||||
@@ -288,6 +327,7 @@ router.post('/proxy', async (req, res, next) => {
|
||||
}
|
||||
responseBody = rewriteLinksInHtml(responseBody, proxyBase, targetUrl, sid);
|
||||
responseBody = rewriteFormActionsInHtml(responseBody, proxyBase, targetUrl, sid);
|
||||
responseBody = rewriteMetaRefreshInHtml(responseBody, proxyBase, targetUrl, sid);
|
||||
}
|
||||
|
||||
res.set({
|
||||
|
||||
Reference in New Issue
Block a user