惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

IT之家
IT之家
博客园 - 聂微东
雷峰网
雷峰网
Microsoft Azure Blog
Microsoft Azure Blog
WordPress大学
WordPress大学
Hugging Face - Blog
Hugging Face - Blog
S
SegmentFault 最新的问题
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tailwind CSS Blog
博客园 - 三生石上(FineUI控件)
V
Visual Studio Blog
博客园 - 司徒正美
爱范儿
爱范儿
月光博客
月光博客
阮一峰的网络日志
阮一峰的网络日志
博客园_首页
博客园 - 【当耐特】
Jina AI
Jina AI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
酷 壳 – CoolShell
酷 壳 – CoolShell
大猫的无限游戏
大猫的无限游戏
小众软件
小众软件
人人都是产品经理
人人都是产品经理
V
V2EX

Mereith's Blog

记一次代理转发问题的排查与解决 k8s + jenkins + gitlab 触发器 【转载】没有编程生产力这样的东西 【后续】居然被 ddos 了 居然被 ddos 了 Tagger - 让版本标签管理更简单 openclash 开启后端口转发失效 nextjs 启动时执行代码 买了太多VPS不知道干什么,干脆做个网站 juhost Level-1 测评 VMISS CN - Hong Kong VMISS JP - Tokyo - BGP 测评 VMISS CN - Hong Kong - BGP HomeLab 的终点是 最近在做的事情 因为选择艰难症,自己写了一套开源博客系统 手撸一个nodejs分布式爬虫,还要可视化 HomeLab 分享 我的个人工作流——开源项目推荐 动手写一个超简单的编译器 safari 插件开发 Safari Extensions Preferences 按钮无响应 设置移动端软键盘回车按钮文案 nginx proxy manager 非标准端口反代 Host 不对 监控 k8s ingress 自动添加域名 DNS 解析 使用 ingress 注解给 traefik ingress 添加中间件 使用流水线功能为文章添加固定结尾 为 VanBlog 添加一个小挂件 基于React/umi/egg自建博客系统 如何正确停止 NodeJS 子进程 k8s pod 替换策略
PVE DataCenter Manager 端口号跳转错误修复
wanglu@mereith.com (mereith) · 2025-04-16 · via Mereith's Blog

请注意,本文编写于 416 天前,最后修改于 415 天前,其中某些信息可能已经过时。

我有好几个集群,用 PVE DataCenter Manager 管理的时候,发现跳转有 bug。

比如我用 https://pve.xxxx.com (不用 8006 端口号),我在前端点 Open WebUI 跳转自动给我带上了 8006。

解法是登录到服务器,修改 /usr/share/javascript/proxmox-datacenter-manager/index.hbs,在 head 标签下面加入这个 script 标签。

<script type="text/javascript"> (function() { // 判断字符串是否为IP地址 function isIPAddress(host) { // IPv4地址正则表达式 const ipv4Pattern = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/; if (!ipv4Pattern.test(host)) return false; // 验证每个段是否在0-255范围内 const parts = host.split('.'); for (let i = 0; i < parts.length; i++) { const part = parseInt(parts[i], 10); if (part < 0 || part > 255) return false; } return true; } // 判断是否以.top结尾 function isTopDomain(host) { return host.endsWith('.top'); } // 移除8006端口号 - 修复正则表达式 function removePort8006(url) { return url.replace(/:8006(\b|\/|#|\?)/, function(match, p1) { return p1; // 保留分隔符但移除端口 }); } // 处理URL函数 function processUrl(url) { try { const urlObj = new URL(url, window.location.href); const host = urlObj.hostname; console.log("处理URL:", url, "主机名:", host, "端口:", urlObj.port); // 如果是IP地址,不做处理 if (isIPAddress(host)) { console.log('IP地址链接,不做处理:', url); return url; } // 如果不是.top域名,且有8006端口,去除端口号 if (!isTopDomain(host) && urlObj.port === '8006') { const newUrl = removePort8006(url); console.log('已移除端口号,新URL:', newUrl); return newUrl; } return url; } catch (e) { console.error('解析URL时出错:', e); return url; } } // 立即覆盖window.open方法 const originalWindowOpen = window.open; window.open = function(url, target) { if (url) { console.log("拦截到window.open调用:", url, target); // 移除对target的检查,无论是否有target参数都处理 const newUrl = processUrl(url); if (newUrl !== url) { console.log("调用原始window.open,参数已修改:", newUrl, target); return originalWindowOpen.call(this, newUrl, target || "_blank"); } } return originalWindowOpen.apply(this, arguments); }; // 初始化其他拦截器 function initInterceptors() { console.log("初始化拦截器..."); // 拦截所有链接点击事件 document.removeEventListener('click', linkClickHandler, true); document.addEventListener('click', linkClickHandler, true); // 拦截location.assign const originalAssign = window.location.assign; window.location.assign = function(url) { console.log("拦截到location.assign调用:", url); return originalAssign.call(window.location, processUrl(url)); }; // 尝试拦截location.href设置 try { const originalLocationDescriptor = Object.getOwnPropertyDescriptor(Location.prototype, 'href'); if (originalLocationDescriptor && originalLocationDescriptor.configurable) { Object.defineProperty(Location.prototype, 'href', { set: function(url) { console.log("拦截到location.href设置:", url); return originalLocationDescriptor.set.call(this, processUrl(url)); }, get: originalLocationDescriptor.get, configurable: true }); } } catch (e) { console.error('拦截location.href失败:', e); } console.log("拦截器初始化完成"); } // 链接点击处理函数 function linkClickHandler(event) { // 查找事件路径中的链接元素 let element = event.target; while (element && element.tagName !== 'A') { element = element.parentElement; if (!element) break; } // 如果找到链接 if (element && element.tagName === 'A') { console.log("拦截到链接点击:", element.href, "target:", element.target); const newUrl = processUrl(element.href); if (newUrl !== element.href) { event.preventDefault(); console.log("阻止默认操作,使用新URL打开:", newUrl); if (element.target === '_blank') { window.open(newUrl, '_blank'); } else { window.location.href = newUrl; } } } } // 添加MutationObserver以监视DOM变化 function setupMutationObserver() { console.log("设置MutationObserver..."); const observer = new MutationObserver(function(mutations) { // 当DOM变化时重新初始化拦截器 initInterceptors(); }); observer.observe(document.body, { childList: true, subtree: true }); console.log("MutationObserver已设置"); } // 初始化函数 function initialize() { console.log("初始化拦截脚本..."); initInterceptors(); // DOM加载完成后设置MutationObserver if (document.body) { setupMutationObserver(); } else { window.addEventListener('DOMContentLoaded', setupMutationObserver); } // 页面完全加载后再次初始化 window.addEventListener('load', function() { console.log("页面加载完成,重新初始化拦截器"); initInterceptors(); // 延迟1秒再次初始化,确保WASM应用加载完成 setTimeout(initInterceptors, 1000); }); console.log("拦截脚本初始化完成"); } // 立即初始化 initialize(); // 添加到window对象,方便调试 window.__interceptorFunctions = { initialize: initialize, processUrl: processUrl, isIPAddress: isIPAddress, isTopDomain: isTopDomain, removePort8006: removePort8006 }; })(); </script>