记一次反向代理路径问题
Desc
由于实验在云端环境进行,启动 Gradio 后需通过端口转发访问。初此启动发现 css 不能加载,按钮事件也有问题。F12 检查 Network 发现两个 404:
Name |
Request URL |
info |
https://<forward-ip-port>/info |
theme.css |
https://<forward-ip-port>/theme.css |
观察其他 url 发现,完整的代理路径为 https://<forward-ip-port>/codeserver-forward/<ID>/proxy/<proxy>/
,其后才是 /info
、/theme.css
等。正是这多出的一段路径导致请求失败。
其中,css 问题容易解决,修改网页 HTML,将 theme.css 的 <link>
标签替换正确 url 即可。检查控制台报错,未能请求 info 数据则是按钮事件失效的元凶。继续根据输出定位,知 info 由 index.js 请求:
1 2 3 4 5
| } else { response = await fetch_implementation(`${config2.root}/info`, { headers }); }
|
在 F12 工具里补上了 codeserver-forward/<ID>/proxy/<proxy>
这段路由,没什么效果。
接下来尝试了两种方式,i) 替换 index.js; ii) 拦截 index.js 发出的 /info 请求。
Try
替换 index.js 为本地文件
观察 Network,index.js 被分割为多个文件 (命名形如 index-7a48, index-0750 等) 加载,而在 /info 请求前的只有 index-7a48. 手动下载该文件,与 index.js 有些差异,不过大概定位了 /info 请求位置:
1 2 3
| }) : te = await e(`.../info`, { headers: D }),
|
虽然不知这样处理是否正确,但是检查了 /info 请求前的其他请求,确实只有 index-7a48 与之相关。本地启动 LiveServer,编写油猴脚本进行替换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
(function() { 'use strict';
document.querySelectorAll('script[src="https://<forward-ip-port>/codeserver-forward/<ID>/proxy/<proxy>/assets/index-7a48.js"]').forEach(function(script) { script.remove(); });
var newScript = document.createElement('script'); newScript.src = 'http://127.0.0.1:5500/hpccube-forward/index-7a48.js'; newScript.defer = true; newScript.onload = function() { console.log('New script loaded successfully.'); }; document.head.appendChild(newScript); })();
|
这个脚本确实是运行了;但 /info 请求还是按照错误的 url 发。
拦截 /info 请求并替换
手动下载 info 数据,并拦截请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
(function() { 'use strict';
const originalOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url) { if (url.includes('https://<forward-ip-port>/info')) { url = url.replace('https://<forward-ip-port>/info', 'http://127.0.0.1:5500/hpccube-forward/info'); } return originalOpen.apply(this, arguments); };
const originalFetch = window.fetch; window.fetch = function(input, init) { let url = typeof input === 'string' ? input : input.url; if (url.includes('https://<forward-ip-port>/info/info')) { url = url.replace('https://<forward-ip-port>/info/info', 'http://127.0.0.1:5500/hpccube-forward/info'); } return originalFetch.apply(this, [url, init]); }; })();
|
实测拦截方案成功了,分别向 LiveServer 发了两条 /info 请求,一次 OPTIONS 204,一次 GET 200.
Summary
把 css 和 /info 的问题都解决以后,发现还有不少请求有着与 /info 相同的问题,再改下去意义不大了。
任何通过反向代理的 Web 请求都有可能面临 url 构造错误的问题,在此,Streamlit 做得要比 Gradio 更完善。