完整代码可以参考: github.com/electroluxc…
通常项目中的反向代理
一版来说,我们作为前端在与后端联调的时候,为了避免浏览器的跨域错误,会在打包工具vite或者webpack中,配置反向代理工具
这个时候流程图如下
flowchart TD
C[webpack等打包工具] -->|开启服务| E[前端地址]
E -->|起一个middleware服务拦截指定请求代理| D[后端地址]
这个时候其实可以说我们只有两个地址,也就是在前端地址中拦截后端的middleware请求,然后代理到前端地址
浏览器插件中的反向代理
而在浏览器插件中,我们的实现方式会有所不同,最显而易见的区别是我们会有三个地址,因为如果像在上图一样在 浏览器插件中直接进行串行地址,可能会有问题,
你知道的,我们在 定义前端路由有时候会加上一些兜底。
而没有了webpack,vite等打包工具做聚合,那么串行起来有可能后端代理的地址会命中前端兜底的路由,导致所有的后端请求寄了
{
match: "*",
component: 404/403/other
}
这是设计三个地址的原因,其中我们会有一个中心策略去统筹前端和后端,将他们放在同一个地址上,实现思路可以参考下面
flowchart TD
C[浏览器代理插件] -->|代理地址| D[前端]
C -->|代理地址| E[后端地址]
D -->|聚合| F[另一个地址]
E -->|聚合| F
浏览器插件代码实现
浏览器插件代码实现
首先在 manifest.json
中 的 permissions
去申请权限,
然后定义 host_permissions
接着定义 background
的脚本地址,
最后把内容填进去就好
manifest.json
示例如下
{
"name": "simple-modify-proxy",
"version": "0.1",
"manifest_version": 3,
"description": "",
"author": "Electrolux",
"permissions": [
"proxy"
],
"background": {
"service_worker": "js/background.js"
},
"host_permissions": [
"<all_urls>"
]
}
background.js 中, 代码写法如下,20行代码左右就可以实现了,简单说一下 思路,
- 其中
FindProxyForURL
这个名字不能够改变, 一旦改变那么proxy
不会生效,这点需要尤其注意.然后FindProxyForURL
中不能够有注释,不然注入的时候会有问题 - 这里的命中格式需要你根据自己的项目进行修改,注意一下下面的代码可能会对你浏览的其他网页有影响,所以当你需要的时候再打开这个插件
- 这里只提供最简单的示例,更多的api示例可以参考 google的开发文档 developer.chrome.com/docs/extens…
console.log("background.js loaded")
console.log(chrome)
var FindProxyForUrl = function FindProxyForURL(url, host) {
if(!window.location.href.includes("front-test")){
return 'DIRECT';
}
if (shExpMatch(url, "*api*")) {
// 你的api后端地址
return 'PROXY localhost:8098';
}
if (shExpMatch(url, "*front-test*")) {
// 你的前端地址
return 'PROXY localhost:5500';
}
return 'DIRECT';
}
var configPAC = {
mode: "pac_script",
pacScript: {
data:FindProxyForUrl.toString()
}
};
chrome.proxy.settings.set(
{value: configPAC, scope: 'regular'},
function() {}
);
后端示例
var express = require("express");
var app = express();
let httpServer = http.createServer(app);
app.get("/api/get", function (req, res, next) {
res.send({
code: 200,
message: "success"
});
});
前端
这里我直接用live server了,这是个vscode 插件,直接安装就可以了, 然后我们访问携带 front-test 的就可以访问到我们的界面了。例如 front-test.cn,
front-test.com, www.front.com
最后我们可以简单用一个fetch请求测试一下, 可以看到并没有跨域错误,并且成功命中了
fetch("/api/get").then(e=>e.json()).then(e=>{console.log(e)})