前端用proxy解决跨域

1.什么是跨域

当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域,所以跨域只存在于开发者模式中

跨域访问1

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': ''
     }
}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值