vue axios跨域(CORS) Request Method: OPTIONS问题(预检请求)
我们在vue开发中用axios进行跨域请求时有时会遇到,同一个接口请求了两次,并且第一次都是options请求,然后才是post/get请求
options请求
get请求为什么会出现这种原因呢?
这是因为CORS跨域分为 简单跨域请求和复杂跨域请求;
简单跨域不会发送options请求,复杂跨域会发送一个预检请求options。
简单跨域满足的条件
1.请求方式是以下三种之一:
HEAD
GET
POST
2.HTTP的头信息不超出以下几种字段
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type
但是Content-Type的值,只限于三个值:
application/x-www-form-urlencoded、multipart/form-data、text/plain
复杂跨域满足的条件
1.请求方法不是GET/HEAD/POST
2. post请求的Content-Type并非application/x-www-form-urlencoded, multipart/form-data, 或text/plain
3.请求设置了自定义的header字段
在header中自定义了字段就会触发options预检请求
// 请求拦截器
service.interceptors.request.use(
config => {
if (store.getters.token) {
config.headers['Content-MD5'] = 'MD5'
config.headers['authToken'] = getToken()
config.headers['accessTokenRetireTime'] = getTokenTime()
}
return config
},
error => {
console.log(error) // for debug
return Promise.reject(error)
}
)
解决方案
使用qs
1.可以通过跟后端协调,将所有options放行,此时便能通过post/get请求访问到数据。
2.引入qs模块处理数据
qs.parse()将URL解析成对象的形式
qs.stringify()将对象 序列化成URL的形式,以&进行拼接
1.安装qs
npm install qs
2.在main.js引入qs
import qs from 'qs';
Vue.prototype.$qs = qs;
3.vue实例组件里都可以直接用this.$qs.stringify(要处理的数据),进行数据转换
个人倾向第一种方法,如果用第二种方法对前后端来说比较繁琐。
//axios配置
import axios from 'axios'
import qs from 'qs'
// 添加响应拦截器
axios.interceptors.request.use(
config => {
if (config.method === 'post') {
config.data = qs.stringify(config.data)
}
return config
},
error => {
console.log(error)
Promise.reject(error)
}
)
这里我们看一下,其实就是在 axios 发起请求的前拦截请求,当请求类型是 post 的时候,把请求的入参数据 qs.stringify 一下,看一下前后数据格式的对比。
// qs.stringify 前
{
"userId": "520b0ec329164dd9a4f216ba8d209029",
"startTime": "1548950400000",
"endTime": "1551369599999"
}
// qs.stringify 后
"userId=520b0ec329164dd9a4f216ba8d209029&startTime=1548950400000&endTime=1551369599999"
复制代码
这时候再去看后台我发起的请求, OPTIONS 已经不存在啦,只发起了一次正常的 post 请求
使用Access-Control-Max-Age
这里说一个最简单的解决方法,只要后端同学在设置跨域请求数据的时候,添加 Access-Control-Max-Age ,这个参数的意思是把 OPTIONS 缓存起来,在指定的时间内,不会再次发起 OPTIONS 预请求,这样只有在第一次请求的时候会有 OPTIONS ,如果这个时间拉的足够长,其实并不太损耗资源,这算是一个迂回解决的方法。
// 后端设置,2592000单位秒,这里是30天
response.addHeader( "Access-Control-Max-Age", "2592000" )
复制代码
在控制台开启 Disable cache ,可以看到请求中还有 OPTIONS ,关闭 Disable cache 之后,再看请求已经没有了 OPTIONS
补充知识:vue当中axios调取后台数据 以及设置自定义请求头
从vue2.0开始vue-resource就不再维护了,尤大大开始推荐使用 axios。 具体详细教程可在官网查阅,这篇文章主要说明一些简单的问题。
第一步:安装axios
$ npm install axios
第二步:在 main.js中引入axios
第三步:设置我们自定义的 头请求;
header也可以在我们具体的请求中添加 header参数,我们这里是在main.js中添加公众的。
axios.defaults.timeout = 5000;
//请求超时的时间设定
axios.defaults.headers.post['Content-Type'] = 'application/json';
//axios默认的请求方式,可以自己设置
axios.defaults.baseURL = 'http://localhost:8008';
//axios默认的请求地址,开发时可以实际的接口地址来设置该值,去请求别人的接口(前提是后台已经帮你解决了接口的跨域问题,如果没有,我们自己可以代理转发解决开发跨域的问题)
axios.defaults.headers.common["token"] = "aaaaaaaaaaa";
本文来自博客园,作者:JackieDYH,转载请注明原文链接:https://www.cnblogs.com/JackieDYH/p/17634403.html