在实践中深入了解跨域 + devServer.proxy
1. 背景
前段时间想在群里搞个钉钉机器人定时提醒自己写周报,然而又碰到了跨域的情况,代码大致如下:
-- index.js --
import axios from 'axios'
function sxx () {
axios.post('https://oapi.dingtalk.com/robot/send?XXXXXXXX', {
msgtype: 'text',
text: {
content: '[sxx]: 我就是我, 是不一样的烟火'
}
})
}
sxx ()
-- webpack.config.js --
const path = require('path')
module.exports = {
entry: './index.js',
devServer: {
host: '0.0.0.0',
port: 8080
},
plugins: [
new HtmlWebpackPlugin()
],
output: {
filename: 'main.js',
path: path.resolve(__dirname, './dist')
}
}
报错如下所示:

2. 回顾跨域的知识
对于跨域,MDN里的这篇文章:HTTP访问控制(CORS)讲的很清晰。截取里面非常经典的图片(见下图),我们在domain-a.com网站下,访问domain-b.com的资源(png图片和eot的字体),这两个资源就会跨域,此时浏览器可能会阻止这两个资源请求的发送,也可能是跨站请求正常发送,但返回结果被浏览器拦截,具体要看浏览器的实现。

凭啥你说是阻止了请求的发送?
通过charles可以看到post请求https://oapi.dingtalk.com/robot/send
压根都没有发送,只是一个connect请求(况且若请求真的发送了,群里就会有钉钉机器人的消息了,返回的结果对我来说并没用)

3. 更改origin是否可以处理跨域
import axios from 'axios'
function sxx () {
axios.post('https://oapi.dingtalk.com/robot/send?XXXXXXXX', {
msgtype: 'text',
text: {
content: '[sxx]: 我就是我, 是不一样的烟火'
}
}, { headers: {'Origin': 'oapi.dingtalk.com'} })
}
sxx ()
然而,直接报错了...主要看第一个报错:Refused to set unsafe header "Origin"


4. webpack的devServer.proxy处理了跨域
之前看到慕课网里dell老师讲的devServer.proxy可以代理开发环境中的url,尝试了下竟然绕过了跨域,请求成功了,代码更改如下: -- index.js --
import axios from 'axios'
function sxx () {
axios.post('/robot/send?XXXXXXXX', {
msgtype: 'text',
text: {
content: '[sxx]: 我就是我, 是不一样的烟火'
}
})
}
sxx ()
-- webpack.config.js --
const path = require('path')
module.exports = {
entry: './index.js',
devServer: {
host: '0.0.0.0',
port: 8080,
proxy: {
'/robot': {
target: 'https://oapi.dingtalk.com',
secure: false, // 协议是https的时候必须要写
changeOrigin: true
}
}
},
// ···省略了···太懒···
}
重点:添了changeOrigin: true
后才可跨域,否则还是不行。那么重点就是理解为啥加上changeOrigin
即可跨域
5. changeOrigin如何解决跨域
dell老师在视频里说changeOrigin
字段是为了防止网站被爬数据,会验证请求的origin,若origin不是本网站的,则请求无法获得结果,看起来像是改变了header里的origin,但是刚不是尝试了咱们是无法更改origin的么?
查看文档中关于changeOrigin
字段的描述:
changeOrigin: change the origin of the host header to the target url
还是不太明白,然后查看源码(在http-proxy/common.js中):

changeOrigin
只是更改了request请求中的host,并不是origin,那么更加奇怪了,到底是如何绕过跨域的呢?
其实,devServer中的proxy就相当于charles进行url的代理,在sxx()
执行后发送的请求是http://0.0.0.0:8080/robot/send?XXXXXXXX
,我们是在0.0.0.0:8080下,当然不会限制这样的请求的发送,然后devServer的proxy通过配置将host更改为oapi.dingtalk.com
,该请求就能正常进行,大致情况如下图所示:

6. charles模拟
为验证该想法,使用charles替换devServer.proxy进行url的代理,对于http://0.0.0.0:8080/robot/send?XXXXXXXX
进行Breakpoint,更改该请求的host。
但是,又报错啦...如下图

disableHostCheck: true
即可。
转载自:https://juejin.cn/post/6844904161369128967