通常情况下,跨域问题是由服务端依靠CORS或JSONP等方法解决。为了在开发过程中不依靠后端解决跨域问题,可以使用一台与前端页面服务的Host相同的代理服务器,将请求发送给这台代理服务器,然后再由代理服务器将请求转发给真实的服务器。
使用服务代理可绕开浏览器同源策略的限制。服务代理可以使用Nginx等应用创建,当然Vue CLI也支持创建代理。
Vue CLI代理需要在vue.config.js
中进行配置。
注:Vue CLI代理仅是在开发过程中使用的。
简单代理
Vue CLI创建代理最简单的方式就是:
module.exports = {
devServer: {
proxy: 'http://localhost:4000'
}
}
配置完成后,重启前端页面服务,然后将原本请求的Host改为与页面服务相同的Host即可。例如本地页面服务为http://localhost:8080
,要发送的Ajax请求为http://localhost:4000/api/user
。那么将Ajax请求改为http://localhost:8080/api/user
即可通过服务代理绕过浏览器的同源策略。
由于页面的端口与服务代理的端口一致,所以在发送请求时,可以将
http://localhost:8080/api/user
直接简写为/api/user
。
这种配置方式的服务代理,首先会根据请求路径,在项目的public
目录下寻找对应的资源:
- 如果
public
目录中有请求所对应的资源,那么服务器就直接将该资源发送给浏览器; - 如果
public
目录中没有请求所对应的资源,那么服务器就会将这次请求通过代理的方式完整地转发给proxy
配置的服务器。
例如http://localhost:8080/api/user
:
- 如果
public
目录中有api
目录,并且api
目录下一个名为user
这个资源,那么服务器就直接将user
这个资源发送给浏览器。 - 如果
public
目录中没有api
目录或者有api
目录但是api
目录下没有名为user
的资源,那么服务器就会认为该请求需要走代理。
也就是说,当请求了前端不存在的资源时,请求就会被转发给被代理的服务器(优先匹配前端资源)。
这种配置方式的优缺点如下:
- 优点:配置简单。
- 缺点:不能配置多个代理,不能灵活控制某些请求是否走代理。
完整配置
module.exports = {
devServer: {
proxy: {
'/api': { // 访问代理时的路径前缀
target: '<url>', // 代理的目标路径
ws: true, // 是否支持 webSocket
changeOrigin: true, // 是否将请求头中的Host改成与target一样的Host(默认为true)
},
'/foo': {
target: '<other_url>'
},
}
},
}
例如:
module.exports = {
devServer: {
proxy: {
'/api': { // 路径前缀
target: 'http://localhost:5000', // 代理目标
ws: true,
},
}
},
}
那么在使用代理请求http://localhost:5000
的资源时,除了使用当前服务的Host外,还需要加上路径前缀/api
。即通过http://localhost:8080/api
对http://localhost:5000
的资源进行访问。
在使用http://localhost:8080/api
访问时,代理会将整个访问路径(包括前缀)原封不动地转发给http://localhost:5000
这个服务器。例如请求http://localhost:8080/api/user
那么http://localhost:5000
会接收到/api/user
这个请求。
如果在转发时要将路径前缀去掉(例如请求http://localhost:8080/api/user
,http://localhost:5000
接收到的是/user
请求),可以配置路径转发规则pathRewrite
:
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://localhost:5000',
pathRewrite: { // 路径转发规则
// key:用于匹配路径的正则匹配表达式
// value:是替换路径中匹配的内容
'^/api': '',
},
ws: true,
changeOrigin: true,
},
}
},
}
在微服务架构中,一个服务使用一台(或多台)服务器运行,那么可以根据服务来精简配置项。例如:
module.exports = {
devServer: {
proxy: {
'/users': { // http://localhost:5000/users
target: 'http://localhost:5000',
},
'/orders': { // http://localhost:5001/orders
target: 'http://localhost:5001',
},
}
},
}
使用完整配置时的优缺点如下:
- 优点:可以配置多个代理,可以灵活地控制请求是否使用代理。
- 缺点:配置略繁琐,请求资源时必须使用路径前缀。
评论