面试官:为什么有时候post会连续发送两次?
发送两次的原因
浏览器发送两次 POST 请求通常是因为 预检请求(Preflight Request) 的原因,这是由于跨域请求时浏览器执行的一种预检操作。
跨域请求是指请求的目标地址与当前页面的地址不同源,即协议、域名或端口号至少有一个不同。在跨域请求中,如果请求是带有自定义头部(例如 Content-Type)或使用了非简单请求方法(例如 POST、PUT、DELETE)的情况下,浏览器会先发送一个预检请求给目标服务器,以确定是否允许实际的请求。
预检请求通常是一个 OPTIONS 请求,用于向服务器确认实际请求是否安全。服务器收到预检请求后,会返回一组响应头,指示浏览器是否允许实际请求。如果服务器确认允许实际请求,则浏览器会发送第二次实际的 POST 请求。
所以,如果你在浏览器的开发者工具中看到两次 POST 请求,一次是 OPTIONS 请求(预检请求),一次是实际的 POST 请求,那么这就是由于跨域请求时浏览器执行的预检操作导致的。
什么情况下只发送一次
在以下情况下,浏览器不会发送两次请求:
- 同源请求:如果请求的目标地址与当前页面的地址同源(即协议、域名和端口号完全相同),则不会发送预检请求,浏览器直接发送实际的 POST 请求。
简单请求:如果请求是一个简单请求,即满足以下条件之一:
- 请求方法为 GET、HEAD 或 POST,并且请求头部不超出一定的限制。
- 请求中只包含简单的头部字段,例如 Content-Type 为 application/x-www-form-urlencoded、multipart/form-data 或 text/plain。
在这些情况下,浏览器不需要发送预检请求,可以直接发送实际的 POST 请求。
什么叫简单请求
简单请求是指在跨域请求中符合一定条件的请求,这些条件主要是为了保证请求的安全性和可预测性。以下是简单请求的主要特征:
请求方法:
- 符合简单请求的请求方法包括:GET、HEAD、POST。
- 如果使用了其他请求方法(如 PUT、DELETE、OPTIONS),则不符合简单请求的条件,需要进行预检请求。
请求头部:
请求头部字段限制在一定范围内,只允许包含少量的字段,例如:
- Accept
- Accept-Language
- Content-Language
- Content-Type(仅限于 application/x-www-form-urlencoded、multipart/form-data、text/plain)
Content-Type:
如果请求包含实体主体(例如 POST 请求),则 Content-Type 头部字段的值必须是以下之一:
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
没有自定义头部:
- 请求中不包含任何自定义头部字段(即非简单请求中定义的头部字段)。
如果一个请求同时满足以上所有条件,则它被认为是一个简单请求。简单请求不会触发浏览器发送预检请求,可以直接发送实际的跨域请求。这样设计的目的是为了在一定程度上减少跨域请求带来的安全风险和性能开销。
本文系作者 @K 原创发布在前端面试题大全站点。未经许可,禁止转载。
暂无评论数据