简单请求和复杂请求

本文详细介绍了HTTP的CORS(跨源资源共享)中简单请求和复杂请求的区别,涉及头信息、域、预请求等核心概念,以及响应头中Access-Control-Allow-Origin、Access-Control-Allow-Methods等的处理策略。

一、简单请求

请求方法是以下三种方法之一:

  • HEAD
  • GET
  • POST

HTTP的头信息不超出以下几种字段:

Content-Type的值只有以下三种(Content-Type一般是指在post请求中,get请求中设置没有实际意义)

  • text/plain
  • multipart/form-data
  • application/x-www-form-urlencoded

简单请求的发送从代码上来看和普通的XHR没太大区别,但是HTTP头当中要求总是包含一个域(Origin)的信息。该域包含协议名、地址以及一个可选的端口,不过这一项实际上由浏览器代为发送 

简单请求的部分响应头及解释如下:

Access-Control-Allow-Origin(必含)- 不可省略,否则请求按失败处理。该项控制数据的可见范围,如果希望数据对任何人都可见,可以填写"*"。
Access-Control-Allow-Credentials(可选) – 该项标志着请求当中是否包含cookies信息,只有一个可选值:true(必为小写)。如果不包含cookies,请略去该项,而不是填写false。这一项与XmlHttpRequest2对象当中的withCredentials属性应保持一致,即withCredentials为true时该项也为true;withCredentials为false时,省略该项不写。反之则导致请求失败。
Access-Control-Expose-Headers(可选) – 该项确定XmlHttpRequest2对象当中getResponseHeader()方法所能获得的额外信息。通常情况下,getResponseHeader()方法只能获得如下的信息:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma

二、复杂请求

非简单请求即为复杂请求。复杂请求我们也可以称之为在实际进行请求之前,需要发起预检请求的请求。

复杂请求表面上看起来和简单请求使用上差不多,但实际上浏览器发送了不止一个请求。其中最先发送的是一种"预请求",此时作为服务端,也需要返回"预回应"作为响应。预请求实际上是对服务端的一种权限请求,只有当预请求成功返回,实际请求才开始执行。

 预请求以OPTIONS形式发送,当中同样包含域,并且还包含了两项CORS特有的内容:

Access-Control-Request-Method – 该项内容是实际请求的种类,可以是GET、POST之类的简单请求,也可以是PUT、DELETE等等。
Access-Control-Request-Headers – 该项是一个以逗号分隔的列表,当中是复杂请求所使用的头部。

显而易见,这个预请求实际上就是在为之后的实际请求发送一个权限请求,在预回应返回的内容当中,服务端应当对这两项进行回复,以让浏览器确定请求是否能够成功完成。

复杂请求的部分响应头及解释如下:

Access-Control-Allow-Origin(必含) – 和简单请求一样的,必须包含一个域。
Access-Control-Allow-Methods(必含) – 这是对预请求当中Access-Control-Request-Method的回复,这一回复将是一个以逗号分隔的列表。尽管客户端或许只请求某一方法,但服务端仍然可以返回所有允许的方法,以便客户端将其缓存。
Access-Control-Allow-Headers(当预请求中包含Access-Control-Request-Headers时必须包含) – 这是对预请求当中Access-Control-Request-Headers的回复,和上面一样是以逗号分隔的列表,可以返回所有支持的头部。这里在实际使用中有遇到,所有支持的头部一时可能不能完全写出来,而又不想在这一层做过多的判断,没关系,事实上通过request的header可以直接取到Access-Control-Request-Headers,直接把对应的value设置到Access-Control-Allow-Headers即可。
Access-Control-Allow-Credentials(可选) – 和简单请求当中作用相同。
Access-Control-Max-Age(可选) – 以秒为单位的缓存时间。预请求的的发送并非免费午餐,允许时应当尽可能缓存。

一旦预回应如期而至,所请求的权限也都已满足,则实际请求开始发送。

参考文章: https://segmentfault.com/a/1190000022601274?utm_source=tag-newest

