‘壹’ vue.js使用http-proxy-middleware解决跨域请求问题
最近在使用vue-cli搭建项目的过程中,遇到了跨域请求数据的问题,这里贴出我的解决方法,希望对大家有所帮助。
什么是跨域请求:
如果在A网站中,我们希望使用Ajax来获得B网站中的特定内容,如果A网站与B网站不在同一个域中,那么就出现了跨域访问问题。由于浏览器同源策略,凡是发送请求url的协议、域名、端口三者之间任意一与当前页面地址不同即为跨域。
这里,数据请求用的是vue-resource(目前vue官方是推荐使用axios),安装插件:
npm install--save-devvue-resource
1
在main.js中引入插件:
importVueResourcefrom'vue-resource'
Vue.use(VueResource)
这里,解决跨域使用的是http-proxy-middleware来进行接口代理,安装方法同上:
npm install--save-devhttp-proxy-middleware
下面开始谈正事,举个栗子:
本地项目地址是:localhost:8080,现在我们要访问 http://m.maizuo.com/v4/api/film/comming-soon 和 http://m.maizuo.com/v4/api/billboard/home 这两个线上地址:
首先,设置build/dev-server.js:
varproxyMiddleware =require('http-proxy-middleware')
varserver = express()
server.middleware = [ proxyMiddleware(['/film/coming-soon'], {target:'http://m.maizuo.com/v4/api', changeOrigin:true}), proxyMiddleware(['/billboard/home'], {target:'http://m.maizuo.com/v4/api', changeOrigin:true})];
server.use(server.middleware);
注意,当要访问多个线上地址时,公共的地址部分写在target属性值里面,比如这里的 http://m.maizuo.com/v4/api ,然后[ ]里边写地址的不同部分。
然后,修改config/index.js :
dev:{env:require('./dev.env'), port:8080, proxyTable: {'/api': { target:'http://m.maizuo.com/v4/api', changeOrigin: true, pathRewrite: {'^/api':''} } } }
这里的target同上面的一样,然后’/api’和’^/api’代表的就是这个根目录地址;
然后,在页面中具体的调用为:
this.$http.get('api/billboard/home').then((response) => {
});
这里,url的值为api + [ ] 中的部分 ;
然后,我们就解决了vue中的跨域问题 ;
这里,贴一下http-proxy-middleware插件的github地址,看更多用法 :
https://github.com/chimurai/http-proxy-mid
‘贰’ 如何解决前端跨域问题
可以使用服务器代理或者在后端设置允许跨域。
现在的项目一般是在后端设置允许跨域,前端在带有允许跨域的情况下,可以像没有跨域一样正常访问。
如果前端单独发布到服务器,也可以在服务器是设置代理,使用代理转发请求。
‘叁’ vue 如何实现跨域
跨域问题是因为浏览器的同源策略引起的,一种浏览器的安全机制,要求 协议,域名,端口 ,都要一致!
出于浏览器的同源策略限制,浏览器会拒绝跨域请求。
什么叫跨域?非同源请求,均为跨域。名词解释:同源 —— 如果两个页面拥有相同的协议(protocol),端口(port)和主机(host),那么这两个页面就属于同一个源(origin)。
怎么解决跨域?最常用的三种方式: JSONP、CORS、postMessage 。
jsonp,只支持get,不支持post,需要调用前端和被调用后端配合(比较常用)
后端HttpClient进行转发,两次请求,效率低,安全(类似Nginx反向代理)
服务端设置响应头,允许跨域,适于小公司快速解决问题
Nginx搭建API接口网关
Zuul搭建API接口网关
后四种都属于服务端设置,对于目前还是一个纯前端的我来说,先把前端的搞懂再说,所以在此只说前端
jsonp工作原理理解
jsonp实际上是通过动态插入js的方式实现的跨域,因为通过script标签引入js文件没有跨域一说
web客户端通过调用脚本的方式去调用跨域服务端动态生成的js文件(一般以json为后缀),同时传递一个callback参数给服务端,服务端以这个参数名为函数名,调用此函数以参数的形式将数据传到web端,这样就实现了前端跨域请求服务端数据。
【JSONP的优缺点】
优点:兼容性好(兼容低版本IE)
缺点:1.JSONP只支持GET请求; 2.XMLHttpRequest相对于JSONP有着更好的错误处理机制
CORS :是W3C 推荐的一种新的官方方案,能使服务器支持 XMLHttpRequest 的跨域请求。CORS 实现起来非常方便,只需要增加一些 HTTP 头,让服务器能声明允许的访问来源。
postMessage : window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持 window.postMessage方法。
‘肆’ vue 设置proxyTable解决跨域问题
最近接收一个前后端分离的项目,本地环境启动之后总是报跨域问题:
经过一番费劲心思的排查,发现是浏览器的同源策略不允许跨域访问,所谓同源策略是指协议、域名、端口相同,proxyTable通过代理可以解决这个问题。
在config目录下的index.js设置
上方配置的目的就是将前端请求localhost:3000/api/xxx 代理为localhost:8081/api/xxx
‘伍’ 解决Vue http中的跨域问题
在平常的项目开发当中,很容易遇到跨域的问题,好在vue-cli的脚手架提供了跨域的解决方案,在config下的index.js中有个proxyTable属性,在其中添加如下配置:
proxyTable: {
'/api':{
target:'http://localhost:8090',
changeOrigin:true,
pathRewrite:{
}
}
如上所示,如果在8090后在加路径,则无效(亲测);
在pathRewite中可以添加替换,因为在正常代理过后会在路径结尾有ap这个路径,所以如果实际的地址和这个不同,则可以进行替换。
‘陆’ vue 前端设置跨域多代理
在项目开发的时候经常会遇到后端提供的多个服务请求地址域名或端口号不一致的情况这时候就需要前端设置多个proxy跨域代理,本文以vue-element-admin为例展示步骤如下:
1: 配置环境变量 .env.development
2: 配置项目根目录下的vue.config.js 找到devServer
PS:注意VUE_APP_BASE_API 放在数组的最后一个,如果你VUE_APP_BASE_API跟我一样设置为'' 的话,这样才不会被代理的虚拟path覆盖!
3: 找到项目中管理请求地址的文件 src/api/proxy.js (proxy.js 是我随便起的名字😄)
打开proxy.js
proxy_api 就是你之前在步骤1:中定义的虚拟path
VUE_APP_BASE_API_PROXY = '/proxy-api'
const url = (path) => (proxy_api + path) 一个路径处理函数,参数是'/xx/xxx/fetch/list',return (proxy_api + path)
需要额外注意的是我在配置环境变量 .env.development的时候基础api设置的是空:
所以不需要在src/utils/request.js 中对代理的请求进行拦截
如果你为VUE_APP_BASE_API设置了虚拟path路径,那么就需要在src/utils/request.js为这个虚拟路径配置拦截,比较麻烦比不建议这么做。
至此跨域多代理已经设置完了,本文中设置两个代理一个基础代理VUE_APP_BASE_API,一个额外代理VUE_APP_BASE_API_PROXY,默认情况下走基础代理,当请求匹配到匹'/proxy-api' 时走额外代理~
‘柒’ Vue项目中跨域问题的解决
在Web端Vue项目开发过程中,跨域问题是不可避免的;在我参与的Vue项目中,使用服务器代理的解决方案;针对不同的环境(开发环境/生产环境),采用了不同的服务器代理方案;
服务器代理的原理大概是这样:
代理服务器和访问源(请求端)是同源的,但和被访问服务器(资源端)是不同源的,但服务器之间的访问不受浏览器同源策略的影响(即不必担心是否有跨域问题),那么我们即可请求到同源服务器上的从被访问服务器上的获取到的请求资源了 ;
这样配置完成后,我们发起的每次http请求的Request Url的前面一部分都会和我们本地的源一样;
举例:
我们项目跑在开发环境下的 http://localhost:8080 上,那么上述请求的Request Url的就是 http://localhost:8080/api/bookCate ;这应该就是我们的代理服务器中该资源的地址,与客户端同源;而数据的实际来源则是 http://219.216.5.26:8080/api/bookCate ,这样即实现代理跨域;
目前猜测这个代理服务器可能是Node;
nginx 版本: 1.16.1
修改 nginx.conf 文件下的 serve 下配置:
举例:
生产环境下的,我们项目跑Nginx服务器监听的 http://localhost:8088 上,那么上述请求的Request Url的就是 http://localhost:8088/api/bookCate ;
这应该就是我们的代理服务器中该资源的地址,与客户端同源;
而数据的实际来源则是 http://219.21.5.5:9903/api/bookCate ,这样即实现代理跨域;