如何拦截JS发起的GET请求并重写URL以静态化旧站点?
解决JS动态发起GET请求的拦截与URL重写问题
问题分析
你之前的XHR和fetch拦截脚本没生效,大概率是因为目标JS用了**动态创建DOM元素(比如<script>标签)**的方式加载资源——这种请求不属于AJAX请求(XHR/fetch),所以不会被你之前的拦截代码捕获。网络面板里标记为script类型的请求,基本都是这种情况。
完整解决方案
需要覆盖三种常见的JS发起请求的场景:XHR、Fetch、动态DOM元素加载,把以下脚本放在HTML的<head>最顶部,确保在其他JS执行前完成拦截逻辑的注入。
1. 拦截动态创建的资源标签(script/link/img等)
针对JS通过document.createElement创建标签加载资源的情况:
// 自定义URL重写逻辑,根据你的本地资源路径修改 function rewriteUrl(originalUrl) { // 示例:将原站点域名替换为本地静态资源路径 const oldDomain = "https://your-old-domain.com"; const localBase = "./static-resources"; return originalUrl.replace(oldDomain, localBase); } // 重写document.createElement,拦截资源标签创建 const originalCreateElement = document.createElement; document.createElement = function(tagName) { const element = originalCreateElement.call(this, tagName); const tag = tagName.toLowerCase(); // 拦截script标签的src设置 if (tag === "script") { const originalSetSrc = Object.getOwnPropertyDescriptor(element.__proto__, "src").set; Object.defineProperty(element, "src", { set: function(value) { const localUrl = rewriteUrl(value); console.log(`拦截动态script请求:${value} → ${localUrl}`); originalSetSrc.call(this, localUrl); }, get: function() { return this.getAttribute("src"); } }); } // 拦截link标签的href设置(比如加载CSS) if (tag === "link") { const originalSetHref = Object.getOwnPropertyDescriptor(element.__proto__, "href").set; Object.defineProperty(element, "href", { set: function(value) { const localUrl = rewriteUrl(value); console.log(`拦截动态link请求:${value} → ${localUrl}`); originalSetHref.call(this, localUrl); }, get: function() { return this.getAttribute("href"); } }); } // 若还有其他需要拦截的资源类型(如img),可参照上述逻辑添加 return element; };
2. 拦截XHR请求
优化之前的XHR拦截逻辑,覆盖所有参数:
const originalXhrOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url, async = true, user = null, password = null) { const localUrl = rewriteUrl(url); console.log(`拦截XHR请求:${method} ${url} → ${localUrl}`); originalXhrOpen.call(this, method, localUrl, async, user, password); };
3. 拦截Fetch请求
处理Request对象和字符串URL两种输入情况:
const originalFetch = window.fetch; window.fetch = async function(input, init) { let targetUrl, newInput; if (input instanceof Request) { targetUrl = input.url; newInput = new Request(rewriteUrl(targetUrl), input); } else { targetUrl = input; newInput = rewriteUrl(targetUrl); } console.log(`拦截Fetch请求:${targetUrl} → ${newInput.url || newInput}`); return originalFetch(newInput, init); };
验证方法
- 打开浏览器开发者工具的「网络」面板,查看请求的「类型」和「发起者」
- 查看控制台的拦截日志,确认所有目标请求都被捕获并重写
- 检查网络请求的URL是否已替换为本地路径
内容的提问来源于stack exchange,提问作者Yannick Perret
相关产品推荐
相关产品推荐

