浏览器预检请求

在 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. 减少请求头的使用:尽量减少使用自定义请求头,避免触发预检请求。

结语

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

相关推荐
angelanana5 天前
【V8引擎blog翻译-191】迭代器助手
浏览器·v8
摇光938 天前
[前端面试]浏览器
前端·面试·职场和发展·浏览器
蓝黑202018 天前
Firefox火狐浏览器打开B站视频时默认静音
firefox·浏览器
cxylay19 天前
【PDF文件】默认被某种软件打开,如何进行修改?
edge·pdf·浏览器·pdf默认打开方式·微软pdf·pdf解决问题
shandianchengzi20 天前
【记录】Windows|Windows 修改字体大全(Windows 桌面、VSCode、浏览器)
windows·vscode·浏览器·字体·美化
金色的暴发户21 天前
从输入url到页面渲染?你还在这么回答吗
前端·面试·浏览器
WangConvey25 天前
Vue检测获取最新资源 解决浏览器缓存问题
javascript·vue.js·缓存·浏览器·浏览器缓存
x-cmd1 个月前
x-cmd pkg | carbonyl - 终端图形浏览器,浏览像素版网页
运维·性能优化·rust·嵌入式·终端·浏览器·命令行
aoi1 个月前
打开新窗口时 debugger 拦截,以查看调用栈排查问题
前端·javascript·浏览器
Amd7941 个月前
Nuxt.js 应用中的 kit:compatibility 事件钩子详解
浏览器·开发·应用·nuxt.js·插件·兼容性·钩子