导图社区 HTTP
HTTP是互联网应用最为广泛的一种网络协议,所有的3w文件都必须遵守这个标准。导图阐述了HTTP的组成,版本更新以及HTTPS,感兴趣的小伙伴可以看看哟。
编辑于2022-11-15 09:08:04 上海HTTP
HTTP 基本概念
HTTP,全称为 HyperText Transfer Protocol,即为超文本传输协议。是互联网应用最为广泛的一种网络协议,所有的 www 文件都必须遵守这个标准。
HTTP 特性
HTTP 是无连接无状态的
HTTP 一般构建于 TCP/IP 协议之上,默认端口号是 80
HTTP 组成
请求
状态行
状态行由请求方式,路径、协议等构成,各元素之间以空格分隔。对应到图中即为 GET、/books/?sex=man&name=Professional、 HTTP/1.1
请求头
请求头提供一些参数比如:Cookie,用户代理信息,主机名等等。(图中即从第二行到最后一行)
请求头详解
Accept : 指定客户端能够接受的内容类型,比如常见的text/html, 最后返回的百度首页也是html 格式
Accept-Encoding: 表示浏览器有能力解码的编码类型
gzip 是 GNU zip 的缩写,它是一个 GNU 自由软件的文件压缩程序,也经常用来表示 gzip 这种文件格式, 其核心是deflate 算法 deflate是同时使用了 LZ77 算法与哈夫曼编码(Huffman Coding)的一个无损数据压缩算法。
Accept-language: 表示浏览器所支持的语言类型
q的设置范围是0~1,0是拒绝该文件类型,大于0则根据q的大小决定优先级。 凡是设置了q值的优先级都会比不设置q值的优先级低,因为q值不可能超过默认1
Cache-Control: 指定请求和响应缓存的机制
Connection: 表示是否需要持久连接
HTTP 1.1 默认持久连接即为keep-alive, HTTP 1.0 则默认为close
Cookie: 会话跟踪
Host: 请求服务器网址
User-Agent: 用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户端使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等
可用来做prerender
Content-Length: 请求的内容长度
Referer: 先前访问的网页的地址,当前请求网页紧随其后,说明你是从哪个站点访问到该网页的
Content-Type: 内容的类型
Get 请求无该字段
POST 请求中常见的有
application/x-www-form-unlencoded 为普通表单的提交
multipart/form-data 文件上传
响应头详解
BDPAGETYPE, BDUSERID, BDQID, 自定义字段
Date: 原始服务器消息发出的时间
Last-Modified: 请求资源的最后修改时间
Expires: 响应过期的日期和时间,如果下次访问在时间允许的范围内,可以不用重新请求,直接访问缓存
Set-Cookie:设置Http Cookie, 下次浏览器访问的时候会带上这个cookie 的值
Server: 服务器软件名称,常见的有Apache 和 Nginx
HTTP header 地址
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers
http://tools.jb51.net/table/http_header
请求正文
请求正文就放一些发送的数据,一般 GET 请求会将参数放在 URL 中,也就是在请求头中而请求正文一般为空,而 POST 请求将参数放在请求正文中。请求正文可以传一些 json 数据或者字符串等等。
请求方法
简单请求
简单请求的约束
请求方法是以下三种方法之一:GET、POST、HEAD
不能自定义请求头header,不得人为设置该集合之外的其他首部字段。该集合为:Accept、Accept-Language、Content-Language、Content-Type
Content-Type 的值仅限于下列三者之一: text/plain multipart/form-data application/x-www-http-urlencoded
请求中的任意XMLHttpRequestUpload 对象均没有注册任何事件监听器;XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问
简单请求的发送从代码上来看和普通的XHR没太大区别,但是HTTP头当中要求总是包含一个域(Origin)的信息。该域包含协议名、地址以及一个可选的端口。不过这一项实际上由浏览器代为发送,并不是开发者代码可以触及到的
GET
GET 请求一般不会产生副作用,它仅仅只是获取资源信息,就像数据库查询一样,不会修改、增加数据,不会影响资源的状态,并且对同一个 URL 的多次GET请求应该返回相同的结果。幂等
POST
POST 请求表示可能会修改服务器上的资源。
复杂请求
简单来说,任何不满足上述简单请求要求的请求,都属于复杂请求。比如说你需要发送PUT、DELETE等HTTP动作,或者发送Content-Type: application/json的内容。
在使用cors 的时候,http 请求会被划分为简单和复杂请求,区别在于是否会触发cors 预检机制。跨域资源共享标准新增了一组HTTP首部字段,允许服务器声明哪些源站通过浏览器权限访问哪些资源。规范要求,对那些MIME类型的POST 请求,浏览器必须首先使用OPTIONS 方法发起一个预检请求,从而获知服务器端是否允许跨域请求
简单请求与复杂请求的跨域设置
简单请求
Access-Control-Allow-Origin:* // 如果只是针对某一个请求源进行设置的话,可以设置为具体的值 Access-Control-Allow-Origin: 'http://www.***.com'
复杂请求
Access-Control-Request-Method: POST Access-Control-Request-Headers: X-CUSTOMER-HEADER, Content-Type
响应
状态码
1xx : 表示请求已经接受了,继续处理
2xx : 表示请求已经处理掉了
200 客户端请求成功
3xx : 重定向
301 请求永久重定向
302 请求临时重定向
304 文件未修改,可以使用缓存
4xx : 一般表示客户端有错误,请求无法实现
401 请求未经过授权,无法访问
403 服务器收到请求,但是拒绝服务,相应正文中会包含原因
404 请求的资源不存在,比如URL 地址错误
400 客户端请求语法问题,服务器无法解读
5xx : 一般为服务器端的错误
500 服务器发生不可预期的错误,无法完成客户端的请求
503 服务器当前不能处理客户端的请求,在过一段时间后,服务器可能会恢复正常
其他
会话跟踪
浏览器与服务器之间的通信是通过 HTTP 协议进行通信的,而 HTTP 协议是”无状态”的协议,它不能保存客户的信息,即一次响应完成之后连接就断开了,下一次的请求需要重新连接,这样就需要判断是否是同一个用户,所以才有会话跟踪技术来实现这种要求
常见方法
URL 重写
URL 重写技术就是在 URL 结尾添加一个附加数据以标识该会话,把会话 ID 通过 URL 的信息传递过去,以便在服务器进行识别不同的用户
隐藏表单域
将会话ID添加到HTML表单元素中提交到服务器,此表单元素并不在客户端显示
Cookie
Cookie 是 Web 服务器发送给客户端的一小段信息,客户端请求时可以读取该信息发送给服务器端,进而进行用户的识别,对于客户端的每次请求,服务器都会将 Cookie 发送到客户端,客户端保存下来,以便下次使用
客户端可以采用两种方式来保存这个 Cookie 对象, 一种方式是保存在客户端内存中,称为临时 Cookie,浏览器关闭后这个 Cookie 对象将消失。 (不指定过期时间) 另外一种方式是保存在客户机的磁盘上,称为永久 Cookie。以后客户端只要访问该网站,就会将这个 Cookie 再次发送到服务器上,前提是这个 Cookie 在有效期内,这样就实现了对客户的跟踪。Cookie 是可以被禁止的,当你打开 Chrome,在设置里面关闭 Cookie,那么你将再也无法登录淘宝页面。
Session
在服务器端会创建一个 session 对象,产生一个 sessionID 来标识这个 session 对象,然后将这个 sessionID 放入到 Cookie 中发送到客户端,下一次访问时,sessionID 会发送到服务器,在服务器端进行识别不同的用户
每一个用户都有一个不同的 session,各个用户之间是不能共享的,是每个用户所独享的,在 session 中可以存放信息。 Session的实现依赖于Cookie,如果Cookie被禁用,那么session也将失效。
Authorization
请求消息头含有服务器用于验证用户代理身份的凭证
JWT
JSON Web Token (or JWT)只是一个包含某种意义数据的JSON串。它最重要的特性就是,为了确认它是否有效,我们只需要看JWT本身的内容,而不需要借助于第三方服务或者在多个请求之间将其保存在内存中-这是因为它本身携带了信息验证码MAC(Message Authentication Code)。
一个JWT包含3个部分:头部Header,数据Payload,签名Signature
Payload只是一个普通的Javascript 对象。对于payload的内容,JWT是没有任何限制的,但必须注意的是,JWT是没有加密的。因此,任何放在token里面的信息,如果被截获了,对任何人别人是可读的。因此,我们不应该在Payload里面存放任何黑客可以利用的用户信息
持久连接
Keep-alive
如果客户端浏览器支持 Keep-Alive ,那么就在HTTP请求头中添加一个字段 Connection: Keep-Alive,当服务器收到附带有 Connection: Keep-Alive 的请求时,它也会在响应头中添加一个同样的字段来使用 Keep-Alive 。这样一来,客户端和服务器之间的HTTP连接就会被保持,不会断开(超过 Keep-Alive 规定的时间,意外断电等情况除外),当客户端发送另外一个请求时,就使用这条已经建立的连接。
简单说就是保持当前的TCP连接,避免了重新建立连接
缓存机制
强缓存
强缓存主要是由 Cache-control 和 Expires 两个 Header 决定的
Expires 的值和头里面的 Date 属性的值来判断是否缓存还有效。Expires 是 Web 服务器响应消息头字段,在响应 http 请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。Expires 的一个缺点就是,返回的到期时间是服务器端的时间,这是一个绝对的时间,这样存在一个问题,如果客户端的时间与服务器的时间相差很大(比如时钟不同步,或者跨时区),那么误差就很大
Cache-Control 指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。但是其设置的是一个相对时间
max-age: 是距离请求发起的时间的秒数,该时间内会命中强缓存
no-store: 表示没有缓存
no-cache: 有缓存但是要重新验证,即重新向服务器请求
private: 表示该响应是专用于某单个用户的,中间人不能缓存此响应,该响应只能应用于浏览器私有缓存中
public: 表示响应可以被任何中间人(比如中间代理、CDN 等缓存)
Cache-control 优先级比 Expires 优先级高
首次请求,直接从 server 中获取。其中会设置 max-age=100 第二次请求,age=10,小于 100,则命中 Cache,直接返回 第三次请求,age=110,大于 110。强缓存失效,就需要再次请求 Server
协商缓存
If-Modified-Since——Last-Modified
Last-Modified 表示本地文件最后修改日期,浏览器会在 request header 加上 If-Modified-Since(上次返回的 Last-Modified 的值),询问服务器在该日期后资源是否有更新,有更新的话就会将新的资源发送回来 但是如果在本地打开缓存文件,就会造成 Last-Modified 被修改,所以在 HTTP / 1.1 出现了 ETag
If-none-match——ETags
Etag 就像一个指纹,资源变化都会导致 ETag 变化,跟最后修改时间没有关系,ETag 可以保证每一个资源是唯一的。If-None-Match 的 header 会将上次返回的 Etag 发送给服务器,询问该资源的 Etag 是否有更新,有变动就会发送新的资源回来
If-none-match、ETags 优先级高于 If-Modified-Since、Last-Modified
如果浏览器命中强缓存,则不需要给服务器发请求;而协商缓存最终由服务器来决定是否使用缓存,即客户端与服务器之间存在一次通信
在 chrome 中强缓存(虽然没有发出真实的 http 请求)的请求状态码返回是 200 (from cache);而协商缓存如果命中走缓存的话,请求的状态码是 304 (not modified)。 不同浏览器的策略不同,在 Fire Fox中,from cache 状态码是 304.
HTTP 版本更新
在 1991 年发布了 HTTP 0.9 版,在 1996 年发布 1.0 版,1997 年是 1.1 版,1.1 版也是到今天为止传输最广泛的版本。2015 年发布了 2.0 版,其极大的优化了 HTTP/1.1 的性能和安全性,而 2018 年发布的 3.0 版,继续优化 HTTP/2,激进地使用 UDP 取代 TCP 协议,目前,HTTP/3 在 2019 年 9 月 26 日 被 Chrome,Firefox,和 Cloudflare 支持
HTTP 0.9
单行协议,请求由单行指令构成。以唯一可用的方法 GET 开头。后面跟的是目标资源的路径
HTTP 1.0
默认模型,是短连接,每一个 HTTP 请求都由它自己独立的连接完成;这意味着发起每一个 HTTP 请求之前都会有一次 TCP 握手,而且是连续不断的
HTTP 1.1
连接可以复用
长连接:connection: keep-alive。HTTP 1.1 支持长连接(PersistentConnection),在一个 TCP 连接上可以传送多个 HTTP 请求和响应,减少了建立和关闭连接的消耗和延迟,在 HTTP1.1 中默认开启 Connection:keep-alive
增加了管道化技术(HTTP Pipelinling)
,允许在第一个应答被完全发送完成之前就发送第二个请求,以降低通信延迟。复用同一个 TCP 连接期间,即便是通过管道同时发送了多个请求,服务端也是按请求的顺序依次给出响应的;而客户端在未收到之前所发出所有请求的响应之前,将会阻塞后面的请求(排队等待),这称为"队头堵塞"(Head-of-line blocking)。
支持响应分块,分块编码传输
Transfer-Encoding: chunkedContent-length 声明本次响应的数据长度。keep-alive 连接可以先后传送多个响应,因此用 Content-length 来区分数据包是属于哪一个响应
引入额外的缓存控制机制
在 HTTP1.0 中主要使用 header 里的 If-Modified-Since,Expires 等来做为缓存判断的标准,HTTP1.1 则引入了更多的缓存控制策略例如 Entity tag, If-None-Match,Cache-Control 等更多可供选择的缓存头来控制缓存策略
Host 头
不同的域名配置同一个 IP 地址的服务器。Host 是 HTTP 1.1 协议中新增的一个请求头,主要用来实现虚拟主机技术
虚拟主机(virtual hosting)即共享主机(shared web hosting),可以利用虚拟技术把一台完整的服务器分成若干个主机,因此可以在单一主机上运行多个网站或服务。
HTTP 2.0
HTTP/2 是二进制协议而不是文本协议
帧:客户端与服务器通过交换帧来通信,帧是基于这个新协议通信的最小单位
消息:是指逻辑上的 HTTP 消息,比如请求、响应等,由一或多个帧组成。
流:流是连接中的一个虚拟信道,可以承载双向的消息;每个流都有一个唯一的整数标识符
HTTP 2.0 中的帧将 HTTP/1.x 消息分成帧并嵌入到流 (stream) 中。数据帧和报头帧分离,这将允许报头压缩。将多个流组合,这是一个被称为多路复用 (multiplexing) 的过程,它允许更有效的底层 TCP 连接。
也就是说,流用来承载消息,消息又是有一个或多个帧组成。二进制传输的方式更加提升了传输性能。每个数据流都以消息的形式发送,而消息又由一个或多个帧组成。帧是流中的数据单位。
这是一个复用协议。并行的请求能在同一个连接中处理,移除了 HTTP/1.x 中顺序和阻塞的约束。多路复用允许同时通过单一的 HTTP/2 连接发起多重的请求-响应消息, 即避免了1.x 的单个TCP 发送请求限制(6)
将 HTTP 消息分解为独立的帧,交错发送,然后在另一端重新组装是 HTTP 2 最重要的一项增强。事实上,这个机制会在整个网络技术栈中引发一系列连锁反应,从而带来巨大的性能提升,让我们可以:1.并行交错地发送多个请求,请求之间互不影响。2.并行交错地发送多个响应,响应之间互不干扰。3.使用一个连接并行发送多个请求和响应。4.消除不必要的延迟和提高现有网络容量的利用率,从而减少页面加载时间。5.不必再为绕过 HTTP/1.x 限制而做很多工作(比如精灵图) ..
压缩了headers
HTTP/2 使用 HPACK 压缩格式压缩请求和响应标头元数据,这种格式采用两种简单但是强大的技术:这种格式支持通过静态霍夫曼代码对传输的标头字段进行编码,从而减小了各个传输的大小
服务端推送
其允许服务器在客户端缓存中填充数据,通过一个叫服务器推送的机制来提前请求
HTTPS
HTTP + SSL/TLS
TLS
TLS 握手的过程采用的是非对称加密
Client Hello: 客户端发送一个随机值(Random1)以及需要的协议和加密方式。
Server Hello 以及 Certificate: 服务端收到客户端的随机值,自己也产生一个随机值(Random2),并根据客户端需求的协议和加密方式来使用对应的方式,并且发送自己的证书(如果需要验证客户端证书需要说明)
Certificate Verify: 客户端收到服务端的证书并验证是否有效,验证通过会再生成一个随机值(Random3),通过服务端证书的公钥去加密这个随机值并发送给服务端,如果服务端需要验证客户端证书的话会附带证书
Server 生成 secret: 服务端收到加密过的随机值并使用私钥解密获得第三个随机值(Random3),这时候两端都拥有了三个随机值,可以通过这三个随机值按照之前约定的加密方式生成密钥,接下来的通信就可以通过该密钥来加密解密
HTTPS 会加密header + http body, URL 是包含在Header 中所以会被加密
HTTPS(TLS/SSL协议)的完整流程主要由两层组成,分别是握手层和加密层。握手层在加密层的上层,握手层提供加密层所需要的信息(密钥块),对于一个HTTPS请求来说,HTTP消息在没有完成握手之前,是不会传递给加密层的,一旦握手层处理完毕,最终应用层所有的HTTP消息交由加密层进行加密
握手完成之后才会通讯