浏览器预检请求

在 web 开发时遇到 preflight CORS 跨域错误,如下图所示

所谓 preflight CORS,就是在使用跨域请求时,浏览器会先发送一个预检请求,也被称为 OPTIONS 请求,来确认服务器是否支持特定的请求方法、请求头、以及是否允许跨域请求。

本文来分析分析这个预检请求到底有啥用,以及为什么会出现跨域失败的情况。

什么是预检请求?

预检请求是浏览器在发送跨域请求时,在正式请求之前,向服务器发送的一个 HTTP OPTIONS 请求。预检请求的主要目的是为了确定服务器是否支持特定的请求方法、请求头、以及是否允许跨域请求。预检请求的响应中包含了支持的请求方法、请求头以及是否允许跨域请求的信息,如果服务器支持这些请求,则浏览器才会发送真正的请求。

所以,如果出现预检请求跨域失败的情况,一般可以通过以下几个方面进行排查:

  • 服务端是否支持预检请求;
  • 服务端是否支持特定的请求方法、请求头、以及是否允许跨域请求。
  • 服务端是否正确返回了预检请求的响应。

为什么要有预检请求?

在 Web 开发中,由于浏览器的同源策略限制,跨域请求是一个很常见的问题。如果没有预检请求,浏览器就不能确定服务器是否支持特定的请求方法、请求头、以及是否允许跨域请求。这时浏览器会发出一个简单请求(比如 GETPOST 请求),服务器会拒绝该请求并返回错误信息。为了解决这个问题,引入了预检请求机制,用来确认服务器是否支持跨域请求,并根据响应信息决定是否发送真正的请求。

触发预检请求的条件

当满足以下条件时,浏览器会触发预检请求:

1、请求方法不是 GETHEADPOST 中的一种;

2、只能使用安全的请求头;

请求头 说明
Accept 指定客户端能够接收的内容类型
Accept-Language 指定客户端能够接收的语言
Content-Language 指定请求体中的语言
DPR 指定设备的像素比
Downlink 指定设备的下行速度
Save-Data 指定是否启用节省数据模式
Viewport-Width 指定设备的视口宽度
Width 指定设备的屏幕宽度
Content-Type 指定请求体的内容类型,只能使用 application/x-www-form-urlencodedmultipart/form-datatext/plain 中的一种

3、发送的请求数据是不可序列化的数据类型,比如 BlobFile 等。

预检请求的响应

当浏览器发送预检请求时,服务器需要返回以下信息:

  • Access-Control-Allow-Origin:指定允许跨域访问的域名;
  • Access-Control-Allow-Methods:指定允许的 HTTP 方法;
  • Access-Control-Allow-Headers:指定允许的请求头;
  • Access-Control-Allow-Credentials:指定是否允许发送 Cookie;
  • Access-Control-Max-Age:指定响应缓存时间。

如果服务器返回的信息不符合要求,浏览器将不会发送真正的请求,而是返回一个错误信息。

预检请求的缓存

由于预检请求的响应信息是不变的,所以可以进行缓存。服务器可以在响应中添加 Access-Control-Max-Age 头信息,来指定响应的缓存时间,避免重复发送预检请求。

预检请求的限制

预检请求可能会对性能产生一定的影响,因为每次跨域请求都需要发送一个额外的预检请求。为了避免这个影响,可以通过以下几个方面进行优化:

  1. 使用简单请求:对于满足条件的请求(请求方法为 GETHEADPOST,没有自定义请求头),可以使用简单请求来避免预检请求。
  2. 减少跨域请求:尽量减少跨域请求的次数,可以通过将静态资源放在同一域名下,或者使用 CDN 来提高性能。
  3. 缓存预检请求的响应:可以使用 Access-Control-Max-Age 头信息来缓存预检请求的响应,避免重复发送预检请求。
  4. 减少请求头的使用:尽量减少使用自定义请求头,避免触发预检请求。

结语

预检请求是解决跨域请求的一个重要机制,它可以确保浏览器发送的请求是安全的,并且服务器也能够正确地处理这些请求。预检请求虽然会对性能产生一定的影响,但可以通过减少跨域请求、缓存预检请求的响应、减少请求头的使用等方式进行优化,提高性能。合理的使用预检请求,可以帮助我们更好地解决跨域请求的问题。

相关推荐
gqkmiss5 分钟前
Chrome 浏览器 131 版本开发者工具(DevTools)更新内容
前端·chrome·浏览器·chrome devtools
敲代码的彭于晏2 天前
除了localStorage、sessionStorage,了解Cache Storage吗?
前端·浏览器·pwa
gqkmiss3 天前
Chrome 浏览器 131 版本新特性
前端·chrome·浏览器·chrome 131
日升_rs3 天前
Chrome 浏览器 131 版本新特性
前端·chrome·浏览器
明里灰5 天前
从浏览器地址栏输入url到显示页面的步骤
前端·浏览器
jyl_sh8 天前
WebKit(适用2024年11月份版本)
前端·浏览器·客户端·webkit
lrlianmengba13 天前
推荐一款大学生都爱用的浏览器:twinkstar
浏览器
羊小猪~~13 天前
前端入门一之DOM、获取元素、DOM核心、事件高级、操作元素、事件基础、节点操作
前端·javascript·css·vscode·html·浏览器·edge浏览器
就是我14 天前
浏览器的启发式缓存实际上会缓存多久
前端·浏览器
angelanana19 天前
【V8引擎blog翻译-191】迭代器助手
浏览器·v8