一、为什么要配置跨域代理:
浏览器发送请求,如果域名、协议、端口号不同,就会返回不了数据,这个时候就需要处理跨域问题。
二、跨域代理的原理:
因为服务器端是不受域限制的,所以可以通过本地服务器的代理来绕过浏览器,先请求服务器端,由服务器转发请求到指定的接口,然后由服务器端返回指定的数据。
三、实现:
(1)、配置nodeJs跨域服务
proxy.js文件:
const http=require('http');
const request=require('request');
const hostname='127.0.0.1';
const port=8010;
const imgPort=8011;
// 声明apiServer服务,由此服务向指定的接口发送请求,
// 比如当前发送的请求为http://127.0.0.1:8010/news/3892357,
// 监听到8010这个端口之后,就会执行本服务(apiServer),
// 本服务截取请求里面的req.url(/news/3892357)和指定接口拼接,然后发送请求到此路径
const apiServer=http.createServer((req,res)=>{
//指定的接口+请求里面的资源路径
const url='http://news-at.zhihu.com/api/4'+req.url;
const options={
url:url
};
//回调函数,请求完成之后执行的操作(返回数据到页面)
function callback(error,response,body) {
if (!error && response.statusCode===200){
res.setHeader('Content-Type','text/plan;charset-UTF-8');
res.setHeader('Access-Control-Allow-Origin','*');
res.end(body);
}
}
//用request.get方法,发送请求
request.get(options,callback);
});
//声明图片接口监听服务,原来同上
const imgServer=http.createServer((req,res)=>{
const url=req.url.split('/img/')[1];
const options={
url:url,
encoding:null
}
function callback(error,response,body) {
if (!error && response.statusCode===200){
const contentType=response.headers['content-type'];
res.setHeader('Content-Type',contentType);
res.setHeader('Access-Control-Allow-Origin','*');
res.end(body);
}
}
request.get(options,callback);
});
//监听端口8010,执行apiServer
apiServer.listen(port,hostname,()=>{
console.dir(`接口代理运行在http://${hostname}:${port}/`);
});
//监听端口8011,执行imgServer
imgServer.listen(imgPort,hostname,()=>{
console.dir(`图片代理运行在http://${hostname}:${imgPort}/`);
});
(2)、启动nodeJs跨域服务
node proxy.js
(3)、配置axios
util.js
//引入axios
import axios from 'axios';
//设置api接口和imgPath根路径
const Util={
apiPath:'http://127.0.0.1:8010/',
imgPath:'http://127.0.0.1:8011/img/'
}
//声明axios发送请求的方法ajax
Util.ajax=axios.create({
baseURL:Util.apiPath
});
//声明axios发送请求的方法ajax返回结果后的拦截器
Util.ajax.interceptors.response.use(res=>{
return res.data;
})
//导出Util
export default Util;
(4)、main.js里面全局引入axios,并发送请求
import Vue from 'vue'
import App from './App'
// 引入util.js
import util from './libs/util.js';
Vue.config.productionTip = false;
// 设置全局变量$axios
Vue.prototype.$axios = util;
/* eslint-disable no-new */
new Vue({
el: '#app',
components: { App },
template: '<App/>',
methods:{
login:function () {
var url = "/news/3892357";
// 这里会发送到http://127.0.0.1:8010/news/3892357,
// 然后触发proxy.js的apiServer.listen监听器,执行apiServer,
// 所有最终会发送到http://news-at.zhihu.com/api/4/news/3892357
$axios.ajax.get(url).then(res=>{
console.dir(res);
});
}
},
created() {
this.login();
}
})
(5)、App.vue里面请求图片
<template>
<div id="app">
<img :src="srcUrl">
</div>
</template>
<script>
export default {
name: 'App',
data() {
return{
//全局变量$axios的imgPath(http://127.0.0.1:8011/img/)
url:this.$axios.imgPath
}
},
computed:{
srcUrl(){
// 请求路径为 http://127.0.0.1:8011/img/https://pic3.zhimg.com/30594279d368534c6c2f91b2c00c7806.jpg
// 因为请求了127.0.0.1:8011,根据proxy.js里面的配置,就会触发imgServer.listen监听器,
// 执行imgServer,所有最终的请求路径为:req.url.split('/img/')[1]
// 也就是https://pic3.zhimg.com/30594279d368534c6c2f91b2c00c7806.jpg
return this.url+"https://pic3.zhimg.com/30594279d368534c6c2f91b2c00c7806.jpg";
}
}
}
</script>
<style>
</style>