HTTP
HTTP 协议是个⽆状态协议,不会保存状态
Post 和 Get
Get
请求能缓存,Post
不能。Post
相对Get
安全⼀点点,因为Get
请求都包含在URL
⾥,且会被浏览器保存历史纪录,Post
不会,但是在抓包的情况下都是⼀样的。Post
可以通过request body
来传输⽐Get
更多的数据,Get
没有这个技术。URL
有⻓度限制,会影响Get
请求,但是这个⻓度限制是浏览器规定的,不是RFC
规定的。Post
⽀持更多的编码类型且不对数据类型限制。
常⻅状态码
3XX 重定向
301 moved permanently
,永久性重定向,表示资源已被分配了新的URL
。302 found
,临时性重定向,表示资源临时被分配了新的URL
。303 see other
,表示资源存在着另⼀个URL
,应使⽤GET
⽅法定向获取资源。304 not modified
,表示服务器允许访问资源,但因发⽣请求未满⾜条件的情况。307 temporary redirect
,临时重定向,和302
含义类似,但是期望客户端保持请求⽅法不变向新的地址发出请求。
4XX 客户端错误
400 bad request
,请求报⽂存在语法错误。401 unauthorized
,表示发送的请求需要有通过HTTP
认证的认证信息。403 forbidden
,表示对请求资源的访问被服务器拒绝。404 not found
,表示在服务器上没有找到请求的资源。
5XX 服务器错误
500 internal sever error
,表示服务器端在执⾏请求时发⽣了错误。501 Not Implemented
,表示服务器不⽀持当前请求所需要的某个功能。503 service unavailable
,表明服务器暂时处于超负载或正在停机维护,⽆法处理请求。
HTTP 头
通⽤字段 | 作⽤ |
---|---|
Cache-Control | 控制缓存的⾏为 |
Connection | 浏览器想要优先使⽤的连接类型,⽐如 keep-alive |
Date | 创建报⽂时间 |
Pragma | 报⽂指令 |
Via | 代理服务器相关信息 |
Transfer-Encoding | 传输编码⽅式 |
Upgrade | 要求客户端升级协议 |
Warning | 在内容中可能存在错误 |
请求字段 | 作⽤ |
---|---|
Accept | 能正确接收的媒体类型 |
Accept-Charset | 能正确接收的字符集 |
Accept-Encoding | 能正确接收的编码格式列表 |
Accept-Language | 能正确接收的语⾔列表 |
Expect | 期待服务端的指定⾏为 |
From | 请求⽅邮箱地址 |
Host | 服务器的域名 |
If-Match | 两端资源标记⽐较 |
If-Modified-Since | 本地资源未修改返回 304(⽐较时间) |
If-None-Match | 本地资源未修改返回 304(⽐较标记) |
User-Agent | 客户端信息 |
Max-Forwards | 限制可被代理及⽹关转发的次数 |
Proxy-Authorization | 向代理服务器发送验证信息 |
Range | 请求某个内容的⼀部分 |
Referer | 表示浏览器所访问的前⼀个⻚⾯ |
TE | 传输编码⽅式 |
响应字段 | 作⽤ |
---|---|
Accept-Ranges | 是否⽀持某些种类的范围 |
Age | 资源在代理缓存中存在的时间 |
ETag | 资源标识 |
Location | 客户端重定向到某个 URL |
Proxy-Authenticate | 向代理服务器发送验证信息 |
Server | 服务器名字 |
WWW-Authenticate | 获取资源需要的验证信息 |
实体字段 | 作⽤ |
---|---|
Allow | 资源的正确请求⽅式 |
Content-Encoding | 内容的编码格式 |
Content-Language | 内容使⽤的语⾔ |
Content-Length | request body ⻓度 |
Content-Location | 返回数据的备⽤地址 |
Content-MD5 | Base64 加密格式的内容 MD5 检验值 |
Content-Range | 获取资源需要的验证信息 |
Content-Type | 内容的媒体类型 |
Expires | 内容的过期时间 |
Last_modified | 内容的最后修改时间 |
http ⽆状态⽆连接
- http 协议对于事务处理没有记忆能⼒。
- 对同⼀个 url 请求没有上下⽂关系。
- 每次的请求都是独⽴的,它的执⾏情况和结果与前⾯的请求和之后的请求是⽆直接关系的,它不会受前⾯的请求应答情况直接影响,也不会直接影响后⾯的请求应答情况。
- 服务器中没有保存客户端的状态,客户端必须每次带上⾃⼰的状态去请求服务器。
- ⼈⽣若只如初⻅,请求过的资源下⼀次会继续进⾏请求。
http 协议⽆状态中的 状态 到底指的是什么?!
- 【状态】的含义就是:客户端和服务器在某次会话中产⽣的数据。
- 那么对应的【⽆状态】就意味着:这些数据不会被保留。
- 通过增加 cookie 和 session 机制,现在的⽹络请求其实是有状态的。
- 在没有状态的 http 协议下,服务器也⼀定会保留你每次⽹络请求对数据的修改,但这跟保留每次访问的数据是不⼀样的,保留的只是会话产⽣的结果,⽽没有保留会话。
http-cache:就是 http 缓存
⾸先得明确 http 缓存的好处
- 减少了冗余的数据传输,减少⽹费
- 减少服务器端的压⼒
- Web 缓存能够减少延迟与⽹络阻塞,进⽽减少显示某个资源所⽤的时间
- 加快客户端加载⽹⻚的速度
常⻅ http 缓存的类型
- 私有缓存(⼀般为本地浏览器缓存)
- 代理缓存
然后谈谈本地缓存
本地缓存是指浏览器请求资源时命中了浏览器本地的缓存资源,浏览器并不会发送真正的请求给服务器了。
- 它的执⾏过程是
- 第⼀次浏览器发送请求给服务器时,此时浏览器还没有本地缓存副本,服务器返回资源给浏览器,响应码是
200
OK ,浏览器收到资源后,把资源和对应的响应头⼀起缓存下来。 - 第⼆次浏览器准备发送请求给服务器时候,浏览器会先检查上⼀次服务端返回的响应头信息中的
Cache-Control
,它的值是⼀个相对值,单位为秒,表示资源在客户端缓存的最 ⼤有效期,过期时间为第⼀次请求的时间减去Cache-Control
的值,过期时间跟当前的请求时间⽐较,如果本地缓存资源没过期,那么命中缓存,不再请求服务器。 - 如果没有命中,浏览器就会把请求发送给服务器,进⼊缓存协商阶段。
- 第⼀次浏览器发送请求给服务器时,此时浏览器还没有本地缓存副本,服务器返回资源给浏览器,响应码是
与本地缓存相关的头有: Cache-Control
、 Expires
, Cache-Control
有多个可选值代表不同的意义,⽽ Expires
就是⼀个⽇期格式的绝对值。
Cache-Control
Cache-Control
是 HTTP
缓存策略中最重要的头,它是 HTTP/1.1
中出现的,它由如下⼏个值
no-cache :不使⽤本地缓存。需要使⽤缓存协商,先与服务器确认返回的响应是否被更改,如果之前的响应中存在 ETag ,那么请求的时候会与服务端验证,如果资源未被更 改,则可以避免重新下载。
no-store :直接禁⽌游览器缓存数据,每次⽤户请求该资源,都会向服务器发送⼀个请求,每次都会下载完整的资源。
public :可以被所有的⽤户缓存,包括终端⽤户和 CDN 等中间代理服务器。
private :只能被终端⽤户的浏览器缓存,不允许 CDN 等中继缓存服务器对其缓存。
max-age :从当前请求开始,允许获取的响应被重⽤的最⻓时间(秒)。
Cache-Control: public, max-age=1000
表示资源可以被所有⽤户以及代理服务器缓存,最⻓时间为 1000
秒。
Expires
Expires
是 HTTP/1.0
出现的头信息,同样是⽤于决定本地缓存策略的头,它是⼀个绝对时间,时间格式是如 Mon, 10 Jun 2022 21:31:12 GMT
,只要
发送请求时间是在 Expires
之前,那么本地缓存始终有效,否则就会去服务器发送请求获取新的资源。如果同时出现 Cache-Control:max-age
和
Expires
,那么 max-age
优先级更⾼。他们可以这样组合使⽤。
Cache-Control: public
Expires: Wed, Jan 10 2018 00:27:04 GMT
所谓的缓存协商
当第⼀次请求时服务器返回的响应头中存在以下情况时
- 没有
Cache-Control
和Expires
Cache-Control
和Expires
过期了Cache-Control
的属性设置为no-cache
时
那么浏览器第⼆次请求时就会与服务器进⾏协商,询问浏览器中的缓存资源是不是旧版本,需不需要更新,此时,服务器就会做出判断,如果缓存和服务端
资源的最新版本是⼀致的,那么就⽆需再次下载该资源,服务端直接返回 304 Not Modified
状态码,如果服务器发现浏览器中的缓存已经是旧版本了,那
么服务器就会把最新资源的完整内容返回给浏览器,状态码就是 200 Ok
,那么服务端是根据什么来判断浏览器的缓存是不是最新的呢?其实是根据 HTTP
的另外两组头信息,分别是: Last-Modified/If-Modified-Since
与 ETag/If-None-Match
。
Last-Modified 与 If-Modified-Since
浏览器第⼀次请求资源时,服务器会把资源的最新修改时间 Last-Modified:Thu, 29 Dec2022 18:23:55 GMT 放在响应头中返回给浏览器。
第⼆次请求时,浏览器就会把上⼀次服务器返回的修改时间放在请求头
If-ModifiedSince:Thu,29 Dec 2011 18:23:55
发送给服务器,服务器就会拿这个时间跟服务器上 的资源的最新修改时间进⾏对⽐。
如果两者相等或者⼤于服务器上的最新修改时间,那么表示浏览器的缓存是有效的,此时缓存会命中,服务器就不再返回内容给浏览器了,同时 LastModified
头也不会返回,因为资源没被修改,返回了也没什么意义。如果没命中缓存则最新修改的资源连同 Last-Modified
头⼀起返回。
Cache-Control:max-age=3600
Expires: Fri, Jan 12 2020 00:27:04 GMT
Last-Modified: Wed, Jan 10 2020 00:27:04 GMT
If-Modified-Since: Wed, Jan 10 2020 00:27:04 GMT
这组头信息是基于资源的修改时间来判断资源有没有更新,另⼀种⽅式就是根据资源的内容来判断。
ETag 与 If-None-Match
ETag/If-None-Match
与 Last-Modified/If-Modified-Since
的流程其实是类似的,唯⼀的区别是它基于资源的内容的摘要信息(⽐如 MD5 hash
)来
判断。
浏览器发送第⼆次请求时,会把第⼀次的响应头信息 ETag
的值放在 IfNone-Match
的请求头中发送到服务器,与最新的资源的摘要信息对⽐,如果
相等,取浏览器缓存,否则内容有更新,最新的资源连同最新的摘要信息返回。⽤ ETag
的好处是如果因为某种原因到时资源的修改时间没改变,那么
⽤ ETag
就能区分资源是不是有被更新。
Cache-Control: public, max-age=31536000
ETag: "15f0fff99ed5aae4edffdd6496d7131f"
If-None-Match: "15f0fff99ed5aae4edffdd6496d7131f"
HTTP 的⼏种请求⽅法⽤途
GET
⽅法- 发送⼀个请求来取得服务器上的某⼀资源。
POST
⽅法- 向
URL
指定的资源提交数据或附加新的数据。
- 向
PUT
⽅法- 跟
POST
⽅法很像,也是想服务器提交数据。但是它们之间有不同。PUT
指定了资源在服务器上的位置,⽽POST
没有。
- 跟
HEAD
⽅法- 只请求⻚⾯的⾸部。
DELETE
⽅法- 删除服务器上的某资源。
OPTIONS
⽅法- 它⽤于获取当前
URL
所⽀持的⽅法。如果请求成功,会有⼀个Allow
的头包含类似GET
,POST
这样的信息。
- 它⽤于获取当前
TRACE
⽅法TRACE
⽅法被⽤于激发⼀个远程的,应⽤层的请求消息回路。
CONNECT
⽅法- 把请求连接转换到透明的
TCP/IP
通道。
- 把请求连接转换到透明的
HTTP request 报⽂结构是怎样的
⾸⾏是
Request-Line
包括:请求⽅法,请求URI
,协议版本
,CRLF
⾸⾏之后是若⼲⾏请求头,包括
general-header
,request-header
或者entity-header
, 每个⼀⾏以CRLF
结束请求头和消息实体之间有⼀个
CRLF
分隔根据实际请求需要可能包含⼀个消息实体 ⼀个请求报⽂例⼦如下:
GET /Protocols/rfc2616/rfc2616-sec5.html HTTP/1.1
Host: www.w3.org
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,\*/
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML,
Referer: https://www.google.com.hk/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6
Cookie: authorstyle=yes
If-None-Match: "2cc8-3e3073913b100"
If-Modified-Since: Wed, 01 Sep 2004 13:24:52 GMT
name=qiu&age=25
HTTP response 报⽂结构是怎样的
⾸⾏是状态⾏包括:HTTP 版本,状态码,状态描述,后⾯跟⼀个 CRLF
⾸⾏之后是若⼲⾏响应头,包括:通⽤头部,响应头部,实体头部
响应头部和响应实体之间⽤⼀个 CRLF 空⾏分隔
最后是⼀个可能的消息实体 响应报⽂例⼦如下:
HTTP/1.1 200 OK
Date: Tue, 08 Jul 2014 05:28:43 GMT
Server: Apache/2
Last-Modified: Wed, 01 Sep 2004 13:24:52 GMT
ETag: "40d7-3e3073913b100"
Accept-Ranges: bytes
Content-Length: 16599
Cache-Control: max-age=21600
Expires: Tue, 08 Jul 2014 11:28:43 GMT
P3P: policyref="http://www.w3.org/2001/05/P3P/p3p.xml"
Content-Type: text/html; charset=iso-8859-1
{"name": "qiu", "age": 25}
HTTP 1.0 1.1 2.0
- HTTP1.0
HTTP
协议的第二个版本,第一个在通讯中指定版本号的 HTTP
协议版本 HTTP1.0
浏览器与服务器只保持短暂的连接,每次请求都需要与服务器建立一个 TCP
连接
服务器完成请求处理后立即断开 TCP
连接,服务器不跟踪每个客户也不记录过去的请求简单来讲,每次与服务器交互,都需要新开一个连接。
例如,解析 html
文件,当发现文件中存在资源文件的时候,这时候又创建单独的链接最终导致,一个 html
文件的访问包含了多次的请求和响应,每次请求都需要创建连接、关系连接
这种形式明显造成了性能上的缺陷如果需要建立长连接,需要设置一个非标准的 Connection
字段 Connection: keep-alive
。
- HTTP1.1
在 HTTP1.1
中,默认支持长连接(Connection: keep-alive
),即在一个 TCP
连接上可以传送多个 HTTP
请求和响应,减少了建立和关闭连接的消耗和延迟
建立一次连接,多次请求均由这个连接完成。
这样,在加载 html 文件的时候,文件中多个请求和响应就可以在一个连接中传输。
同时,HTTP 1.1
还允许客户端不用等待上一次请求结果返回,就可以发出下一次请求,但服务器端必须按照接收到客户端请求的先后顺序依次回送响应结果,以保证客户端能够区分出每次请求的响应内容,
这样也显著地减少了整个下载过程所需要的时间。
同时,
HTTP1.1
在HTTP1.0
的基础上,增加更多的请求头和响应头来完善的功能,如下:- 引入了更多的缓存控制策略,如
If-Unmodified-Since
,If-Match
,If-None-Match
等缓存头来控制缓存策略。 - 引入
range
,允许值请求资源某个部分。 - 引入
host
,实现了在一台 WEB 服务器上可以在同一个IP
地址和端口号上使用不同的主机名来创建多个虚拟WEB
站点并且还添加了其他的请求方法:put
、delete
、options
。
- 引入了更多的缓存控制策略,如
HTTP2.0
而 HTTP2.0 在相比之前版本,性能上有很大的提升,如添加了一个特性:
- 多路复用
- 二进制分帧
- 首部压缩
- 服务器推送
多路复用
HTTP/2
复用 TCP
连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应,这样就避免了 队头堵塞
。
上图中,可以看到第四步中 css、js 资源是同时发送到服务端
二进制分帧
- 帧是
HTTP2
通信中最小单位信息。 HTTP/2
采用二进制格式传输数据,而非HTTP 1.x
的文本格式,解析起来更高效。- 将请求和响应数据分割为更小的帧,并且它们采用二进制编码。
HTTP2
中,同域名下所有通信都在单个连接上完成,该连接可以承载任意数量的双向数据流。- 每个数据流都以消息的形式发送,而消息又由一个或多个帧组成。多个帧之间可以乱序发送,根据帧首部的流标识可以重新组装,这也是多路复用同时发送数据的实现条件。
- 帧是
首部压缩
HTTP/2
在客户端和服务器端使用“首部表”来跟踪和存储之前发送的键值对,对于相同的数据,不再通过每次请求和响应发送。- 首部表在
HTTP/2
的连接存续期内始终存在,由客户端和服务器共同渐进地更新。 - 例如:下图中的两个请求, 请求一发送了所有的头部字段,第二个请求则只需要发送差异数据,这样可以减少冗余数据,降低开销。
服务器推送
HTTP2
引入服务器推送,允许服务端推送资源给客户端。- 服务器会顺便把一些客户端需要的资源一起推送到客户端,如在响应一个页面请求中,就可以随同页面的其它资源。
- 免得客户端再次创建连接发送请求到服务器端获取。
- 这种方式非常合适加载静态资源。
- HTTP1.0:
- 浏览器与服务器只保持短暂的连接,浏览器的每次请求都需要与服务器建立一个 TCP 连接。
- HTTP1.1:
- 引入了持久连接,即 TCP 连接默认不关闭,可以被多个请求复用。
- 在同一个 TCP 连接里面,客户端可以同时发送多个请求。
- 虽然允许复用 TCP 连接,但是同一个 TCP 连接里面,所有的数据通信是按次序进行的,服务器只有处理完一个请求,才会接着处理下一个请求。如果前面的处理特别慢,后面就会有许多请求排队等着。
- 新增了一些请求方法。
- 新增了一些请求头和响应头。
- HTTP2.0:
- 采用二进制格式而非文本格式。
- 完全多路复用,而非有序并阻塞的、只需一个连接即可实现并行。
- 使用报头压缩,降低开销。
- 服务器推送。
会话状态
session
: 是⼀个抽象概念,开发者为了实现中断和继续等操作,将userAgent
和server
之间⼀对⼀的交互,抽象为会话
,进⽽衍⽣出会话状态
,也就是session
的概念。cookie
:它是⼀个世纪存在的东⻄,http
协议中定义在header
中的字段,可以认为是session
的⼀种后端⽆状态实现。- 现在我们常说的
session
,是为了绕开cookie
的各种限制,通常借助cookie
本身和后端存储实现的,⼀种更⾼级的会话状态实现。
- 现在我们常说的
session
的常⻅实现要借助 cookie
来发送 sessionID
。
cookie
,类型为「小型文本文件」,指某些网站为了辨别用户身份而储存在用户本地终端上的数据,通过响应头set-cookie
决定。作为一段一般不超过 4KB 的小型文本数据,它由一个名称(Name)、一个值(Value)和其它几个用于控制
Cookie
有效期、安全性、使用范围的可选属性组成。Cookie
主要用于以下三个方面:- 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
- 个性化设置(如用户自定义设置、主题等)
- 浏览器行为跟踪(如跟踪分析用户行为等
HTTPS
在上述介绍 HTTP
中,了解到 HTTP
传递信息是以明文的形式发送内容,这并不安全。而 HTTPS
出现正是为了解决 HTTP
不安全的特性为了保证这些隐私数据能加密传输,
让 HTTP
运行安全的 SSL/TLS
协议上,即 HTTPS = HTTP + SSL/TLS
,通过 SSL
证书来验证服务器的身份,并为浏览器和服务器之间的通信进行加密 SSL
协议位于 TCP/IP
协议与各种应用层协议之间,浏览器和服务器在使用 SSL
建立连接时需要选择一组恰当的加密算法来实现安全通信,为数据通讯提供安全支持。
- 流程图如下所示:
首先客户端通过
URL
访问服务器建立SSL
连接。服务端收到客户端请求后,会将网站支持的证书信息(证书中包含公钥)传送一份给客户端。
客户端的服务器开始协商
SSL
连接的安全等级,也就是信息加密的等级。客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。
服务器利用自己的私钥解密出会话密钥。
服务器利用会话密钥加密与客户端之间的通信。
区别
HTTPS
是HTTP
协议的安全版本,HTTP
协议的数据传输是明文的,是不安全的,HTTPS
使用了SSL/TLS
协议进行了加密处理,相对更安全。HTTP
和HTTPS
使用连接方式不同,默认端口也不一样,HTTP
是80
,HTTPS
是443
。HTTPS
由于需要设计加密以及多次握手,性能方面不如HTTP
。HTTPS
需要SSL
,SSL
证书需要钱,功能越强大的证书费用越高。