HTTP实用指南| 青训营笔记

63 阅读11分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 8 天

HTTP协议简介

HTTP 全称 Hyper Text Transfer Protocol 超文本传输协议 image.png

image.png

默认端口:80

http报文的结构:由起始行、首部、主体组成。

首部下面的空行是用来隔离请求头部和请求数据

image-20220423134917154

请求方法

  • GET: 向服务器获取数据;
  • POST:将实体提交到指定的资源,通常会造成服务器资源的修改;
  • PUT:上传文件,更新数据;
  • DELETE:删除服务器上的对象;
  • HEAD:获取报文首部,与GET相比,不返回报文主体部分;
  • OPTIONS:询问支持的请求方法,用来跨域请求,嗅探请求
  • CONNECT:要求在与代理服务器通信时建立隧道,使用隧道进行TCP通信;
  • TRACE: 回显服务器收到的请求,主要⽤于测试或诊断。

分类

  • 安全Safe:不会修改服务器的数据的方法:GET HEAD OPTIONS
  • 幂等Idempontent:同样的请求被执行一次与连续执行多次的效果时一样的,服务器的状态也是一样的,所有safe的方法都是idempotent的:GET HEAD OPTIONS PUT DELETE

http状态码

  • 2xx:成功
  • 3xx:重定向
  • 4xx:客户端错误
  • 5xx:服务器错误

常见状态码及含义

状态码含义
200 OK客户端请求成功
301 Moved Permanently资源(网页等)被永久转移到其它URL
302 Found临时跳转
304表示可以使用缓存的内容;(不应该认为时一种错误,而是对客户端有缓存情况下服务端的一种响应。)
401 Unauthorized请求未经授权
404 Not Found请求资源不存在,可能是输入了错误的URL
500 Internal Server Error服务器内部发生了不可预期的错误
504 Gateway Timeout网关或者代理的服务器无法在规定的时间内获得想要的响应

一些问题

HTTP 1.0 和 HTTP 1.1 之间有哪些区别?

HTTP 1.0和 HTTP 1.1 有以下区别

  • 连接方面,http1.0 默认使用非持久连接,而 http1.1 默认使用持久连接。http1.1 通过使用持久连接来使多个 http 请求复用同一个 TCP 连接,以此来避免使用非持久连接时每次需要建立连接的时延
  • 资源请求方面,在 http1.0 中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,http1.1 则在请求头引入了 range 头域,它允许只请求资源的某个部分,即返回码是 206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
  • 缓存方面,在 http1.0 中主要使用 header 里的 If-Modified-Since、Expires 来做为缓存判断的标准,http1.1 则引入了更多的缓存控制策略,例如 Etag、If-Unmodified-Since、If-Match、If-None-Match 等更多可供选择的缓存头来控制缓存策略。
  • http1.1 中新增了 host 字段,用来指定服务器的域名。http1.0 中认为每台服 务器都绑定一个唯一的 IP 地址,因此,请求消息中的 URL 并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机,并且它们共享一个IP地址。因此有了 host 字段,这样就可以将请求发往到同一台服务器上的不同网站。
  • http1.1 相对于 http1.0 还新增了很多请求方法,如 PUT、HEAD、OPTIONS 等。

HTTP 1.1 和 HTTP 2.0 的区别

  • 二进制协议:HTTP/2 是一个二进制协议。在 HTTP/1.1 版中,报文的头信息必须是文本(ASCII 编码),数据体可以是文本,也可以是二进制。HTTP/2 则是一个彻底的二进制协议,头信息和数据体都是二进制,并且统称为 "帧" ,可以分为头信息帧和数据帧。 帧的概念是它实现多路复用的基础。

帧是HTTP/2 通信的最小单位

  • 多路复用: HTTP/2 实现了多路复用,HTTP/2 仍然复用 TCP 连接,但是在一个连接里,客户端和服务器都可以同时发送多个请求或回应,而且不用按照顺序一一发送,这样就避免了"队头堵塞"【1】的问题。
  • 数据流: HTTP/2 使用了数据流的概念,因为 HTTP/2 的数据包是不按顺序发送的,同一个连接里面连续的数据包,可能属于不同的请求。因此,必须要对数据包做标记,指出它属于哪个请求。HTTP/2 将每个请求或回应的所有数据包,称为一个数据流。每个数据流都有一个独一无二的编号。数据包发送时,都必须标记数据流 ID ,用来区分它属于哪个数据流。
  • 头信息压缩: HTTP/2 实现了头信息压缩,由于 HTTP 1.1 协议不带状态,每次请求都必须附上所有信息。所以,请求的很多字段都是重复的,比如 Cookie 和 User Agent ,一模一样的内容,每次请求都必须附带,这会浪费很多带宽,也影响速度。HTTP/2 对这一点做了优化,引入了头信息压缩机制。一方面,头信息使用 gzip 或 compress 压缩后再发送;另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就能提高速度了。
  • 服务器推送: HTTP/2 允许服务器未经请求,主动向客户端发送资源,这叫做服务器推送。使用服务器推送提前给客户端推送必要的资源,这样就可以相对减少一些延迟时间。这里需要注意的是 http2 下服务器主动推送的是静态资源,和 WebSocket 以及使用 SSE 等方式向客户端发送即时数据的推送是不同的。

【1】队头堵塞:

