/** * 将发往字面量 IPv4 的 https 请求改写为 http。 * 用于云控面板 HTTP 入口对浏览器返回 307 升级 HTTPS、但 IP 上 443 不可达的场景。 */ 'use strict'; function rewriteHttpsToHttpForLiteralIp(url) { try { const parsed = new URL(url); if (parsed.protocol !== 'https:') { return url; } if (!/^\d{1,3}(\.\d{1,3}){3}$/.test(parsed.hostname)) { return url; } parsed.protocol = 'http:'; return parsed.toString(); } catch (_) { return url; } } async function attachHttpIpRewriteInterceptor(page, contextLabel = 'page', options = {}) { const shareToken = typeof options.shareToken === 'string' ? options.shareToken : ''; const blockHeavyResources = options.blockHeavyResources !== false; await page.setRequestInterception(true); page.on('request', (req) => { if (req.isInterceptResolutionHandled()) { return; } if (blockHeavyResources) { const resourceType = req.resourceType(); if (['image', 'media', 'font'].includes(resourceType)) { req.abort(); return; } } const originalUrl = req.url(); const rewrittenUrl = rewriteHttpsToHttpForLiteralIp(originalUrl); if (rewrittenUrl !== originalUrl) { const continueOptions = { url: rewrittenUrl }; if (shareToken) { const headers = { ...req.headers() }; const existingCookie = headers.cookie || headers.Cookie || ''; if (!existingCookie.includes('share_token=')) { headers.cookie = existingCookie ? `${existingCookie}; share_token=${shareToken}` : `share_token=${shareToken}`; } continueOptions.headers = headers; } req.continue(continueOptions); return; } req.continue(); }); } module.exports = { rewriteHttpsToHttpForLiteralIp, attachHttpIpRewriteInterceptor, };