HTTP OPTIONS请求详解


HTTP OPTIONS 请求详解

OPTIONS 是 HTTP 协议中一种重要但不太常用的请求方法,它主要用于探测服务器支持的通信选项和能力。本文将详细介绍 OPTIONS 请求的细节、应用场景以及如何处理其返回值,帮助读者全面理解这一”隐形侦探”的工作机制。

OPTIONS 方法的基本概念

HTTP 协议定义了多种请求方法,除了常见的 GET 和 POST 外,还有 OPTIONS、HEAD、PUT、DELETE、TRACE 和 CONNECT 等方法。根据 RFC2616 标准(HTTP/1.1),OPTIONS 方法是一种用于发送”探测”请求的方法,目的是确定针对某个目标地址的请求必须具有怎样的约束。

OPTIONS 方法的官方定义是:用于请求获得由 Request-URI 标识的资源在请求/响应的通信过程中可以使用的功能选项。通过这个方法,客户端可以在采取具体资源请求之前,决定对该资源采取何种必要措施,或者了解服务器的性能。

在语法上,OPTIONS 请求可以针对特定资源或整个服务器:

OPTIONS /index.html HTTP/1.1  // 针对特定资源
OPTIONS * HTTP/1.1           // 针对整个服务器

这两种形式在使用场景上有所不同,星号(*)形式主要用于测试服务器性能或作为”ping”操作。

OPTIONS 请求的具体细节

请求格式

一个标准的 OPTIONS 请求格式如下:

OPTIONS /resource HTTP/1.1
Host: example.com
Accept: */*

这个请求中,OPTIONS 表明请求方法,/resource 指定了客户端想要了解的资源路径,Host 指定请求的目标主机名和端口号,而 Accept 表明客户端能够接受的响应内容类型。

在跨域资源共享(CORS)场景中,OPTIONS 请求还会包含特殊的头部信息:

OPTIONS /resources/post-here/ HTTP/1.1
Host: bar.example
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
Origin: https://foo.example
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type

这里的 Access-Control-Request-Method 告知服务器实际请求将使用 POST 方法,Access-Control-Request-Headers 则说明实际请求会携带 X-PINGOTHER 和 Content-Type 头部。

特殊处理要点

OPTIONS 请求有一些特殊的处理要点:

  1. 该请求方法的响应不能被缓存。
  2. 如果 OPTIONS 请求包含一个正文,则必须有 Content-Type 来指定媒体类型。
  3. 请求头中的 Max-Forwards 用来请求特定代理的处理。

OPTIONS 响应详解

响应格式

服务器对 OPTIONS 请求的响应通常如下所示:

HTTP/1.1 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 0
Content-Type: text/html; charset=UTF-8
Date: Tue, 4 May 2021 9:56:29 GMT
Server: Apache/2.4.46 (Unix)

这个响应中,状态码 200 OK 表示请求成功,Allow 头部列出了服务器允许的 HTTP 方法,这是 OPTIONS 请求的主要目的。由于 OPTIONS 请求通常不返回实体内容,Content-Length 通常为 0。

在 CORS 场景中,响应还会包含额外的头部:

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
Vary: Accept-Encoding, Origin
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive

这些额外的头部信息告知浏览器:允许来自https://foo.example的跨域请求,允许的方法有 POST、GET 和 OPTIONS,允许的请求头部有 X-PINGOTHER 和 Content-Type,预检响应可以缓存 86400 秒(1 天)。

响应状态码

OPTIONS 请求通常会返回以下状态码:

  • 200 OK:表示请求成功,响应中包含了请求的信息。
  • 204 No Content:请求成功但没有返回任何内容。
  • 403 Forbidden:表示服务器理解请求但拒绝执行。
  • 405 Method Not Allowed:表示请求方法不被允许。

OPTIONS 方法的主要应用场景

1. 探测服务器功能

客户端可以通过 OPTIONS 请求来了解服务器支持哪些 HTTP 方法,从而避免发送服务器无法处理的请求。例如,使用 curl 命令发送 OPTIONS 请求:

curl -X OPTIONS https://example.org -i

返回的响应会包含 Allow 头部,表明服务器支持的方法。

2. CORS 预检请求

在现代 Web 开发中,OPTIONS 最常见的应用是作为跨源资源共享(CORS)的预检请求。当浏览器需要向不同源的服务器发送”非简单请求”时,会先自动发送一个 OPTIONS 请求,询问服务器是否允许实际的跨域请求。

非简单请求包括:

  • 使用 PUT、DELETE 等方法
  • 发送自定义头部
  • Content-Type 不是 application/x-www-form-urlencoded、multipart/form-data 或 text/plain 之一

3. RESTful API 元信息发现

在 RESTful API 设计中,OPTIONS 方法可用于提供资源的元信息发现功能。客户端可以通过 OPTIONS 请求获取资源支持的操作列表,甚至包括每个方法的简要说明、参数要求等附加信息。

OPTIONS 响应的处理

处理 Allow 头部

客户端收到 OPTIONS 响应后,首先需要检查 Allow 头部,了解服务器支持的方法列表:

fetch("https://example.com/resource", {
  method: "OPTIONS",
})
  .then((response) => {
    const allowedMethods = response.headers.get("Allow");
    console.log("服务器支持的方法:", allowedMethods);
    // 根据支持的方法决定下一步操作
  })
  .catch((error) => console.error("错误:", error));

处理 CORS 预检响应

浏览器会自动处理 CORS 预检请求的响应。开发者需要关注的是确保服务器正确返回所需的 CORS 头部。服务器端的响应应当包含:

  • Access-Control-Allow-Origin:允许请求的来源
  • Access-Control-Allow-Methods:允许的 HTTP 方法
  • Access-Control-Allow-Headers:允许的请求头部
  • Access-Control-Max-Age:预检请求的有效期(秒)

如果预检请求失败(如服务器没有返回正确的 CORS 头部),浏览器将阻止后续的实际请求,并在控制台显示错误。

OPTIONS 响应缓存

虽然 OPTIONS 响应本身不可缓存,但 CORS 预检响应可以通过 Access-Control-Max-Age 头部指定缓存时间,减少预检请求的频率。例如,Access-Control-Max-Age: 86400 表示该预检响应可以缓存一天,在此期间对同一资源的类似请求不会再触发预检请求。

结论

OPTIONS 请求是 HTTP 协议中一个非常实用但容易被忽视的方法。它在服务器功能探测、CORS 预检和 API 元信息发现等场景中扮演着重要角色。通过本文的详细介绍,相信读者已经对 HTTP OPTIONS 请求的细节、用途以及如何处理其响应有了全面的理解。

在实际开发中,尤其是涉及跨域请求的场景,合理配置 OPTIONS 请求的响应头部对于确保应用的正常运行至关重要。同时,了解 OPTIONS 方法也有助于我们设计更加符合 RESTful 风格的 API,提供更好的服务发现能力。