预检请求

233 阅读2分钟

预检请求(Preflight Request)是浏览器在执行跨域请求前,自动发出的一个 HTTP OPTIONS 请求。预检请求的目的是确保服务器允许实际请求的方法和头部,从而避免跨域请求对服务器产生意外影响。

预检请求主要用于那些对服务器有潜在影响的“复杂请求”(非简单请求),例如:

  1. 使用了非简单方法(如 PUT、DELETE、PATCH、OPTIONS 等,而不是 GET、POST、HEAD)。
  2. 使用了非简单头部(如 Content-Type 为 application/json,而不是 application/x-www-form-urlencoded, multipart/form-data, text/plain)。

预检请求的流程

  1. 浏览器发送预检请求:浏览器首先发送一个 OPTIONS 请求,带有以下 CORS 相关的头部信息:

    • Origin: 发起请求的来源。
    • Access-Control-Request-Method: 实际请求将使用的 HTTP 方法。
    • Access-Control-Request-Headers: 实际请求将使用的自定义头部。
  2. 服务器响应预检请求:服务器检查请求头并返回带有以下头部信息的响应:

    • Access-Control-Allow-Origin: 允许的来源。
    • Access-Control-Allow-Methods: 允许的方法。
    • Access-Control-Allow-Headers: 允许的自定义头部。
    • Access-Control-Allow-Credentials(如果需要):指明是否允许包含凭证。
    • Access-Control-Max-Age(可选):指明结果的缓存时间,以减少预检请求的数量。
  3. 浏览器发送实际请求:如果预检请求得到的响应头部允许实际请求,浏览器会继续发送实际的跨域请求。

预检请求示例

假设我们从 https://example.com 发起一个跨域请求到 https://api.otherdomain.com,并使用了自定义的头部和方法:

预检请求

OPTIONS /some-resource HTTP/1.1
Host: api.otherdomain.com
Origin: https://example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header

预检请求的响应

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 86400

实际请求

如果预检请求通过,浏览器会发送实际请求:

PUT /some-resource HTTP/1.1
Host: api.otherdomain.com
Origin: https://example.com
X-Custom-Header: value
Content-Type: application/json

{ "key": "value" }

实际请求的响应

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true
Content-Type: application/json

{ "response": "success" }

总结

预检请求是 CORS 机制的一部分,用于确保跨域请求在实际发送之前,经过服务器的验证和授权。通过预检请求,浏览器可以获知服务器是否允许某些类型的跨域请求,并获取相应的权限信息,以安全地执行跨域操作。