素材巴巴 > 程序开发 >

神坑——后端允许了跨域但是前端(vue3 vite axios)仍然提示跨域

程序开发 2023-09-20 23:36:30

这个问题坑了我整整一个晚上。·这明明是个非常常见的问题,我自己也遇到好多次了,以前都是后端允许跨域就可以了。但是这次就是不行!

首先网上最多的方案是用代理,例如这篇:https://blog.csdn.net/admin_web/article/details/121924527

我一晚上也主要在按照这些方法去尝试,但是我努力一个晚上,都不行,一直怀疑是自己的姿势不对!最后在快要放弃前(12点多,不清醒了),瞎猫碰上死耗子,居然解决了。

不是配置问题!

PS:我的后端用go写的,这里也贴一下我的允许跨域方案:

// 允许跨域
 func Options() gin.HandlerFunc {return func(c *gin.Context) {method := c.Request.Methodc.Header("Access-Control-Allow-Origin", "*")c.Header("Access-Control-Allow-Headers", "Access-Control-Allow-Headers,Authorization,User-Agent, Keep-Alive, Content-Type, X-Requested-With,X-CSRF-Token,AccessToken,Token")c.Header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, PATCH, OPTIONS")c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")c.Header("Access-Control-Allow-Credentials", "true")// 放行所有OPTIONS方法if method == "OPTIONS" {c.AbortWithStatus(http.StatusAccepted)}c.Next()}
 }
 

报错

我后端完整的请求:http://localhost:10001/captcha

我的baseurl如下图:
在这里插入图片描述我的请求接口这么写的,"captcha"就是相对路径:

export function getcaptchaId() {return get<{ id: string }>("captcha");
 }
 

然后请求:
在这里插入图片描述
看报错很明显,提示就是跨域,都提示这么明显了,我没理由怀疑他吧,所以一晚上都在往这个方向尝试。

实际问题

然而真实答案是因为少了个/,其他不变,就改动下面一个地方:

export function getcaptchaId() {return get<{ id: string }>("captcha/");
 }

和原来相比,就captcha后面加了个/。然后,就解决了!对,就是这么的简单。

原理分析

于是我就去查了下这个/的作用,这篇文章有讲解,它里面提到有重定向,于是我去掉反斜杠再去试试,然后我再看看我的后端:

[GIN-debug] redirecting request 301: /captcha/ --> /captcha/
 

后端确实是有提示访问进来被重定向了。但是,依然没用,前端还是提示跨域。

所以,可能原因是:go的后端虽然能够像文章分析的那样重定向,但是,重定向之后,并不会再经过允许跨域的中间件(因为我的print没有打印出来,说明都没进入),所以,这里可以认为后端配置的允许跨域中间件并没有生效。

使用代理存在的问题

网上普遍提示使用代理去解决。我尝试了一晚上不成功(昨晚有点迷糊了,没有找到本质的原因,一直不成功,下面的测试是我第二天写这篇博客才测试的),不甘心,要分析下它的问题。

下面先假设我还没加那个/,存在跨域问题的请情况下去使用代理。

我使用vite的代理:

    //反向代理配置 - 可解决跨域问题server: {proxy: {"/api": {target: "http://localhost:10001/",changeOrigin: true},},},
 

然后:

axios.defaults.baseURL = "/api"; // 设置服务端地址
 

然后看报错:
在这里插入图片描述

PS:用chrome调试时,更改了vite配置一定要重新run ,并且强制清理缓存并硬性重新加载,不然可能看到的是假象,我都被折磨死了。

实际请求的却是端口3000,这个端口是我前端的端口。而不是后端的端口,但是我看后端,确实有请求进入的:
在这里插入图片描述
说明代理是生效的,上面请求显示3000端口应该是代理的效果了。

这里的问题是,我的请求并没有/api,所以请求不到。

然后我发现还有个rewrite方法,我再改了一下:

    //反向代理配置 - 可解决跨域问题server: {proxy: {"/api": {target: "http://localhost:10001/",changeOrigin: true,rewrite: (path) => path.replace("/api", ""),},},},
 

我加了个rewrite,其他不变,然后再看结果:
在这里插入图片描述
在这里插入图片描述
还是报错,但是确实发现链接上的/api给去掉了。后端其实也接收到请求了,但是被重定向了,然后就没有下文了。这也不行呀,没法正常请求。

是不是这个rewrite不好使?

上面的原理分析不是说了这个重定向的问题吗,所以我还想试一下,加上那个/

export function getcaptchaId() {return get<{ id: string }>("captcha/"); // 加上反斜杠
 }
 

在这里插入图片描述
好家伙,真的可以,加了反斜杠就能解决这个重定向的问题,也能正常使用,所以,rewrite也是有用的。

当然,也可以不使用rewrite,在我后端路径上加个/api,然后captcha后面不加反斜杠, 试试看吧:

在这里插入图片描述
仔细看,其实还是会重定向,但是,这种情况下能够正常访问到接口。

到这里,说明这个代理的方法确实也能解决跨域问题。

总结

  1. 实际上后端允许跨域之后,前端就不存在跨域问题,是我的姿势不对,请求的链接最后没有加/,但是浏览器这个错误提示很误导人。
  2. 代理的方式也能解决跨域的问题,这种情况下,后端就不需要配置允许跨域了。
  3. vite代理的rewrite有点小毛病,虽然能够发挥作用,但是也要注意链接最后要加上/,否则请求会失败

这么一个傻逼问题,真的折磨人呀!这通下来,以后应该不会被跨域问题折磨了吧。。。。。。。


标签:

素材巴巴 Copyright © 2013-2021 http://www.sucaibaba.com/. Some Rights Reserved. 备案号:备案中。