目录
一、相关问题
1. HTTP请求常见的状态码和字段?
(1)状态码
(2)字段
① Host 字段
② Content-length 字段
③ Connection 字段
④ Content-Type 字段
⑤ Content-Encoding 字段
2. GET 和 POST 的区别?
(1)作用不同
(2)参数传递方式不同
(3)安全性不同
(4)参数长度限制不同
(5)编码方式不同
(6)缓存机制不同
(7)时间消耗不同
3. GET 和 POST 方法都是安全和幂等的吗?
4. 什么是强缓存和协商缓存?
(1)强制缓存
(2)协商缓存
① 使用 ETag 字段实现的协商缓存过程
② 使用 last-modified 实现的协商缓存过程
一、相关问题
1. HTTP请求常见的状态码和字段?
(1)状态码
https://i-blog.csdnimg.cn/direct/b6e10f055d1048468008f5e9c00dcd07.png" width="596" />
1xx 类状态码 属于提示信息,是 协议处理中的 一种 中间状态,实际 用到的比较少。
2xx 类状态码 表示服务器 成功处理了 客户端的请求,也是我们 最愿意看到的 状态。
- 「200 OK」是 最常见的 成功状态码,表示一切正常。如果是非 HEAD 请求,服务器返回的 响应头 都会有 body 数据。
- 「204 No Content」也是 常见的 成功状态码,与 200 OK 基本相同,但 响应头 没有 body 数据。
- 「206 Partial Content」是应用于 HTTP 分块下载 或 断点续传,表示应 返回的 body 数据 并不是 资源的 全部,而是 其中的 一部分,也是 服务器 处理成功的 状态。
3xx 类状态码 表示客户端 请求的资源 发生了变动,需要客户端用新的 URL 重新发送请求获取资源,也就是重定向。
- 「301 Moved Permanently」表示 永久 重定向,说明 请求的资源 已经 不存在了,需 改用新的 URL 再次访问。
- 「302 Found」表示 临时 重定向,说明 请求的 资源还在,但 暂时 需要用 另一个 URL 来访问。301 和 302 都会 在 响应头 里 使用 字段 Location ,指明 后续要 跳转的 URL,浏览器 会自动重定向 新的 URL。
- 「304 Not Modified」不具有 跳转的 含义,表示 资源 未修改,重定向 已存在的 缓冲文件,也称 缓存 重定向,也就是 告诉 客户端可以 继续使用 缓存资源,用于 缓存控制。
4xx 类状态码 表示客户端 发送的 报文有误,服务器 无法处理,也就是 错误码 的含义。
- 「400 Bad Request」表示 客户端请求的 报文有错误,但只是个 笼统的 错误。
- 「403 Forbidden」表示 服务器禁止 访问资源,并不是 客户端的 请求出错。
- 「404 Not Found」表示 请求的资源 在服务器上 不存在 或 未找到,所以 无法提供给 客户端。
5xx 类状态码 表示客户端 请求报文正确,但是 服务器 处理时 内部发生了 错误,属于 服务器端的 错误码。
- 「500 Internal Server Error」与 400 类型,是个 笼统通用的 错误码,服务器 发生了 什么错误,我们 并不知道。
- 「501 Not Implemented」表示 客户端 请求的 功能 还不支持,类似 “即将开业,敬请期待" 的意思。
- 「502 Bad Gateway」通常是 服务器作为 网关 或 代理 时返回的 错误码,表示 服务器 自身工作正常,访问 后端服务器 发生了 错误。
- 「503 Service Unavailable」表示 服务器 当前很忙,暂时 无法响应 客户端,类似 “网络服务正忙,请稍后重试” 的意思。
https://i-blog.csdnimg.cn/direct/d344bbd56c4c433e85a866117b607446.png" width="602" />
(2)字段
https://i-blog.csdnimg.cn/direct/e819c5fef96f4eecb8b601506f8b61f1.png" width="575" />
① Host 字段
客户端发送 请求时,用来指定服务器的 域名。
https://i-blog.csdnimg.cn/direct/f047d7351db441d691ab0c272ff6e79a.png" width="494" />
有了 Host 字段,就可以 将 请求发往「同一台」服务器上的 不同网站。
② Content-length 字段
服务器在 返回数据时,会有 Content-Length 字段,表明本次回应的数据长度。
https://i-blog.csdnimg.cn/direct/06de3233fe074e60a85b73152871f724.png" width="365" />
如上面是 告诉浏览器,本次 服务器回应的 数据长度是 1000 个字节,后面的字节就属于下一个回应了。
③ Connection 字段
Connection 字段最常用于 客户端 要求 服务器使用「HTTP 长连接」机制,以便 其他 请求复用。
https://i-blog.csdnimg.cn/direct/c33d8532b4b14272ab5b9eb5d11aa168.png" width="380" />
④ Content-Type 字段
Content-Type 字段用于 服务器 回应时,告诉 客户端,本次数据是什 么格式。
https://i-blog.csdnimg.cn/direct/2cec8bf7fcc446eaa8e484d288b52ff2.png" width="461" />
上面的 类型表明,发送的是 网页,而且 编码 是 UTF-8。
⑤ Content-Encoding 字段
Content-Encoding 字段说明 数据的 压缩方法。表示 服务器 返回的 数据 使用了 什么 压缩格式。
https://i-blog.csdnimg.cn/direct/e8933c3cf58248b6839abc3610fb8694.png" width="477" />
上面 表示 服务器 返回的数据 采用了 gzip 方式压缩,告知 客户端 需要用 此方式 解压。
客户端 在请求时,用 Accept-Encoding 字段说明 自己可以接 受哪些 压缩方法。
2. GET 和 POST 的区别?
(1)作用不同
- GET 用于从服务端 获取资源。
- POST 一般用来 向服务器端 提交数据。
(2)参数传递方式不同
- GET 请求的参数 一般写在 URL 中,且只接受 ASCII 字符。
- POST 请求参数 一般放在请求体中,对于 数据类型也 没有限制。
(3)安全性不同
因为 参数传递方式的 不同,所以 两者安全性不同,GET 请求的 参数 直接暴露在 URL 中,所以 更不安全,不能用来 传递 敏感信息。
(4)参数长度限制不同
- GET 传送的 数据量较小,不能大于2KB。
- POST 传送的 数据量较大,一般被默认为不受限制。
- HTTP 协议没有 Body 和 URL 的长度限制,对 URL 限制的大多是浏览器和服务器的 原因。
(5)编码方式不同
- GET 请求 只能进行 URL 编码 (application/x-www-form-urlencoded)
- POST 支持 多种 编码方式 (application/x-www-form-urlencoded 或 multipart/form-data,二进制数据 使用 多种编码)
(6)缓存机制不同
- GET 请求会 被浏览器 主动 cache,而 POST 不会,除非 手动设置。
- GET 请求参数会 被完整 保留在 浏览器 历史记录 里,而 POST 中的参数 不会 被保留。
- GET 产生的 URL 地址可以被 保存为书签,而 POST 不可以。
- GET 在浏览器 回退时是 无害的,而 POST 会 再次 提交请求。
(7)时间消耗不同
- GET 产生一个 TCP 数据包。
- POST 产生两个 TCP 数据包。
- 对于 GET 方式的请求,浏览器 会把 header 和 data 一并发送出去,服务器响应 200(返回数据)。
- 而对于 POST,浏览器先发送 Header,服务器响应 100 continue,浏览器 再发送 data,服务器响应 200 ok(返回数据)。
https://i-blog.csdnimg.cn/direct/7607a9a6d9b34fed8a13154fcd57ee0e.png" width="381" />
https://i-blog.csdnimg.cn/direct/c49f9c976b864efcb389e112444ec6cf.png" width="376" />
3. GET 和 POST 方法都是安全和幂等的吗?
安全和幂等的概念:
- 在 HTTP 协议里,所谓的「安全」是指 请求方法 不会「破坏」服务器上的 资源。
- 所谓的「幂等」,意思是 多次执行 相同的操作,结果 都是「相同」的。
从 RFC 规范 定义的语义 来看:
- GET 方法就是 安全 且 幂等的,因为它是「只读」操作,无论 操作 多少次,服务器上的 数据都是 安全的,且 每次的结果 都是相同的。所以,可以对 GET 请求的 数据 做缓存,这个 缓存 可以做到 浏览器 本身上(彻底 避免浏览器 发请求),也可以 做到 代理上(如 nginx),而且在 浏览器中 GET 请求可以 保存为 书签。
- POST 因为是「新增 或 提交数据」的操作,会 修改服务器上的 资源,所以是 不安全的,且多次 提交数据 就会创建 多个资源,所以 不是幂等的。所以,浏览器 一般不会 缓存 POST 请求,也 不能把 POST 请求保存为书签。
小结:
- GET 的 语义是 请求获取 指定的资源。GET 方法是 安全、幂等、可被缓存的。
- POST 的 语义是 根据 请求负荷(报文主体)对 指定的资源 做出处理,具体的 处理方式 视资源类型 而不同。POST 不安全,不幂等,(大部分实现)不可缓存。
4. 什么是强缓存和协商缓存?
对于一些 具有 重复性的 HTTP 请求,比如 每次请求 得到的 数据 都一样的,我们 可以把 这对「请求-响应」的数据都 缓存在 本地,那么下次就 直接读取 本地的 数据,不必在 通过网络 获取 服务器的 响应了,这样的话 HTTP/1.1 的性能 肯定 肉眼可见的 提升。
所以,避免发送 HTTP 请求的方法 就是 通过 缓存技术,HTTP 设计者早 在之前就 考虑到了这点,因此 HTTP 协议的头部有不少是针对缓存的字段。HTTP 缓存有两种实现方式,分别是 强制缓存 和 协商缓存。
(1)强制缓存
强缓存 就是 浏览器本地 根据服务器 设置的 过期时间 来判断 是否 使用缓存,决定 是否 使用 缓存的主动性 在于浏览器 这边。如下图中,返回的是 200 状态码,但在 size 项中标识的是 from disk cache,就是使用了强制缓存。
https://i-blog.csdnimg.cn/direct/d36ffd78981347f8addcc04679361e9a.png" width="559" />
强缓存是 利用下面这 两个 HTTP 响应头部(Response Header)字段 实现的,它们都 用来 表示资源 在客户端 缓存的 有效期:
- Cache-Control,是一个 相对时间;
- Expires,是一个 绝对时间;
如果 HTTP 响应头部 同时 有 Cache-Control 和 Expires 字段的话,Cache-Control 的优先级高于 Expires。
Cache-control 选项 更多一些,设置 更加 精细,所以 建议 使用 Cache-Control 来实现 强缓存。具体的 实现流程如下:
- 当 浏览器 第一次 请求访问 服务器资源时,服务器 会在 返回 这个资源的 同时,在 Response 头部加上 Cache-Control,Cache-Control 中设置了 过期时间 大小;
- 浏览器 再次请求 访问服务器中的 该资源时,会 先通过 请求资源的 时间 与 Cache-Control 中设置的 过期时间 大小,来 计算出 该资源 是否过期,如果没有,则 使用 该缓存,否则 重新 请求服务器;
- 服务器 再次 收到请求后,会 再次更新 Response 头部的 Cache-Control。
(2)协商缓存
当在浏览器 使用 开发者工具的时候,可能会看到过 某些请求的 响应码是 304,这个是 告诉 浏览器 可以使用 本地缓存的 资源,通常 这种通过 服务端 告知 客户端 是否可以 使用缓存的 方式 被称为 协商缓存。
https://i-blog.csdnimg.cn/direct/202fbff7033e4c7e90e6c711c50adb1b.png" width="507" />
上图就是一个 协商缓存 的过程,所以 协商缓存 就是 与 服务端协商 之后,通过 协商结果 来判断是否 使用 本地缓存,即 浏览器每一次都要 发送请求 到 服务器询问 是否使用缓存。协商缓存可以 基于 两种头部 来实现。
第一种:请求头部中的 If-Modified-Since 字段 与 响应头部中的 Last-Modified 字段 实现,这两个字段的 意思是:
- 响应头部 中的 Last-Modified:标示 这个 响应资源 的最后 修改时间;
- 请求头部 中的 If-Modified-Since:当 资源过期了,发现 响应头中 具有 Last-Modified 声明,则再次 发起请求的 时候 带上 Last-Modified 的时间,服务器 收到 请求后 发现有 If-Modified-Since 则 与 被请求资源的 最后 修改时间 进行对比(Last-Modified),如果 最后 修改时间 较新(大),说明 资源 又被改过,则 返回最新 资源,HTTP 200 OK;如果 最后 修改 时间 较旧(小),说明 资源 无新修改,响应 HTTP 304 走缓存。
第二种:请求头部中的 If-None-Match 字段 与 响应头部 中的 ETag 字段,这 两个字段 的意思是:
- 响应头部中 Etag:唯一标识 响应资源;
- 请求头部中的 If-None-Match:当资源过期时,浏览器 发现 响应头 里有 Etag,则 再次向 服务器 发起 请求时,会将 请求头 If-None-Match 值 设置为 Etag 的值。服务器 收到 请求后 进行比对,如果 资源 没有变化 返回 304,如果 资源 变化了 返回 200。
第一种 实现方式 是 基于 时间 实现的,第二种 实现方式 是 基于 一个唯一标识 实现的,相对来说 后者 可以 更加准确地 判断 文件内容 是否 被修改,避免 由于 时间篡改 导致的 不可靠问题。
注意:协商缓存这 两个字段 都需要 配合 强制缓存 中 Cache-Control 字段来使用,只有 在 未能命中 强制缓存 的时候,才能 发起带有 协商缓存 字段的请求。
https://i-blog.csdnimg.cn/direct/91ff7d7d6ba24e1d91309364dabaa8d9.png" width="471" />
① 使用 ETag 字段实现的协商缓存过程
- 当浏览器 初次请求 访问 服务器资源 时,服务器 会在 返回这个资源的 同时,同时 生成 一个 Etag 值 携带在 响应头 里 返回给浏览器,这个 唯一标识的值是 根据 当前请求的 资源生成的。
- 当 浏览器 再次 请求访问服务器 中的该资源时,首先会先 检查强制 缓存 是否过期。如果没有过期,则直接使用 本地缓存;如果 缓存过期了,会在 请求头 加上 If-None-Match 字段,该字段的值就是之前 服务器 返回的 Etag 的值。
- 服务器收到 之后 拿该值 与 资源文件 最新的 Etag 值 做对比。如果 没有变化 则返回 304,告诉 浏览器 继续 使用缓存(不返回 资源文件);如果变化,则返回 200 状态码 和 资源,并在 请求头 加上新的 ETag 值。
② 使用 last-modified 实现的协商缓存过程
- 当浏览器 初次请求 访问 服务器资源 时,服务器端 读出文件修改时间,将 读出来的 修改时间 赋给 响应头的 last-modified 字段,返回给浏览器。
- 当 客户端 读取到 last-modified 的时候,会在 下次的 请求标头中 携带 If-Modified-Since 字段,而 这个 请求头中的 If-Modified-Since 就是之前 服务器返回的 last-modified 字段。
- 和 ETag 字段相同的,之后 每次对 该资源的 请求,都会 带上 If-Modified-Since 这个字段。而 服务端 就需要拿 其中表示时间 与最新 读取 该资源的 修改时间进行对比,来决定是 读取缓存 还是 返回 新的资源。
如果 在第一次 请求资源的 时候,服务端 返回的 HTTP 响应头部 同时有 Etag 和 Last-Modified 字段,那么 客户端 再下一次 请求的 时候,如果 带上了 ETag 和 Last-Modified 字段 信息 给服务端,这时 Etag 的 优先级 更高,也就是 服务端 先会 判断 Etag 是否 变化了,如果 Etag 有变化 就不用 在判断 Last-Modified 了,如果 Etag 没有变化,然后 再看 Last-Modified。