You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在不修改HTML文件的前提下将外部资源请求重定向到本地文件?

如何在不修改HTML文件的前提下将外部资源请求重定向到本地文件?

嘿,我来帮你理清楚这个问题——你之前的.htaccess规则没生效,核心原因其实很关键:浏览器是直接向foobar.com发起脚本请求的,这些请求根本不会经过你的服务器!哪怕页面是你服务器托管的,只要资源URL是外部域名,浏览器就会直接跳去那个域名拿资源,你的.htaccess根本抓不到这些请求,自然没法重写。

那有没有办法解决?当然有,给你两个靠谱的方案:

方案一:服务器端替换HTML内容 + 本地重写

思路是:在HTML文件从你的服务器发送到浏览器之前,把里面的外部资源链接替换成你自己服务器的路径,这样浏览器就会向你的服务器请求资源,再用rewrite规则把这个请求指向本地文件。

以Apache为例,你需要启用mod_substitute模块,然后在.htaccess里加这些配置:

# 先替换HTML里的外部资源链接为本地代理路径
AddOutputFilterByType SUBSTITUTE text/html
Substitute "s|https://foobar.com/foo/scripts/script.js|/local-proxy/script.js|ni"

# 再把本地代理路径重写到实际的本地文件
RewriteEngine On
RewriteRule ^local-proxy/script\.js$ /js/script.js [L]

解释一下:第一部分会在HTML输出时,把所有指向foobar.com的脚本链接替换成你服务器的/local-proxy/script.js,浏览器收到页面后就会向你的服务器请求这个路径;第二部分的rewrite规则则把这个请求转发到你本地的/js/script.js文件。

方案二:用Service Worker拦截请求

Service Worker是运行在浏览器后台的脚本,它可以拦截当前页面发出的所有网络请求,包括外部域名的,然后你可以自定义这些请求的响应。

步骤如下:

  1. 先在你的服务器根目录创建一个sw.js文件,内容如下:
self.addEventListener('fetch', function(event) {
  // 匹配目标外部资源的请求
  if (event.request.url.startsWith('https://foobar.com/foo/scripts/script.js')) {
    // 替换成本地资源的请求
    event.respondWith(fetch('/js/script.js'));
  }
});
  1. 同样用服务器端注入的方式,在HTML里自动注册这个Service Worker(不用手动改HTML文件),还是用Apache的mod_substitute
AddOutputFilterByType SUBSTITUTE text/html
Substitute "s|</body>|<script>if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js'); }</script></body>|ni"

这样浏览器加载页面时,会自动注册Service Worker,之后页面发出的所有请求都会被它拦截,匹配到目标外部脚本时,就会转而请求你本地的文件。

为什么你原来的方法不行?

再强调一遍:当HTML里写的是https://foobar.com/...的资源链接,浏览器会直接向foobar.com的服务器发送请求,这个请求的目标域名不是你的服务器,所以你的.htaccess完全接触不到这些请求,规则自然不会生效。

备注:内容来源于stack exchange,提问作者van_folmert

火山引擎 最新活动