<think>好的,我现在需要详细解答用户关于CORS中简单请求复杂请求预检请求的区别的问题。用户提供了几个引用资料,我需要结合这些资料来组织回答,确保准确性全面性。 首先,我需要回忆CORS的基本概念。CORS是跨域资源共享的机制,允许不同源的服务器进行资源交互。同源策略限制了跨域请求,而CORS通过特定的HTTP头部来放宽这些限制。 根据引用[1],简单请求需要满足特定条件,比如方法为GET、POST或HEAD,头部字段有限等。而复杂请求则不满足这些条件,会触发预检请求。引用[3]提到,预检请求使用OPTIONS方法,检查服务器是否允许实际请求。引用[2][5]提到了实际应用中可能遇到的问题,比如配置不当导致403错误,需要前后端配合。 接下来,我需要明确区分这三个概念。简单请求直接发送,无需预检;复杂请求需要先发送预检请求,验证通过后再发送实际请求。预检请求复杂请求的一部分,属于OPTIONS方法的请求。 然后,我需要结构清晰地分点解释每个请求类型的条件、流程示例。例如,简单请求的条件包括方法、头部Content-Type;复杂请求的条件则相反,可能使用PUT、DELETE等方法,或包含自定义头部。预检请求的触发条件流程需要详细说明,比如浏览器自动发送OPTIONS请求,检查服务器返回的CORS头。 同时,要引用用户提供的资料来支持解释,比如引用[3]说明预检通过后的处理方式,引用[4]中的代码示例帮助理解实现方法。还要注意用户提到的常见问题,比如预检请求被忽视可能导致错误,这需要在区别部分强调预检的必要性。 最后,生成相关问题时要涵盖应用场景、配置方法、问题排查等,帮助用户深入理解。例如,如何避免不必要的预检请求,或者预检失败的原因。 总结,回答的结构应该包括定义、触发条件、流程、区别对比示例,确保用户能清晰理解这三个概念及其在实际中的应用。</think>### CORS 简单请求 vs 复杂请求 vs 预检请求详解 #### 一、简单请求(Simple Requests) **定义** 简单请求是满足以下所有条件的HTTP请求[^3]: 1. **方法限制**:仅限 `GET`、`POST`、`HEAD`。 2. **头部限制**:只能包含以下安全头部字段: - `Accept` - `Accept-Language` - `Content-Language` - `Content-Type`(仅限 `text/plain`、`multipart/form-data`、`application/x-www-form-urlencoded`) 3. **无自定义头部**:例如 `Authorization`、`X-Custom-Header` 等。 **流程** 浏览器直接发送请求,并在请求头中添加 `Origin` 字段。服务器响应时需包含 `Access-Control-Allow-Origin` 头,否则请求被拦截[^3]。 **示例**: ```http GET /api/data HTTP/1.1 Origin: https://example.com ``` --- #### 二、复杂请求(Complex Requests) **定义** 不满足简单请求条件的请求均属于复杂请求,例如: 1. **非常用方法**:如 `PUT`、`DELETE`、`PATCH`。 2. **包含自定义头部**:如 `Authorization`、`X-Requested-With`。 3. **特殊Content-Type**:如 `application/json`。 **特点** - **需预检请求**:浏览器在发送实际请求前,先发送 `OPTIONS` 方法的预检请求[^2]。 - **双重验证**:服务器需明确允许实际请求的方法头部。 --- #### 三、预检请求(Preflight Requests) **定义** 预检请求复杂请求的前置验证步骤,通过 `OPTIONS` 方法检查服务器是否支持实际请求的方法头部[^2][^3]。 **触发条件** - 使用 `PUT`、`DELETE` 等方法。 - 包含自定义头部或非安全 `Content-Type`(如 `application/json`)。 **流程** 1. 浏览器发送 `OPTIONS` 请求,包含以下关键头: - `Origin` - `Access-Control-Request-Method`(声明实际请求方法) - `Access-Control-Request-Headers`(声明自定义头部) 2. 服务器响应需包含: - `Access-Control-Allow-Origin` - `Access-Control-Allow-Methods`(允许的方法列表) - `Access-Control-Allow-Headers`(允许的头部列表) 3. 验证通过后,浏览器发送实际请求[^3]。 **示例**: ```http OPTIONS /api/data HTTP/1.1 Origin: https://example.com Access-Control-Request-Method: DELETE Access-Control-Request-Headers: X-Custom-Header ``` --- #### 四、核心区别对比 | 特性 | 简单请求 | 复杂请求 | 预检请求 | |-----------------------|-----------------------------------|-----------------------------------|-----------------------------------| | **触发条件** | 符合方法、头部、Content-Type限制 | 不符合简单请求条件 | 复杂请求的前置步骤 | | **请求次数** | 1次 | 2次(预检 + 实际请求) | 本身是1次OPTIONS请求 | | **HTTP方法** | GET/POST/HEAD | PUT/DELETE等 | OPTIONS | | **自定义头部** | 不允许 | 允许 | 需在预检中声明 | | **服务器响应头要求** | 仅需`Access-Control-Allow-Origin`| 需包含方法、头部、来源等多重验证 | 明确返回允许的方法头部 | --- #### 五、常见问题与解决方案 1. **为什么复杂请求需要预检?** 防止恶意请求滥用非安全方法或头部(如删除资源)[^3]。 2. **预检失败的可能原因** - 服务器未配置 `Access-Control-Allow-Methods` 或 `Access-Control-Allow-Headers`[^5]。 - `Origin` 不在允许列表中。 3. **如何减少预检请求?** 尽量使用简单请求条件(如将 `Content-Type` 改为 `application/x-www-form-urlencoded`)[^4]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值