报文结构
请求头(request headers)、响应头(response headers)、请求体(FormData, request body)、响应体(response)
缓存
缓存有两种,强缓存和协商缓存。如果强缓存存在,那么执行强缓存,如果不存在则执行协商缓存。
强制缓存
本地缓存,本地存在一个存在一个缓存数据库, 如果缓存数据库中存在所请求的数据的时候,直接从本地缓存数据库里获取。强制缓存有两个字段表明 cache-control和expires
- Expires 缓存到期的时间,精确到秒。但由于服务端时间和客户端时间可能有误差,这也将导致缓存命中的误差。Expires是http1.0的产物,故现在主要使用的还是cache-control。并且Cache-control的优先级比Expires的高
- Cache-control 有多个值
- max-age: t秒 t表示一个时间,上一次访问后多久失效。上一次的时间应该是date对应的字段
- no-store 禁止缓存,每次都从服务器重新获取200
- no-chche 使用协商缓存来获取数据
- public 客户端和代理服务区都可以缓存
- private 客户端缓存
协商缓存
协商缓存有两组数据Last-Modified/if-Modified-Since和Etag/If-None-Match
- Last-Modified/if-Modified-Since:Last-Modified表示上次被修改的时间,在第一次请求的时候会在响应头里面返回。如果再次请求会在请求头的携带上if-Modified-Since(如果是协商缓存的话),if-Modified-Since的值就是第一次请求的Last-Modified的值。服务器拿到if-Modified-Since的值跟实际被修改的时间做对比,如果小于实际被修改的时间,那么服务器重新请求资源,返回200。否则返回403,告诉客户端使用本地缓存(from memory cache)
- Etag/If-None-Match:Etag是服务器根据当前文件的内容,给文件生成的唯一标识,只要里面的内容有改动,这个值就会变,相当于文件的hash值。工作原理跟Last-Modified/if-Modified-Since基本一样。不同的是一个是时间一个是 唯一标识
两种协商缓存对比
在精准度上,ETag优于Last-Modified。优于 ETag 是按照内容给资源上标识,因此能准确感知资源的变化。而 Last-Modified 就不一样了,它在一些特殊的情况并不能准确感知资源变化,主要有两种情况:
- 编辑了资源文件,但是文件内容并没有更改,这样也会造成缓存失效。
- Last-Modified 能够感知的单位时间是秒,如果文件在 1 秒内改变了多次,那么这时候的 Last-Modified 并没有体现出修改了。
在性能上,Last-Modified优于ETag,也很简单理解,Last-Modified仅仅只是记录一个时间点,而 Etag需要根据文件的具体内容生成哈希值。另外,如果两种方式都支持的话,服务器会优先考虑ETag。
状态码
COSR和两种请求方式
CORS(Cross-origin resource sharing),跨域资源共享。浏览器遵循同源政策,协议(http,还是https),主机IP,端口相同则是同源。跨域请求会被浏览器拦截,注意是浏览器拦截,不是服务器拦截,数据会发送到浏览器。
两种请求方式:简单请求和非简单请求
简单请求
符合以下条件的即为简单请求
- 请求方式为 GET POST HEAD
- 请求头为以下字段(以下只是列举了一部分,其实还有很多,查看了很多文档,但是文档的内容好像都不大一样)
- Accept 接受的返回数据类型
- Accept-Language
- Content-Language
- Content-Type 发送的数据类型(只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain)
- Referer 直译为推荐人。表示从哪个域名跳转过来
- User-Agent
实际过程中主要看请求方式是否为GET POST HEAD,在就是Content-Type的值,上传必定为非简单请求,因为他的Content-Type 不是该三个值里面的一个。在者就是是否往请求头里面添加自定字段,如果添加则为分简单请求。
Access-Control-Allow-Credentials 表示是否允许发送Cookie。跨域默认该值为false,如果需要发送Cookie,那么在响应头里面设置该值为true,并且在前端也要设置withCredentials为true
access-control-expose-header 响应头返回的字段默认就那几个,如果想展示更多,会在改值里面显示
非简单请求
在进行预检请求之前会发送预检请求,预检请求的请求方式为OPTIONS,如果预检请求没有通过(跨域),那么不会进行非正常请求。预检请求是否通过主要是请求头的三个字段
- Origin
- Access-Control-Request-Method 请求方式
- Access-Control-Request-Headers 在请求头添加那个自定义字段
预检请求响应字段
- Access-Control-Allow-Origin 允许请求的源列表 * 表示任何都可以请求
- Access-Control-Allow-Methods 允许请求的方法列表
- Access-Control-Allow-Headers 允许请求的自定义请求头字段
- access-control-allow-credentials 是否发送Cookie
- Access-Control-Max-Age 预检请求有效时间,多久不用发送预检请求
预检请求请求头字段和响应头字段比较,浏览就知道这个预检请求是否通过,通过之后发送真正的非简单请求。真正的非简单请求和简单请求一样。
简单请求和非简单请求的是否跨域都是有Origin和Access-Control-Allow-Origin决定
正向代理,反向代理
代理服务器与正真的服务器如果是一对一的,那么是正向代理,如果是一对多,那么是反向代理,nginx就是反向代理
跨域的解决方案
- jsonp
- nginx(原理就是请求转发,nginx只是工具)
- postmessage(客户端之间)
server {
listen 80;
server_name client.com;
location /api {
proxy_pass server.com;
}
}