【网络面试篇】HTTP(1)(笔记)——状态码、字段、GET、POST、缓存
目录
一、相关问题
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)状态码
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」表示 服务器 当前很忙,暂时 无法响应 客户端,类似 “网络服务正忙,请稍后重试” 的意思。
(2)字段
① Host 字段
客户端发送 请求时,用来指定服务器的 域名。
有了 Host 字段,就可以 将 请求发往「同一台」服务器上的 不同网站。
② Content-length 字段
服务器在 返回数据时,会有 Content-Length 字段,表明本次回应的数据长度。
如上面是 告诉浏览器,本次 服务器回应的 数据长度是 1000 个字节,后面的字节就属于下一个回应了。
③ Connection 字段
Connection 字段最常用于 客户端 要求 服务器使用「HTTP 长连接」机制,以便 其他 请求复用。
④ Content-Type 字段
Content-Type 字段用于 服务器 回应时,告诉 客户端,本次数据是什 么格式。
上面的 类型表明,发送的是 网页,而且 编码 是 UTF-8。
⑤ Content-Encoding 字段
Content-Encoding 字段说明 数据的 压缩方法。表示 服务器 返回的 数据 使用了 什么 压缩格式。
上面 表示 服务器 返回的数据 采用了 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(返回数据)。
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,就是使用了强制缓存。
强缓存是 利用下面这 两个 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,这个是 告诉 浏览器 可以使用 本地缓存的 资源,通常 这种通过 服务端 告知 客户端 是否可以 使用缓存的 方式 被称为 协商缓存。
上图就是一个 协商缓存 的过程,所以 协商缓存 就是 与 服务端协商 之后,通过 协商结果 来判断是否 使用 本地缓存,即 浏览器每一次都要 发送请求 到 服务器询问 是否使用缓存。协商缓存可以 基于 两种头部 来实现。
第一种:请求头部中的 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 字段来使用,只有 在 未能命中 强制缓存 的时候,才能 发起带有 协商缓存 字段的请求。
① 使用 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。