什么是简单请求和复杂请求。
某些请求不会触发 CORS 预检请求,这样的请求一般称为"简单请求",而会触发预检的请求则为"复杂请求"。
1.简单请求
- 请求方法为
GET、HEAD、POST
- 只有以下
Headers
字段
- `Accept`
- `Accept-Language`
- `Content-Language`
- `Content-Type`
- `DPR/Downlink/Save-Data/Viewport-Width/Width` (这些不常见,放在一起)
Content-Type
只有以下三种
- `application/x-www-form-urlencoded`
- `multipart/form-data`
- `text/plain`
- 请求中的任意 XMLHttpRequestUpload 对象均没有注册任何事件监听器;
- 请求中没有使用 ReadableStream 对象。
2.复杂请求
- 不满足简单请求的,都是复杂请求
由此可见,因为上述请求在获取B站资源的请求Headers里带有 Access-Control-Request-Headers: range
, 而range
正好不在简单请求的条件2中提到的Headers范围里,因此属于复杂请求,于是触发预检options请求。
什么是跨域
刚刚提到了一个词叫跨域,那什么是跨域呢?在了解跨域之前,首先要了解一个概念:同源。所谓同源是指,域名、协议、端口均相同。
不明白没关系,举个例子。
需要特别注意的是,localhost和127.0.0.1虽然都指向本机,但也不属于同源。
而非同源之间网页调用就是我们所说的跨域。在浏览器同源策略限制下,向不同源发送XHR请求,浏览器认为该请求不受信任,禁止请求,具体表现为请求后不正常响应。
options带来什么问题
由此可见,复杂请求的条件其实非常容易满足,而一旦满足复杂请求的条件,则浏览器便会发送2次请求(一次预检options,一次复杂请求),这一次options就一来一回(一个RTT),显然会导致延迟和不必要的网络资源浪费,高并发情况下则可能为服务器带来严重的性能消耗。
如何优化options
每次复杂请求前都会调用一次options,这其实非常没有必要。因为大部分时候相同的请求,短时间内获得的结果是不会变的,是否可以通过浏览器缓存省掉这一次查询?
Access-Control-Max-Age
就是优化这个流程中使用的一个Header。它的作用是当你每次请求options
方法时,服务端返回调用支持的方法(Access-Control-Allow-Methods )和Headers(Access-Control-Allow-Headers)有哪些,同时告诉你,它在接下来 Access-Control-Max-Age
时间(单位是秒)里都支持,则这段时间内,不再需要使用options进行请求。特别注意的是,当Access-Control-Max-Age
的值为-1时,表示禁用缓存,每一次请求都需要发送预检请求,即用OPTIONS请求进行检测。
5.Status Code
状态码是什么
HTTP Status Code是常说的HTTP状态码。当用户访问一个网页时,浏览器会向网页所在服务器发出请求。服务器则会根据请求作出响应,而状态码则是响应的一部分,代表着本次请求的结果。所有状态码的第一个数字代表了响应的大概含义,组合上第二第三个数字则可以表示更具体的原因。如果请求失败了,通过这个状态码,大概初步判断出这次请求失败的原因。以下是五类状态码的含义。
状态码流程
可以根据以下流程图了解下各类状态码间的关系。
- 2xx和3xx之间的流程关系
- 4xx的状态流程
- 5xx的状态流程
常见状态码介绍
- 200 OK
这是最常见的状态码。代表请求已成功,数据也正常返回。而B站猫片里虽然响应成功了,但却不是200,而是206,是为什么呢,接下去继续看看。
- 206 Partial Content
这个状态码在上面B站请求的响应结果。服务器已经成功处理了部分 GET 请求。类似于B站看视频或者迅雷这类的 HTTP下载工具都是使用此类响应实现断点续传或者将一个大文档分解为多个下载段同时下载。
- 307 Temporary Redirect
内部重定向。重定向的意思是,当你输入一个网址的时候,浏览器会自动帮你跳转到另外一个网址上。比如,当你在浏览器输入框输入http://www.baidu.com/
时。由于使用http并不安全,百度会自动帮你跳转到它对应的https网页上。而此时,需要重定向的地址,会通过Response Headers
的Location
返回
404 Not Found
请求失败,请求所希望得到的资源未被在服务器上发现。出现这个错误的最有可能的原因是服务器端没有这个页面,或者是Request Method与注册URL的Method不一致,比如我有一个URL在服务端注册的Request Method 为 POST,但调用的时候却错误用了GET,则也会出现404错误。
499 Client has closed connection
网络请求过程中,由于服务端处理时间过长,客户端超时。一般常见于,后端服务器处理时间过长,而客户端也设置了一个超时等待时间,客户端等得“不耐烦”了,主动关掉连接时报出。
502 Bad Gateway
服务器方面无法给予正常的响应。一般常见于服务器崩溃后,nginx 无法正常收到服务端的响应,给客户端返回502状态码。
504 Gateway Timeout
网络请求过程中,由于服务端处理时间过长,网关超时。一般常见于,后端服务器逻辑处理时间过长,甚至长于 nginx设置的最长等待时间时报错。它跟 499 状态码非常像,区别在于499 表示的是客户端超时,504是网关超时。如果是499超时,可以考虑修改客户端的代码调整超时时间,如果是504,则考虑调整nginx的超时配置。