在Vue项目中我们通常通过Axios进行接口请求,本地开发时可能需要通过devServer进行跨域处理。今天来梳理一下。
XMLHttpRequest请求接口
当我们在项目中通过axios或者直接通过XMLHttpRequest发送网络请求时,如果url没有协议、域名端口,直接通过相对路径请求,例如直接是”/api/…..”,我们通过控制台的network可以发现Request URL是”http://localhost:****/api/….”,协议、域名端口与当前页面地址栏显示的协议、域名端口是一致的。也就是说当我们进行网络请求却没有指定域名或服务器地址时,浏览器自动将当前网站的域名或服务器地址作为请求。
跨域
跨域限制是因为浏览器的一个安全策略-同源策略,它限制了从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。只有两个请求地址的协议域名端口完全一致的情况下,才能被浏览器认为同源。默认情况下,浏览器不允许非同源之间进行交互。
在本地进行Vue项目开发时,我们访问的域名一般都是localhost,而一般前后端都是由不同的人进行开发,后端程序并没有运行在同一台电脑上时,我们访问接口就会因为域名不同发生跨域问题,在控制台我们可以看到请求状态为failed。
解决跨域问题主要有两种方式,一是CORS,这是一个W3C的标准,全称是跨域资源共享,这是处理跨域问题的标准做法。对于简单请求需要后端设置response的Header:”Access-Control-Allow-Origin”:”*”,非简单请求还要增加’Access-Control-Request-Method’:’PUT,POST,GET,DELETE,OPTIONS’和’Access-Control-Allow-Headers’, ‘Origin, X-Requested-With, Content-Type, Accept, t’。如果请求中需要携带cookie,后端要指定origin为明确的地址,不能为*,同时前后端设置’Access-Control-Allow-Credentials’:true
另一种方式是设置代理,避免直接通过浏览器向后端发送请求,而是将请求发送到同源的代理服务器,由代理服务器向后端发送请求并将返回结果转发给浏览器。比如配置nginx服务器,监听网站所在的域名端口,并转发到正确的服务器地址。
server{
# 监听9099端口
listen 9099;
# 域名是localhost
server_name localhost;
#凡是localhost:9099/api这个样子的,都转发到真正的服务端地址http://localhost:9871
location ^~ /api {
proxy_pass http://localhost:9871;
}
}
而我们在开发Vue项目时更便捷的方式是使用VueCLI的代理服务器。
vue.config.js中devServer的配置
module.exports = {
devServer: {
proxy: {
"/api": {
target: "http://localhost:3333",
ws: true,
pathRewrite: { "^/api": "/" },
},
},
}
}
当我们在vue.config.js中配置了上述代码后,运行项目后回在本地运行一个node代理服务器,它所监听的域名和端口与项目运行地址一致。当我们进行XHR请求的时候,如果请求地址是相对路径或者是本机地址,那么请求就会发送到node代理服务器中,代理服务器将请求转发到target属性配置的地址上。
上面例子中,匹配所有/api开头的请求,并将请求路径中的/api重写为/,然后发送到http://localhost:3333,同时支持websocket请求。
pathRewrite 重写target的URL路径。对象键将用作RegExp来匹配路径。
pathRewrite: {'^/old/api' : '/new/api'}
// remove path
pathRewrite: {'^/remove/api' : ''}
// add base path
pathRewrite: {'^/' : '/basepath/'}
// custom rewriting
pathRewrite: function (path, req) { return path.replace('/api', '/base/api') }
router针对特定请求重新定位target。
router: {
'integration.localhost:3000' : 'http://localhost:8001', // host only
'staging.localhost:3000' : 'http://localhost:8002', // host only
'localhost:3000/api' : 'http://localhost:8003', // host + path
'/rest' : 'http://localhost:8004' // path only
}
更多配置选项参见 http-proxy-middleware