1.什么是跨域
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域,所以跨域只存在于开发者模式中
2.前端如何用proxy解决跨域
注意:首先proxy是根据axios发出的请求url(此url是baseURL(如果你写了)和index.js文件里传输的url拼接一起的)来识别,而且全路径是不会被识别的,这是代理内部自己做的判断。
(1).第一种方法
request.js文件
const axiosInstance = axios.create({
withCredentials: true,
timeout: 180000
});
// 请求拦截添加时间戳
axiosInstance.interceptors.request.use(config => {
console.log(config,"请求拦截器")
if (config.retry) {
return config;
}
let baseUrl = process.env.VUE_APP_API_URL;
if (process.env.NODE_ENV === 'development' && config.proxyFlag) {
// 当处于开发模式并且配置了本地代理,无需 baseUrl 作为基础路径
// 根据接口配置中定义的 “proxyFlag--代理标识”,使用对应的代理配置
config.url = config.proxyFlag + config.url;
baseUrl = '';
} else if (isURL(config.url)) {
// 接口地址是一个完整 url 的情况,就不需要 baseUrl 作为基础路径
baseUrl = '';
} else if (config.baseURL) {
// 接口配置中存在自己的 baseUrl U的情况,就不使用默认的 baseUrl 作为基础路径
baseUrl = config.baseURL;
}
let queries = '';
let url = config.url;
if (config.responseType === 'upload') {
config.timeout = 200000;
}
if (url.indexOf('?') < 0) {
queries = '?_t=';
} else if (config.params) {
queries = '&_t=';
} else {
queries = '_t=';
}
return {
...config,
url: baseUrl + url + (config.withTimeStamp ? (queries + (+new Date())) : '')
};
}, error => {
Promise.reject(error);
});
index.js文件(接口文件)
export function checkId(data) {
return request({
url: '/route/checkId',
method: 'post',
proxyFlag: '/sysApi',
contentType: 'application/x-www-form-urlencoded',
data
});
}
.env.development文件
NODE_ENV=development
# 页面环境
VUE_APP_ENV=development
# 接口环境
VUE_APP_API_ENV=development
# 页面地址
VUE_APP_BASE_URL=http://localhost:9527
# 页面基础路径
VUE_APP_PUBLIC_PATH=/
# 业务接口地址
VUE_APP_API_URL=https://abc.abc.com/dcapi
vue.config.js文件
devServer: {
port: port,
open: true,
overlay: {
warnings: false,
errors: true
},
proxy: {
'/sysApi': {
target: 'https://127.0.0.1',
pathRewrite: {
'^/sysApi': ''
}
},
}
},
(2).第二种方法
request.js文件
const axiosInstance = axios.create({
withCredentials: true,
timeout: 180000
});
const NODE_ENV = process.env.NODE_ENV;
const BASE_URL = process.env.VUE_APP_API_URL;
export const proxyName = '/dev-api';
// 请求配置再加工
function requestConfigWrapper(config) {
// 重新请求
if (config.retry) {
return config;
}
let baseUrl = BASE_URL;
let requestPath = config.url;
// 当处于开发模式并且配置了本地代理,无需 baseUrl 作为基础路径
// 根据接口配置中定义的 “proxyName--代理名称”,使用对应的代理配置
if (NODE_ENV === 'development') {
if (config.proxyName) {
requestPath = config.proxyName + requestPath;
baseUrl = '';
}
}
// 接口地址是一个完整 url 的情况,就不需要 baseUrl 作为基础路径
if (isURL(requestPath)) {
baseUrl = '';
}
// 接口配置中存在自己的 baseUrl 的情况,就不使用默认的 baseUrl 作为基础路径
if (config.baseURL) {
baseUrl = config.baseURL;
}
// 设置请求时间戳
let timeStamp = '';
if (requestPath.indexOf('?') < 0) {
timeStamp = '?_t=';
} else if (config.params) {
timeStamp = '&_t=';
} else {
timeStamp = '_t=';
}
// 设置上传文件的响应超时
if (config.responseType === 'upload') {
config.timeout = 200000;
}
return {
...config,
url: baseUrl + requestPath + (timeStamp + (+new Date()))
};
}
// 请求拦截
axiosInstance.interceptors.request.use(config => {
return requestConfigWrapper(config);
}, error => {
Promise.reject(error);
});
index.js文件(其中的proxyName是request.js文件)
import request, { proxyName } from '@/utils/request';
export function queryList(data) {
return request({
url: '/monitor/config/list',
method: 'post',
proxyName,
data
});
}
.env.development文件
NODE_ENV=development
# 页面环境
VUE_APP_ENV=development
# 接口环境
VUE_APP_API_ENV=development
# 页面地址
VUE_APP_BASE_URL=http://localhost:9527
# 页面基础路径
VUE_APP_PUBLIC_PATH=/
# 业务接口地址
VUE_APP_API_URL=http://127.0.0.1:9507
vue.config.js文件
devServer: {
port: port,
open: true,
overlay: {
warnings: false,
errors: true
},
proxy: {
'/dev-api': {
onProxyRes: function (proxyRes, req, res) {
console.log('代理信息------------------------------');
console.log(proxyRes);
console.log('请求信息------------------------------');
console.log(req);
console.log('响应信息------------------------------');
console.log(res);
},
target: process.env.VUE_APP_API_URL,
pathRewrite: {
'^/dev-api': ''
}
}
}
},
(3).第三种方法(若依和vue-element-admin都使用的方法)
request.js文件
// 创建axios实例
const service = axios.create({
// axios中请求配置有baseURL选项,表示请求URL公共部分
baseURL: process.env.VUE_APP_BASE_API,
// 超时
timeout: 10000
})
// request拦截器
service.interceptors.request.use(config => {
console.log(config,"请求拦截器")
// 是否需要设置 token
const isToken = (config.headers || {}).isToken === false
// 是否需要防止数据重复提交
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
if (getToken() && !isToken) {
config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
}
// get请求映射params参数
if (config.method === 'get' && config.params) {
let url = config.url + '?' + tansParams(config.params);
url = url.slice(0, -1);
config.params = {};
config.url = url;
}
if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
const requestObj = {
url: config.url,
data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
time: new Date().getTime()
}
const sessionObj = cache.session.getJSON('sessionObj')
if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
cache.session.setJSON('sessionObj', requestObj)
} else {
const s_url = sessionObj.url; // 请求地址
const s_data = sessionObj.data; // 请求数据
const s_time = sessionObj.time; // 请求时间
const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交
if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
const message = '数据正在处理,请勿重复提交';
console.warn(`[${s_url}]: ` + message)
return Promise.reject(new Error(message))
} else {
cache.session.setJSON('sessionObj', requestObj)
}
}
}
return config
}, error => {
console.log(error)
Promise.reject(error)
})
index.js文件
import request from '@/utils/request'
// 查询字典类型列表
export function listType(query) {
return request({
url: '/system/dict/type/list',
method: 'get',
params: query
})
}
vue.config.js文件
// webpack-dev-server 相关配置
devServer: {
host: '0.0.0.0',
port: port,
open: true,
proxy: {
// detail: https://cli.vuejs.org/config/#devserver-proxy
[process.env.VUE_APP_BASE_API]: {
target: `http://localhost:8080`,
changeOrigin: true,
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: ''
}
}
},
disableHostCheck: true
},
.env.development文件
# 页面标题
VUE_APP_TITLE = 若依管理系统
# 开发环境配置
ENV = 'development'
# 若依管理系统/开发环境
VUE_APP_BASE_API = '/api'
# 路由懒加载
VUE_CLI_BABEL_TRANSPILE_MODULES = true
(4).第四种方法
request.js文件
const BASE_URL = '/admin/api';
axios.defaults.withCredentials = true;
const axiosInstance = axios.create({
baseURL: BASE_URL,
withCredentials: true,
timeout: 600000
});
// 请求拦截添加时间戳
axiosInstance.interceptors.request.use(config => {
let queries = '';
// let url = config.baseURL + config.url;
let url = config.url;
if (config.responseType === 'upload' || config.responseType === 'blob') {
config.timeout = 200000;
}
if (url.indexOf('?') < 0) {
queries = '?_t=';
} else if (config.params) {
queries = '&_t=';
} else {
queries = '_t=';
}
return {
...config,
url: url + queries + (+new Date())
};
}, error => {
Promise.reject(error);
});
index.js文件
import httpRequest from '../request';
delete(options) {
return httpRequest({
url: '/dict/deleteInfo/' + options,
contentType: 'application/x-www-form-urlencoded',
method: 'get',
});
},
vue.config.js文件(此时的拦截器名称你可以命名为)
devServer: {
port: port,
open: true,
overlay: {
warnings: false,
errors: true
},
proxy: {
'/admin': {
target: process.env.VUE_APP_API_URL,
changOrigin: true,
ws: true,
pathRewrite: {
'^/admin': ''
}
}
}
},
env.development文件
NODE_ENV=development
# 页面环境
VUE_APP_ENV=local
# 接口环境
VUE_APP_API_ENV=local
# 页面地址
VUE_APP_BASE_URL=http://localhost:9030/api
# 页面基础路径
VUE_APP_PUBLIC_PATH=/
# 业务接口地址
VUE_APP_API_URL=http://192.168.200.95:9505
注:
我们上面的配置('/api': 'http://localhost:8000'
)本质上会将 /api
映射成 http://localhost:8010/api
,而不是我们希望的 http://localhost:8010
这个映射结果。如果我们希望映射的结果中不带这个 /api
,就需要通过 pathRewrite
属性重写路径,因此,'/api'
后面跟得一般不是字符串
第一种情况
1.要理解pathRewrite,首先要明白proxyTable下‘/api’的作用。
使用代理, 首先需要有一个标识, 标明哪些连接需要使用代理,只有有标识的连接才用代理。”/api”就是告知,接口以”/api”开头的才用代理,所以写请求接口时要使用“/api/xx/xx”的形式,使用代理后生成的请求路径就是’http://localhost:8083/api/xx/xx’.
2.pathRewrite中 “^/api”:""的作用
当实际需要请求的路径里面没有”/api“时. 就需要 pathRewrite,用’’^/api’’:’’, 把’/api’去掉, 这样既能有正确标识, 又能在请求到正确的路径。
第二种情况
使用代理, 首先需要有一个标识, 标明哪些连接需要使用代理,只有有标识的连接才用代理。
比如请求的url='/ab/admin/list' ,跨域的标识可以为'/ab','admin','/list',及url只要包含标识就可以了
但我试的第一个不能重定向到空
'/ab': {
target: process.env.VUE_APP_API_URL,
changOrigin: true,
pathRewrite: {
'^/ab': '/ab'
}
}
'/admin': {
target: process.env.VUE_APP_API_URL,
changOrigin: true,
pathRewrite: {
'^/admin': ''
}
}
'/list': {
target: process.env.VUE_APP_API_URL,
changOrigin: true,
pathRewrite: {
'^/list': ''
}
}