队头阻塞是由 HTTP 基本的“请求 - 应答”模型所导致的。HTTP 规定报文必须是“一发一收”,这就形成了一个先进先出的“串行”队列。队列里的请求是没有优先级的,只有入队的先后顺序,排在最前面的请求会被最优先处理。如果队首的请求因为处理的太慢耽误了时间,那么队列里后面的所有请求也不得不跟着一起等待,结果就是其他的请求承担了不应有的时间成本,造成了队头堵塞的现象。

请求头

Header首部和请求方法配合工作,共同决定了客户端和服务器能做什么事情。

请求头说明
Accept接收类型,表示浏览器支持的MIME类型(对标服务端返回的Content-Type)
Content-Type客户端发送出去实体内容的类型
Cache-Control指定请求和响应遵循的缓存机制,如no-cache
If-Modified-Since对应服务端的Last-Modified,用来匹配看文件是否变动,只能精确到1s之内
Expires缓存控制,在这个时间内不会请求,直接使用缓存,服务端时间
Max-age代表资源在本地缓存多少秒,有效时间内不会请求,而是使用缓存
If-None-Match对应服务端的ETag,用来匹配文件内容是否改变(非常精确)
Cookie有cookie并且同域访问时会自动带上
Referer该页面的来源URL(适用于所有类型的请求,会精确到详细页面地址,csrf拦截常用到这个字段)
Origin最初的请求是从哪里发起的(只会精确到端口),Origin比Referer更尊重隐私
User-Agent用户客户端的一些必要信息,如UA头部等

响应头

响应头说明
Content-Type服务端返回的实体内容的类型
Cache-Control指定请求和响应遵循的缓存机制,如no-cache
Last-Modified请求资源的最后修改时间
Expires应该在什么时候认为文档已经过期,从而不再缓存它
Max-age客户端的本地资源应该缓存多少秒,开启了Cache-Control后有效
ETag资源的特定版本的标识符,Etags类似于指纹
Set-Cookie设置和页面关联的cookie,服务器通过这个头部把cookie传给客户端
Server服务器的一些相关信息
Access-Control-Allow-Origin服务器端允许的请求Origin头部(譬如为*)

HTTP缓存

减少了服务器和客户端之间的通信次数,降低网络延迟,加速页面加载,提高用户体验等 HTTP缓存就是HTTP协议规定缓存时如何工作,如何储存和各种类型等等事情

HTTP缓存的运作方式

image-20220429102851750

  • 浏览器请求资源,先看自己有没有缓存,没有就向服务器发起请求,有就执行下一步
  • 查看缓存是否过期,若没有过期,则返回;若过期,
  • 和服务器进行验证,若服务器告知未过期,那就继续使用;若过期,就返回新的资源作为新的缓存

缓存相关首部

  • Cache-Control常见设置
    • max-age:保存为缓存的最长时间(单位:秒)
    • no-cache:可以进行缓存,但每次使用前都要和服务器进行确认,同时代理服务器也不能对资源进行缓存。(不会走强缓存了,每次请求都回询问服务端缓存是否新鲜)
    • no-store:禁止缓存,每次都要向服务器请求资源。
    • must-revalidete:在缓存过期前可以使用,在缓存过期后必须向服务器验证
  • etage/If-None-Match:hash码,资源的标识
  • expires:缓存的过期时间
  • last-modified/If-Modified-since:表示资源最后修改时间

HTTP缓存的分类:

根据是否需要重新向服务器发起请求:强制缓存、协商缓存。

根据是否可以被单个或者多个用户来分类,可分为:私有缓存、共享缓存

强缓存

强制缓存在缓存数据未失效的情况下(即Cache-Control的max-age没有过期),那么就会直接使用浏览器的缓存数据,不会再向服务器发送任何请求。

优点:强制缓存生效时,http状态码200。这种方式页面的加载速度是最快的,性能也是很好的。

缺点:但是在这期间,如果服务器端的资源修改了,页面上是拿不到的,因为它不会再向服务器发请求了。

协商缓存

协商缓存不管是否生效,都需要与服务器发送交互 怎么设置协商缓存? response header里面的设置:

  • etage:标识
  • last-modified:表示资源最后修改时间
etag: '5c20abbd-e2e8'
last-modified: Mon, 24 Dec 2018 09:49:49 GMT

步骤:

每次请求返回来 response header 中的 etag和 last-modified,在下次请求时在 request header 就把这两个带上(If-None-Match和If-Modified-since),服务端把你带过来的标识进行对比,然后判断资源是否更改了,如果更改就直接返回新的资源,和更新对应的response header的标识etag、last-modified。如果资源没有变,那就不变etag、last-modified。

如果资源没更改,返回304,浏览器读取本地缓存。 如果资源有更改,返回200,返回最新的资源。

cookie

前面说过HTTP是无状态的协议,如何让他保持状态呢?就需要设置我们的cookie

Set-Cookie - response

标题说明
Name=value各种cookie的名称和值
Expires=DateCookie 的有效期,缺省时Cookie仅在浏览器关闭之前有效
Path=Path限制指定Cookie 的发送范围的文件目录,默认为当前
Domain=domain限制cookie生效的域名,默认为创建cookie的服务域名
secure仅在HTTPS 安全连接时,才可以发送Cookie
HttpOnlyJavaScript 脚本无法获得Cookie
SameSite=[None/Strict/Lax]None:同站、跨站请求都可发送 Strict:仅在同站发送 Lax:允许与级导航一起发送,并将与第三方网站发起的GET请求一起发送