0%

解决Axios额外的发起一次option请求

昨天,群里的一位群友 资深全栈开发无霜 讨论了这个问题,我就想起来我平时也经常遇到这样的现象,但是我忽略了,今天 Mark 一下。

有时候,前端明明只发起了一次 post 请求,但是后端却会收到 2 次请求,其中一个是 option 请求

原因

跨域分为简单跨域请求复杂跨域请求

简单跨域请求是不会发送 OPTIONS 的,请求的复杂跨域请求才会发送一个预检请求 OPTIONS

复杂跨域请求要满足以下:

  1. 请求方式不是 GETPOSTHEAD
  2. POST 请求的 Content-Type 并非 application/x-www-form-urlencoded, multipart/form-data, 或 text/plain
  3. 请求设置了自定义 header 字段

解决方法

如果不想发送 option 请求可以改为简单请求
比如你的 Content-Type 可能是 application/json 格式,将其改为 application/x-www-form-urlencoded

  1. 不设置自定义请求头
  2. Content-Type 设置为 application/x-www-form-urlencoded
1
2
axios.defaults.headers.post["Content-Type"] =
"application/x-www-form-urlencoded";
  1. 把 json 格式的 data 参数用 qs 序列化成字符串;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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;
  1. 其实我们没有必要去避免 OPTIONS 请求,在实际项目中未必都是简单请求,也不是所有预检请求都可以转为简单请求,只需要后台配合设置一下跨域响应头部就可以解决了。
1
2
3
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”);
  1. 减少检查频率(方法由**资深全栈架构师ZJINH**提供)
1
header( ' Access-Control-Max-Age', '600'); //10分钟检查一次

部分来源