我在学习尚硅谷Ajax课程时候,第一次遇到跨域的问题–Access to XMLHttpRequest at ‘http://localhost:5000/students’ from origin ‘http://localhost:8080’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource的报错,那时候是通过设置头部信息——将Access-Control-Allow-Origin头部信息的值为“*”解决的,而本次文章主要是通过开启代理服务器解决跨域问题
报错
模拟一个场景,我们通过axios获取想要的数据
<template>
<div>
<button @click='getStudents'>获取学生信息</button>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'App',
methods: {
getStudents() {
axios.get('http://localhost:5000/students') //获取数据的网址
.then(
response => {
console.log('请求成功' + response.data);
},
erro => {
console.log('请求失败' + erro.message);
}
)
}
}
}
</script>
在浏览器中,通过点击按钮获取信息,而控制台中报错:Access to XMLHttpRequest at 'http://localhost:5000/students' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
这是因为我们跨域了,违背了同源策略("协议名+主机名+端口号"三者相同)。
细想,我们运行代码时候,显示的是8080的端口号的页面,而我们需要访问数据的页面的端口号为5000,这表明我们跨域了
解决方案
使用代理服务器可以转发请求,以避免由于不同源导致的跨域问题。例如,在应用程序中,我们可以将请求发送到代理服务器上,代理服务器会将该请求发送到目标站点,然后将响应返回给应用程序
查阅官方文档,在文档中有这样的说明
如果你的前端应用和后端 API 服务器没有运行在同一个主机上,你需要在开发环境下将 API 请求代理到 API 服务器。这个问题可以通过
vue.config.js
中的devServer.proxy
选项来配置。
devServer.proxy
可以是一个指向开发环境 API 服务器的字符串:
我们需要开启代理服务器,在配置文件中只需添加devServer的配置即可(每次修改配置里面的信息都需要重新启动脚手架:node run server)
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
pages: {
index: {
//入口
entry: 'src/main.js',
}
},
transpileDependencies: true,
lintOnSave: false, //关闭语法检查
//开启代理服务器
devServer: {
proxy: 'http://localhost:5000' //指向的是需要数据的网络端口号
}
})
与此同时,我们axios请求数据的地址指向代理服务器
数据请求成功
配置多个代理
访问多个服务时,我们需要配置多个代理服务器。
在本机中指定前缀(ps:本机的前缀是忽略协议名、主机号、端口号的前缀)。
<template>
<div>
<button @click='getStudents'>获取学生信息</button>
<button @click='getCars'>获取汽车信息</button>
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'App',
methods: {
getStudents() {
axios.get('http://localhost:8080/msg1/students')
.then(
response => {
console.log('请求成功', response.data);
},
erro => {
console.log('请求失败', erro.message);
}
)
},
getCars() {
axios.get('http://localhost:8080/msg2/cars')
.then(
response => {
console.log('请求成功', response.data);
},
erro => {
console.log('请求失败', erro.message);
}
)
},
}
}
</script>
在vue.config.js中我们添加多个代理,代理服务器配置好前缀,使之对应的数据得以转发,代理服务器中还需要配置pathRewrite路径重写,把前缀清掉后到目标服务器中查找数据,没把前缀清掉的话在目标服务器是找不到数据的
vue.config.js:
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
pages: {
index: {
//入口
entry: 'src/main.js',
}
},
transpileDependencies: true,
lintOnSave: false, //关闭语法检查
//开启代理服务器
devServer: {
proxy: {
'/msg1': {
target: 'http://localhost:5000', //代理目标的基础路径
pathRewrite: { '^/msg1': '' }, //一定要路径重写,不然
ws: true,
changeOrigin: true
},
'/msg2': {
target: 'http://localhost:5001',
pathRewrite: { '^/msg2': '' },
}
}
}
})