前端涨薪功法:CORS策略中post为什么会发送两次请求?
CORS策略下,为什么Post请求会发送两次?
在前后端分离的Web应用中,我们常用CORS(跨域资源共享)策略来解决跨域问题。但是在使用CORS时,有些同学发现Post请求会发送两次,这篇博客就来分析原因以及解决方法。
CORS简介
CORS需要浏览器和服务器同时支持,关键步骤是:
- 浏览器发送预检请求,询问服务器是否允许跨域;
- 服务器响应,明确指出允许的方法和头信息;
- 浏览器确认可以跨域,发送真正的请求。
为什么会发送两次请求?
要启用CORS,需要服务器设置Access-Control-Allow-Origin等响应头。
如果未正确配置,第一次Post会触发预检请求:
POST https://api.example.com
// 预检请求
OPTIONS https://api.example.com
预检请求用于询问服务器是否允许跨域Post请求。如果服务器未响应,则浏览器阻止第二次Post发送。
配置响应头后,预检就通过了,浏览器就会发送第二次真实的Post请求。
所以 CORS 策略会导致 Post 需要发送两次请求。
如何避免两次请求?
要避免CORS发送两次请求,可以采取以下方法:
- 使用相同的域名和端口:CORS是跨域资源共享,因此如果你的前端代码和后端API位于相同的域名和端口下,就不会触发跨域请求,也就不会发送预检请求。这种情况下,POST请求只会发送一次。
- 配置服务器允许简单请求:CORS规范中规定了一些情况下的简单请求,不会触发预检请求。如果你的请求符合简单请求的条件,服务器可以配置响应头部信息,允许这些简单请求。简单请求的条件包括请求方法是GET、HEAD、POST之一,且请求头部只包含一些特定的字段,例如Accept、Accept-Language、Content-Language、Content-Type(只限于application/x-www-form-urlencoded、multipart/form-data、text/plain)等。通过配置服务器响应头部的Access-Control-Allow-Origin字段,允许请求的来源域,可以避免发送预检请求。
- 配置服务器允许特定的自定义请求头部:如果你的请求需要自定义头部信息,例如Authorization等,会触发预检请求。在服务器的响应头部信息中,添加Access-Control-Allow-Headers字段,指定允许的自定义头部信息列表,可以避免发送预检请求。
- 调整前端请求的头部信息:如果你有控制前端代码,可以尝试调整请求的头部信息,以使其符合简单请求的条件。例如,避免发送自定义的头部信息,或者使用合适的Content-Type值。
需要注意的是,上述方法只能在你有控制服务器端和前端代码的情况下实施。如果你无法更改服务器端的配置或者无法控制前端代码,可能需要与后端开发人员沟通,以寻找其他解决方案,例如使用代理服务器或者JSONP等技术手段来规避CORS问题。
服务器只要响应预检请求,明确指出允许跨域请求即可。
例如 Express可以这样配置:
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Content-Type");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
next();
});
配置好服务器响应跨域头后,预检就可以通过,浏览器会直接发送Post而不用两次请求。
考察点
基本的网络请求原理
总结
CORS策略会触发预检请求,如果服务器未正确响应,就会导致Post需要发送两次。这篇博客介绍了两次请求的根本原因,以及如何通过服务器端配置来避免这种情况。
希望这篇CORS的技术分析能帮助大家理解两次请求的根本原因,如果还有其他问题欢迎留言讨论!
转载自:https://juejin.cn/post/7270899875022028837