React中如何使用Axios实现与给定curl命令等效的预检请求功能
报错原因
那三个Refused to set unsafe header报错是浏览器的原生安全限制:Origin、Access-Control-Request-Headers、Access-Control-Request-Method属于浏览器自动管控的请求头,禁止前端业务代码手动设置,强行配置就会触发该报错。
CORS预检请求逻辑
OPTIONS类型的CORS预检请求完全是浏览器自动触发、自动处理的,不需要业务代码手动发送,满足以下任意条件的请求才会触发预检:
- 请求方法为GET、HEAD、POST之外的类型
- POST请求的Content-Type不属于
application/x-www-form-urlencoded、multipart/form-data、text/plain三类 - 请求头包含非CORS安全规范的自定义头(比如你示例中的
X-Requested-With就属于自定义头,会触发预检)
你之前的GET请求没有触发预检,是因为GET属于简单请求方法,且GET请求无请求体,你手动添加的Content-Type: application/json并未实际生效,因此不会触发预检逻辑。
等效请求的正确实现
你给出的curl命令是手动构造了预检请求,但真实浏览器场景下不需要手动发送OPTIONS,你只需要正确构造POST上传请求,浏览器会自动生成符合要求的预检请求,和目标curl参数完全一致。
正确代码如下:
import https from 'https'; // Node环境需要引入,浏览器环境无需该配置 const formData = new FormData(); formData.append( "upfile", this.state.selectedFile, // 从文件选择控件获取的mp3文件 this.state.selectedFile.name ); const config = { headers: { // 仅需添加自定义头,浏览器检测到该头会自动触发预检,自动补充Origin、预检相关头 "X-Requested-With": "XMLHttpRequest", }, // 强制使用TLSv1.2,对应curl的--tlsv1.2参数,浏览器环境默认自动协商无需配置,仅Node环境需要 httpsAgent: new https.Agent({ minVersion: 'TLSv1.2' }) } axios.post(`https://api.aicomposer.net:8008/upload`, formData, config) .then((res) => { console.log(res); }) .catch(err => { console.log(err); });
如果是出于测试目的需要手动发送OPTIONS请求,axios本身支持axios.options()方法,无需自行封装:
axios.options(`https://api.aicomposer.net:8008/upload`, { headers: { "X-Requested-With": "XMLHttpRequest" } }).then(res => console.log(res))
配置完成后发送请求,在浏览器网络面板中可以看到浏览器自动先发起了OPTIONS预检请求,头参数和你给出的curl命令完全一致,预检通过后会自动发送真实的文件上传POST请求。
内容的提问来源于stack exchange,提问作者whitebear
相关产品推荐
相关产品推荐

