利用proxy 解决 Django Vue 开发环境中的跨域问题
最近使用 Django+Vue的组合快速的做一个项目,前段之前有看过,但是只是👀会了,这次实际操作,在前后端分离后的开发环境中踩了坑。
环境
- Django + DRF
- Django Channels,主要是websocket
- vue-admin-template,一个开源的项目,很多东西都有实现,新手可以用来改改就用,还能学习
开发环境:
- wsgi, 8000
- asgi, 8001
- vue, 9528
问题
- 想像在使用nginx一样的透明的使用开发环境
- django已经配置了
corsheaders
middleware了 - 尝试 axios显示指定地址和端口到8000的服务上,解决了axios实例的访问,但是使用 el-upload的表单时,发现就不好使了,localhost和其他不同域,拿不到 cookie中的csrftoken,导致被 django拒绝
解决
在查看了各种文档后,最有效的方案是devServer
的proxy,这是webpack提供的功能,使用的是http-proxy-middleware这个中间件,文档很详细,可以看看。
目标:
- 代理
/api
的请求到8000端口的wsgi server - 代理
/ws
的请求到8001的asgi server
/api ---> localhost:8000/api
localhost:9528 (cookie) --
/ws ---> localhost:8001/ws
vue.conf.js
devServer: {
...
proxy: {
[process.env.VUE_APP_BASE_API]: {
target: 'http://127.0.0.1:8000',
changeOrigin: true,
ws: false,
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: ''
},
cookieDomainRewrite: { '*': 'localhost' }
},
'/ws': {
target: 'ws://127.0.0.1:8001',
// changeOrigin: true,
secure: false,
ws: true
}
}
...
}
说明:
- proxy里面的key表示要代理的path,我这里写的是变量代表的值,是从其他地方看到的,可以根据这个值来判断,比如 /api-prod /api-dev等,这里可以根据自己项目实际的命名规则,一般是
/api
即可 - target:表示要代理的请求目标
- changeOrigin:表示修改请求header中的origin
- ws:表示是否代理websockets
- pathRewrite:根据正则匹配来重写url,根据实际需要来写
- cookieDomainRewrite,
{ '*': 'localhost' }
表示所有重写到localhost,这样所有的cookie都会同步过来,因为我使用了django session和crsftoken,所以这里得同步一下,不然会有前面说的axios header中有X-CRSFToken,而直接请求的form表单中没有,因为cookie不同,取不到csrftoken的值