2

ViteJS 反向代理遇到的小坑

 2 years ago
source link: https://paugram.com/tech/vitejs-proxy-problem.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

公司有一个项目的后端正在陆陆续续重构着,期间需要将新旧 API 一起混用。而且我们都知道,Cookie 默认有同源策略,我们本地开发的环境下,域名地址一般为 localhost127.0.0.1,而直接请求其他站点的接口,即便它返回了 Set-Cookie 头,你也会发现并没有作用。

使用反向代理

想要解决这类问题最简单的办法就是设置反向代理,使得多个来自不同站点的 API 聚合在同一个站点下。在服务器环境下最常见的解决方法就是使用 Nginx 的虚拟主机配置来实现,但在本地开发环境下这种操作就显得略微复杂,而且并不是所有前端都会用 Nginx(偏后端/运维)。幸运的是,ViteJS 内置了基于 node-http-proxy 实现的反向代理功能,平时开发我基本上都在用。

这是来自 官方文档 的示例,其中有一段写了 rewrite 参数的配置:

export default defineConfig({
  server: {
    proxy: {
      '/api': {
        target: 'http://jsonplaceholder.typicode.com',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '')
      }
    }
  }
})

发现了问题

我起初也是参考着这个来的,写了一段将本地 /api 指向 https://paul.ren/api(脱敏)这样的配置,当我想要增加一个 /apiNew 的代理时,发现它并不起作用。

本文有些水,说白了,就是一条“小杠”酿大祸,想看结果可以直接往下跳过...

"/api": {
  target: "https://paul.ren/api",
  changeOrigin: true,
  rewrite: (path) => path.replace(/^\/api/, "")
},
"/apiNew": {
  target: "https://v2.paul.ren/api",
  changeOrigin: true,
  rewrite: (path) => path.replace(/^\/apiNew/, "")
}

然后页面访问 http://localhost:3300/apiNew/login(脱敏)接口后返回 404,这就奇怪了,为什么失败了呢?

我首先想排查下 rewrite 参数干了什么。可 ViteJS 的文档上也没有给具体的说明,就翻了翻其 源码,看起来是把我访问路由的 path 给替换了一波。

访问 `http://localhost:3300/apiNew/login`
得到 path `/apiNew/login`
rewrite 就是把 `/apiNew/login` 的 前缀去掉,变成 `/login`,
最后得到代理地址 `https://v2.paul.ren/api/login`

看起来我的设置是正确的,可实际访问确实如此吗?尝试过在配置项里面写 console.log 函数,没有用,就想着能不能让 ViteJS 把所有信息打印出来,这种情况肯定是属于异常行为了。

开启日志输出

在官方文档用关键词 debug 未果,换了个 log 去搜,有了新的答案,logLevel

这个参数同样也在 vite.config.ts 里面设置,默认是 info,我改成 warn 之后,报错信息果然就出来了。

vite:proxy /apiNew/captcha/ -> https://paul.ren/api +0ms

可以看到,我访问 /apiNew,实际上走了 /api 的规则!一切水落石出了!这么一看,/apiNew 还确实符合 /api 这个规则...

那解决办法就很清楚了,我把 /api 这条规则的适配改成 /api/,就无法匹配 /apiNew 了,最终我的配置项改成了这样子,问题也就成功解决咯!

"/api/": {
  target: "https://paul.ren/api/",
  changeOrigin: true,
  rewrite: (path) => path.replace(/^\/api/, "")
},
"/apiNew/": {
  target: "https://v2.paul.ren/api/",
  changeOrigin: true,
  rewrite: (path) => path.replace(/^\/apiNew/, "")
}

还有一个方法就是把这两个规则互相对调,也就是让 /apiNew 优先级更高,更快被匹配到,但是这样感觉做就是埋坑行为,规则一旦多起来就很麻烦了...

其实最开始是公司的实习生发现后端接口的 Cookie 没法设置上去,就私下开了个腾讯会议问我,我让她按我的方法设置反向代理之后就触发了这样一个问题了。说实话我对这个问题还蛮有兴趣,毕竟从一开始我就没明白 rewrite 这个参数是怎么用的,今天这样一出虽然耗费了将近一小时左右的时间,而且最终解决方案及其「简单粗暴」。但我感觉还是有些许意义的,以后遇到类似问题就多了一个好排查的点了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK