昨天,群里的一位群友 资深全栈开发 无霜 讨论了这个问题,我就想起来我平时也经常遇到这样的现象,但是我忽略了,今天 Mark 一下。
有时候,前端明明只发起了一次 post
请求,但是后端却会收到 2 次请求,其中一个是 option
请求
原因
跨域分为简单跨域请求和复杂跨域请求
简单跨域请求是不会发送 OPTIONS
的,请求的复杂跨域请求才会发送一个预检请求 OPTIONS
复杂跨域请求要满足以下:
- 请求方式不是
GET
、POST
、HEAD
POST
请求的Content-Type
并非application/x-www-form-urlencoded
,multipart/form-data
, 或text/plain
- 请求设置了自定义
header
字段
解决方法
如果不想发送 option 请求可以改为简单请求
比如你的 Content-Type
可能是 application/json 格式,将其改为 application/x-www-form-urlencoded
- 不设置自定义请求头
Content-Type
设置为application/x-www-form-urlencoded
axios.defaults.headers.post["Content-Type"] =
"application/x-www-form-urlencoded";
- 把 json 格式的 data 参数用 qs 序列化成字符串;
import axios from "axios";
import config from "@/config";
import * as util from "utils/common";
import qs from "querystring";
let localUser = util.session("token");
axios.defaults.headers.post["Content-Type"] =
"application/x-www-form-urlencoded";
const instance = axios.create({
timeout: config.timer.connTimeout * 1000,
// 返回数据类型
responseType: "json",
// 表明是否有跨域请求
withCredentials: false,
});
//添加请求拦截器
instance.interceptors.request.use(
function (config) {
// 在发送请求之前做些什么
let data = config.data;
if (data) {
localUser && localUser.token && (data.token = localUser.token);
}
let request = {};
request.jsondata = JSON.stringify(data);
request = qs.stringify(request);
config.data = request;
return config;
},
function (error) {
// 对请求错误做些什么
return Promise.reject(error);
}
);
// 错误处理
instance.interceptors.response.use(
function (response) {
return response;
},
function (error) {
// 对响应错误做点什么
return Promise.reject(error);
}
);
export default instance;
- 其实我们没有必要去避免 OPTIONS 请求,在实际项目中未必都是简单请求,也不是所有预检请求都可以转为简单请求,只需要后台配合设置一下跨域响应头部就可以解决了。
response.addHeader("Access-Control-Allow-Origin", "\*");
response.addHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS,PUT,DELETE");
response.setHeader(“Access-Control-Allow-Headers”, “x-requested-with,Authorization, Content-Type”);
- 减少检查频率(方法由**资深全栈架构师 ZJINH**提供)
header( ' Access-Control-Max-Age', '600'); //10 分钟检查一次