跨域POST请求发送两次请求的情况详解

在制作golang组件的过程中,打算开发一个小工具用来配置组件的参数,后台用到了beego。在此期间遇到了一个问题:我在发送一个post请求时,在控制台总会看到两次请求,于是打算进一步地了解一下请求机制,并消去多余的HTTP请求。

请求头:


golang

可以看到Request Method是OPTIONS,而不是POST,同时也没有对应的参数,看了网上的说法才了解到,第一次请求是用来进行预检,检查你是否有权限去进行此次的POST请求,而第二次请求就是正确的POST的请求了:


golang

beego的设置:

beego.InsertFilter("*", beego.BeforeRouter, cors.Allow(&cors.Options{
AllowOrigins: []string{"http://dtsvr-tool.oa.com"},
AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
AllowHeaders: []string{"Origin", "Authorization", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Content-Type"},
ExposeHeaders: []string{"Content-Length", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Content-Type"},
AllowCredentials: true,
}))

而有次校验的原因是我发送了一个非简单请求,也是头一次听说这个词,于是就搜索了一哈:

  • 非简单请求:只使用 GET, HEAD 或者 POST 请求方法。如果使用 POST 向服务器端传送数据,则数据类型 (Content-Type) 只能是 application/x-www-form-urlencoded, multipart/form-data 或 text/plain中的一种。

那按照上述所说,只要把请求改成简单请求就可以了,方法有两个:

  • 将post请求改为get请求
axios.interceptors.request.use(function (config) {
config.withCredentials = true
if (config.method === 'post' && config.data.constructor.name !== 'FormData') {
let params = {}
let str = []
for (let k in config.data) {
if (typeof config.data[k] !== 'function') {
// 参数是对象,并且不为空
if (typeof config.data[k] === 'object') {
params[k] = JSON.stringify(config.data[k])
} else {
params[k] = config.data[k]
}
}
}
Object.keys(params).map(function (key) {
str.push(encodeURIComponent(key) + '=' + encodeURIComponent(params[key]))
})
config.data = str.join('&')
}
// Do something before request is sent
return config
}, function (error) {
// Do something with request error
return Promise.reject(error)
})
  • 将post的header改为application/x-www-form-urlencoded,multipart/form-data或者text/plain
config.headers = 'application/x-www-form-urlencoded;charset=utf-8'

这样我们就可以忽略掉预检请求,而只发送一次请求了。

END