什么情况下会发起Options请求?

2023年 11月 24日 58.5k 0

引言

在Web开发中,HTTP协议扮演着至关重要的角色,它定义了客户端和服务器之间如何交换数据。本文将详细介绍HTTP协议中的OPTIONS请求方法,并阐述其在实际应用中的重要性。

什么是OPTIONS请求?

首先,我们需要了解什么是OPTIONS请求。OPTIONS是HTTP协议中定义的一种请求方法。这些方法包括GET、POST、PUT、DELETE、HEAD、CONNECT、TRACE以及我们这里讨论的OPTIONS。每种方法都代表不同类型的请求行为。

OPTIONS请求的主要目的不是获取响应主体内容,而是获取信息。这些信息包括服务器支持哪些HTTP方法,或者针对某个URL的跨域资源共享(CORS)设置等。

OPTIONS请求具体做什么?

那么,OPTIONS具体做什么呢?简单来说,当一个客户端发送一个OPTIONS请求到服务器时,它在寻求信息——特别地,它想知道针对某个资源服务器允许哪些HTTP方法。

例如,在浏览器发起一个非简单跨域请求之前(比如PUT或DELETE等),会先发送一个预检(preflight) OPTIONS 请求到目标URL。如果服务器响应表示接受此类操作,则浏览器才会发出实际的非简单跨域请求;否则浏览器将阻止该次网络交互。

预检CORS配置通过以下两个步骤完成:

  • 浏览器首先向服务器发送带有Origin头和Access-Control-Request-Method头(指定真正要使用的HTTP动词)以及可能带有Access-Control-Request-Headers头(指定真正要使用的自定义头部字段) 的 OPTIONS 请求。
  • 服务端收到预检CORS配置后进行判断处理,并返回状态码200以及一系列Access-Control-Allow-*头部字段来告诉浏览器是否可以进行下一步操作。

哪些情况需要发送预检CORS配置?

然而,并不是所有情况下都需要发送预检CORS配置。当满足以下所有条件时被称为"简单请求":

  • 方法为GET, HEAD 或 POST。
  • HTTP 的 header 信息不超过以下几种字段:Accept, Accept-Language, Content-Language, Content-Type (但只限于三个值application/x-www-form-urlencoded, multipart/form-data 或 text/plain)

对于"简单请求"而言,浏览器直接发出CORS请求,在Header 中加入Origin字段即可。

预检请求包含以下头信息:

  • Access-Control-Request-Method:实际要发送给服务器的HTTP方法
  • Access-Control-Request-Headers:实际要发送给服务器额外添加到标准CORS协议上header字段

值得注意是,“复杂”或者“非简单”的跨域POST请求数字类型Content-Type值必须为: application/x-www-form-urlencoded,multipart/form-data 或 text/plain其中之一,否则就会触发预检请求。

如果服务器允许该跨域操作,则返回状态码200,并在响应头中加入Access-Control-Allow-Origin等字段;否则返回相应错误信息。只有当预检成功后才会发起真正的HTTP请求。

OPTIONS请求的另一个重要用途是CORS预检。这是一种由CORS(Cross-Origin Resource Sharing, 跨来源资源共享)机制提供的安全措施。在跨域请求中,浏览器为了保护用户信息不被恶意网站获取,在发送真正的请求前,会先使用OPTIONS方法发出一个HTTP预检请求到服务器,以确认真正的请求是否安全被服务器接收。

应用

如果你正在使用Koa框架,你可以使用koa-cors中间件来处理跨域和OPTIONS请求。以下是一个简单示例:

const Koa = require('koa');
const cors = require('@koa/cors');

const app = new Koa();

app.use(cors({
  origin: '*', // 允许所有源
  allowMethods: ['GET', 'POST', 'DELETE', 'PUT'], // 允许的HTTP方法
  allowHeaders: ['Content-Type'], // 允许的头部字段
}));

app.listen(3000);

在这个示例中,我们通过cors中间件设置了允许所有源、指定HTTP方法以及Content-Type头部。

注意:实际情况下,出于安全考虑,不建议将origin设置为"*"(允许所有源),而应该明确指定允许哪些源进行跨域请求。

一个非简单请求的预检请求通过之后,其他所有非简单请求都不用预检了吗?

不完全是这样的。预检请求的结果会被浏览器缓存一段时间,这个时间长度由服务器端在响应预检请求时通过Access-Control-Max-Age头部字段来指定。也就是说,在这个时间范围内,对于相同的URL、相同的请求方法和头部信息,浏览器不会再次发送预检请求。

但是如果超过了Access-Control-Max-Age所设定的时间,或者你发起了一个新的、与之前不同URL、方法或头部信息的非简单请求,那么浏览器仍然需要发送新的预检请求。

因此,并非所有非简单请求都只需要一次预检。具体还取决于服务器对CORS策略设置以及是否超出了缓存有效期等因素。

写在最后

在实际应用中,OPTIONS请求主要用于两个方面:

  • CORS 预检请求:当我们在进行跨域操作并且满足一定条件(如请求方法非GET/HEAD/POST、Content-Type非application/x-www-form-urlencoded、multipart/form-data或text/plain等)时,浏览器会自动发送一个OPTIONS预检请求。这是为了确认实际的HTTP请求是否可以被服务器接受。此时,服务器需要正确响应OPTIONS请求,并在响应头中包含正确的CORS相关信息。
  • 探索服务器能力:你也可以直接使用OPTIONS来查询服务器支持的HTTP方法。例如,你可能对一个API端点发出OPTIONS请求以查看它支持什么样的HTTP方法。

总结起来说,你可以把OPTIONS看作是询问“我能做什么”,而不直接执行具体操作。理解并合理使用OPTIONS方法,对于我们进行Web开发和维护工作有着重要意义。

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论