HTTP(Hyper Text Transfer Protocol)<超文本传输协议>的缩写.是用于从WWW服务器传输超文本到本地浏览器的传输协议.HTTP是一个应用层协议,由请求和响应构成,是一个标准的个客户端和服务器模型
1. http协议发展史
HTTP/0.9
HTTP 于 1990 年问世。那时的 HTTP 并没有作为正式的标准被建立。现在的 HTTP 其实含有 HTTP1.0 之前 版本的意思,因此被称为 HTTP/0.9。
该版本只有一个命令GET,没有header等描述数据的信息,服务器只能回应HTML格式的字符串,不能回应别的格式。服务器发送完毕,就关闭tcp连接。
HTTP/1.0
HTTP 正式作为标准被公布是在 1996 年的 5 月,版本被命名为 HTTP/1.0,并记载于 RFC1945。
首先,任何格式的内容都可以发送。这使得互联网不仅可以传输文字,还能传输图像、视频、二进制文件。这为互联网的大发展奠定了基础。
其次,除了GET命令,还引入了POST命令和HEAD命令,丰富了浏览器与服务器的互动手段。
再次,HTTP请求和回应的格式也变了。除了数据部分,每次通信都必须包括头信息(HTTP header),用来描述一些元数据。
其他的新增功能还包括状态码(status code)、多字符集支持、多部分发送(multi-part type)、权限(authorization)、缓存(cache)、内容编码(content encoding)等。
HTTP/1.0 版的主要缺点是,每个TCP连接只能发送一个请求。发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接。TCP连接的新建成本很高,因为需要客户端和服务器三次握手,并且开始时发送速率较慢(slow start)。所以,HTTP 1.0版本的性能比较差。随着网页加载的外部资源越来越多,这个问题就愈发突出了。
为了解决这个问题,有些浏览器在请求时,用了一个非标准的Connection字段。这个字段要求服务器不要关闭TCP连接,以便其他请求复用。服务器同样回应这个字段。Connection: keep-alive
一个可以复用的TCP连接就建立了,直到客户端或服务器主动关闭连接。但是,这不是标准字段,不同实现的行为可能不一致,因此不是根本的解决办法。
HTTP/1.1
1997 年 1 月公布的 HTTP/1.1, 比1.0版本晚了半年,它进一步完善了HTTP协议,是目前主流的 HTTP 协议版本。
1.1 版增加了请求命令(OPTIONS、PUT、PATCH、DELETE、TRACE、CONNECTION。客户端请求的头信息新增了Host字段,用来指定服务器的域名。
1.1 版的最大变化,就是引入了持久连接(persistent connection),即TCP连接默认不关闭,可以被多个请求复用,不用声明Connection: keep-alive
。
客户端和服务器发现对方一段时间没有活动,就可以主动关闭连接。不过,规范的做法是,客户端在最后一个请求时,发送Connection: close,明确要求服务器关闭TCP连接。
目前,对于同一个域名,大多数浏览器允许同时建立6个持久连接。
缺点: 虽然1.1版允许复用TCP连接,但是同一个TCP连接里面,所有的数据通信是按次序进行的。服务器只有处理完一个回应,才会进行下一个回应。要是前面的回应特别慢,后面就会有许多请求排队等着。这称为队头堵塞
。
为了避免这个问题,只有两种方法:一是减少请求数,二是同时多开持久连接。这导致了很多的网页优化技巧,比如合并脚本和样式表、将图片嵌入CSS代码、域名分片(domain sharding)等等。如果HTTP协议设计得更好一些,这些额外的工作是可以避免的。
HTTP/2.0
HTTP/2.0版本中所有数据以二进制(最小数据单位是帧)传输,HTTP/1.1中大部分数据通过字符串的形式;同一个连接里面发送多个请求不再需要按照顺序来;头信息压缩以及推送等提高效率的功能。 HTTP/2.0 正在制订中,但要达到 较高的使用覆盖率,仍需假以时日。
2. 网络基础
2.1经典五层模型
- 物理层主要作用是定义物理设备如何传输数据,机器的硬件,网卡端口,网线等。
- 数据链路层在通信的实体间建立数据链路连接,比如最基础的数据传输数据流,可以自己选择二进制或者ASCII码形式等。
- 网络层为数据在结点之间传输创建逻辑链路,比如输入百度,网络层会为我们找到百度的网址,如何寻找到的过程就是网络层要做的事。
- 传输层: 向用户提供可靠的端到端(end-to-end)服务;传输层向高层屏蔽了下层数据通信的细节(比如一个post请求,如何分片如何发送使服务端很好接收到,这个规则由传输层实现,应用层的HTTP不用关心这些,但是适当理解对HTTP更好地使用是很有帮助的)。
- 应用层: 为应用软件提供了很多服务,帮我们实现了HTTP协议,我们只要按照规则去使用HTTP协议;它构建于TCP协议之上;屏蔽了网络传输相关细节。
2.2 DNS服务器的作用
用户通常使用主机名称或者域名来访问对方的计算机,因为更好记住。但是计算机更擅长处理IP地址这样的一串数字。DNS服务就是为了解决这个问题,DNS协议通过域名查找IP地址,或者逆向从IP地址查询域名的服务。
2.3 TCP
TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
建立起一个TCP连接需要经过三次握手
, 关闭TCP连接需要经过四次挥手
。
3. 三次握手与四次挥手
3.1 三次握手
1)发送端首先发送一个带有SYN(synchronize)标志地数据包给接收方。
2)接收方接收后,回传一个带有SYN/ACK标志的数据包传递确认信息,表示我收到了。
3)最后,发送方再回传一个带有ACK标志的数据包,代表我知道了,表示’握手‘结束。
通俗的说法
1)Client:嘿,李四,是我,听到了吗?
2)Server:我听到了,你能听到我的吗?
3)Client:好的,我们互相都能听到对方的话,我们的通信可以开始了。
其中 位码即tcp标志位,有6种标示:
- SYN(synchronous建立联机)
- ACK(acknowledgement 确认)
- PSH(push传送)
- FIN(finish结束)
- RST(reset重置)
- URG(urgent紧急)
- Sequence number(顺序号码)
- Acknowledge number(确认号码)
注:为什么是三次握手
因为网络传输有延迟,客户端发送请求到服务器端要求即那里连接,如果服务器直接返回的话可能会产生丢包的情况导致客户端收不到数据,客户端会因为超时就关闭了,可能就去发送新的请求了,然而服务器端并不知道丢包导致客户端没有接收数据。服务器端t端口就一直开着,造成额外的开销。所以需要三次握手确认这个过程。
3.2. 四次挥手
1)第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
2)第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手
通俗的说法
1)Client:我所有东西都说完了。
2)Server:我已经全部听到了,但是等等我,我还没说完。
3)Server:好了,我已经说完了。
4)Client:好的,那我们的通信结束。
注:TCP为什么要进行四次挥手
4次挥手的目的是终止数据传输,并回收资源,此时两个端点两个方向的序列号已经没有了任何关系,必须等待两方向都没有数据传输时才能拆除虚链路,不像初始化时那么简单,发现SYN标志就初始化一个序列号并确认SYN的序列号。因此必须单独分别在一个方向上终止该方向的数据传输。
4. HTTP工作过程
一次HTTP操作称为一个事务,其工作整个过程如下:
1 ) 地址解析如用客户端浏览器请求这个页面:http://localhost.com:8080/index.html
从中分解出协议名、主机名、端口、对象路径等部分,对于我们的这个地址,解析得到的结果如下:
协议名:http
主机名:localhost.com
端口:8080
对象路径:/index.htm
在这一步,需要域名系统DNS解析域名localhost.com,得主机的IP地址。
2)封装HTTP请求数据包
把以上部分结合本机自己的信息,封装成一个HTTP请求数据包
3)封装成TCP包,建立TCP连接(TCP的三次握手)
在HTTP工作开始之前,客户机(Web浏览器)首先要通过网络与服务器建立连接,该连接是通过TCP来完成的,该协议与IP协议共同构建Internet,即著名的TCP/IP协议族,因此Internet又被称作是TCP/IP网络。HTTP是比TCP更高层次的应用层协议,根据规则,只有低层协议建立之后才能进行更高层协议的连接,因此,首先要建立TCP连接,一般TCP连接的端口号是80。这里是8080端口
4)客户机发送请求命令
建立连接后,客户机发送一个请求给服务器,请求方式的格式为:统一资源标识符(URI:Uniform Resource Identifier)、协议版本号,后边是MIME信息包括请求修饰符、客户机信息和可能的内容。
5)服务器响应
服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后边是MIME信息包括服务器信息、实体信息和可能的内容。
实体消息是服务器向浏览器发送头信息后,它会发送一个空白行来表示头信息的发送到此结束,接着,它就以Content-Type应答头信息所描述的格式发送用户所请求的实际数据
6)服务器关闭TCP连接
一般情况下,一旦Web服务器向浏览器发送了请求数据,它就要关闭TCP连接,然后如果浏览器或者服务器在其头信息加入了这行代码Connection:keep-alive
TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了网络带宽。
经典面试题【从输入URL到页面加载发生了什么?】
- DNS解析:如果地址包含域名通过DNS解析获取服务器对应的ip地址,如果输入的URL不包含域名则不经过这一步。
- TCP连接 : 经过DNS解析后获取到了服务器的IP地址,在获取到IP地址后,便会开始建立一次连接(三次握手)。
- 发送HTTP请求: 在确认与服务器建立连接后,便会发送一个HTTP请求。
- 服务器处理请求并返回HTTP报文: 服务器在收到浏览器发送的HTTP请求之后,会将收到的HTTP报文封装成HTTP的Request对象,并通过不同的Web服务器进行处理,处理完的结果以HTTP的Response对象返回,主要包括状态码,响应头,响应报文三个部分。
- 浏览器解析渲染页面
- 连接结束: 在页面元素传输完成后,会选择关闭连接(TCP四次挥手)。
5. http报文
报文(message)
报文是网络中交换与传输的数据单元,也是网络传输的单元。报文包含了将要发送的完整的数据信息,其长短不需一致。报文在传输过程中会不断地封装成分组、包、帧来传输,封装的方式就是添加一些控制信息组成的首部,那些就是报文头。
http有两种报文
- 请求报文: 请求行、首部字段、报文主体(请求正文)
- 响应报文:状态行、首部字段、报文主体(响应正文)
请求行(HTTP请求报文的第一行)
请求行由方法字段、URL字段和HTTP协议版本字段。其中,方法字段严格区分大小写,当前HTTP协议中的方法都是大写。
- 方法字段如下介绍如下(请求方法用来定义队对资源的操作)
1)GET:请求获取Request-URI(URI:通用资源标识符,URL是其子集,URI注重的是标识,而URL强调的是位置,可以将URL看成原始的URI),所标识的资源
2)POST:在Request-URI所标识的资源后附加新的数据;支持HTML表单提交,表单中有用户添入的数据,这些数据会发送到服务器端,由服务器存储至某位置(例如发送处理程序)
3)HEAD:请求Request-URI所标识的资源响应消息报头,HEAD方法可以在响应时不返回消息体。
4)PUT:与GET相反,请求服务器存储一个资源,并用Request-URI做为其标识;例如发布系统。
5)DELETE:请求删除URL指向的资源
6)OPTIONS:请求查询服务器的性能,或者查询与资源相关的选项
7)TRACE:跟踪请求要经过的防火墙、代理或网关等,主要用于测试或诊断
8)CONNECT保留将来使用
状态行 HTTP响应报文的第一行
状态行包括三个字段:协议版本、状态码与原因短语
- 状态码
状态码由三位数字组成,第一个数字定义了响应的类别, 且由5种取值:
1)1xx: 指示消息--表示已接收,继续处理
2)2xx: 成功--表示请求已被成功接收、理解、接收
3)3xx: 重定向--要完成请求必须进行更进一步的操作
4)4xx: 客户端错误--请求有语法错误或请求无法实现
5)5xx:服务器端错误--服务器端未能实现合法的请求
6. 跨域
1. 什么是跨域
浏览器的同源策略限制了跨域请求资源。即当一个请求url的协议、域名、端口三者之间任意一与当前页面地址不同即为跨域。
2. 实现跨域的常用方法
(1) jsonp (JSON+Padding)将JSON数据填充进回调函数
jsonp 是解决跨域问题的一种方案,不同于 json,其并不是一种数据交换格式,而只是一种绕过跨域的技巧。
简单来说就是创建一个回调函数,然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调。 因为在HTML标签里,一些标签比如script、img、iframe这样的拥有src属性获取资源的标签是没有跨域限制的。因此利用script加载预设的 callback 将内容传递给 js。一般来说我们约定通过一个参数来告诉服务器 JSONP 返回时应该调用的回调函数名,然后拼接出对应的 js。以下为一个简单例子。
html页面
服务器端返回
# 服务器端通过获取请求参数重的callback名称, 拼出返回值。
infoHandler({
"name": "shirley",
"age":18,
"gender": "female",
"idCard": "23213123231232ui323"
});
缺点是JSONP只能发GET请求,因为本质上script加载资源就是GET请求
(2) CORS
CORS:是一个W3C标准, Cross-origin resource sharing 即 “跨域资源共享”。它允许浏览器向跨源服务器,发出XMLHttpRequest
请求,从而克服了AJAX只能同源使用的限制。
CORS需要客户端和服务端同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。整个CORS通信过程,都是浏览器自动完成,不需要用户参与。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
- CORS请求分类
浏览器将CORS请求分成两类:请求简单请求
(simple request)和非简单请求
(not-so-simple request)。
简单请求: 请求满足以下两个条件的就是简单请求
1. 请求方法是以下三种方法之一:HEAD,GET,POST 。
2. HTTP的头信息不超出以下几种字段
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
非简单请求: 不满足上面两个条件的就是非简单请求。
注意
1、对于简单请求,浏览器直接请求,会在请求头信息中,增加一个origin字段,来说明本次请求来自哪个源(协议+域名+端口)。服务器根据这个值,来决定是否同意该请求,服务器返回的响应会多几个头信息字段。
2、非简单请求是对那种对服务器有特殊要求的请求,都会在正式通信之前,增加一次HTTP请求,称之为预检(options请求)。浏览器会先询问服务器,当前网页所在域名是否在服务器的许可名单之中,服务器允许之后,浏览器会发出正式的XMLHttpRequest请求,否则会报错。
options请求: options请求是浏览器自发起的preflight request(预检请求),获取响应后发现可以跨域,接着就发送真实的请求。
- 服务器端实现跨域CORS接口
1、设置Access-Control-Allow-Origin
'Access-Control-Allow-Origin': 'http://XXX.com' // 设置接指定地址的请求或设置为'*' 表示接受任意域名的请求
- 除get、post、head请求方法和其它自定义的请求头 即非简单请求时。预请求验证通过才能发送。
'Access-Control-Allow-Methods': 'POST,PUT,HEAD'
'Access-Control-Allow-Headers': 'X-Test-Cors', //设置自定义的请求头
设置缓存, 允许浏览器在指定时间内,无需再发送预检请求,直接用本次结果即可。
'Access-Control-Max-Age': '5', //秒为单位 -1是不缓存 5秒一下chrome都默认是5
设置是否可以携带cookie
'Access-Control-Allow-Credentials': true,//如果Access-Control-Allow-Origin字段设置* 此字段设为true无效
(3) nginx反向代理
原理是:同源策略只是浏览器的安全策略,不是HTTP协议的一部分。服务器端调用HTTP接口只是使用HTTP协议,不会执行JS脚本,不需要同源策略,也就不存在跨越问题。
// Nginx配置如下:
server{
# 监听8001端口
listen 8001;
# 域名是localhost
server_name localhost;
#凡是localhost:8001/api这个样子的,都转发到真正的服务端地址http://localhost:9001
location ^~ /api {
proxy_pass http://localhost:9001;
}
7. 首部字段
上面的HTTP报文介绍了首部字段。首部字段同时存在于请求和响应报文内,并涵盖 HTTP 报文相关的内容信息。使用首部字段是为了给客服端和服务器端提供报文主体大小、所使用的语言、认证信息等内容。
首部字段结构
由首部字段名和字段值,中间用冒号分割。 例如 Content-Type:text/html
注 : HTTP 报文首部中出现了两个或以上具有相同首部字段名的首部字段时,这种情况在规范内尚未明确,根据浏览器内部处理逻辑的不同,优先处理的顺序可能不同,结果可能并不一致。首部字段类型
HTTP 首部字段根据实际用途被分为以下 4 种类型:
1. 通用首部字段(General Header Fields)
请求报文和响应报文两方都会使用的首部。
2. 请求首部字段(Request Header Fields)
从客户端向服务器端发送请求报文时使用的首部。补充了请求的附加内容、客户端信息、响应内容相关优先级等信息。
3. 响应首部字段(Response Header Fields)
从服务器端向客户端返回响应报文时使用的首部。补充了响应的附加内容,也会要求客户端附加额外的内容信息。
4. 实体首部字段(Entity Header Fields)
针对请求报文和响应报文的实体部分使用的首部。补充了资源内容更新时间等与实体有关的信息。通用首部字段 (HTTP/1.1)
Cache-Control 控制缓存的行为
Connection 逐挑首部、连接的管理
Date 创建报文的日期时间
Pragma 报文指令
Trailer 报文末端的首部一览
Transfer-Encoding 指定报文主体的传输编码方式
Upgrade 升级为其他协议
Via 代理服务器的相关信息
Warning 错误通知请求首部字段
Accept 用户代理可处理的媒体类型
Accept-Charset 优先的字符集
Accept-Encoding 优先的内容编码
Accept-Language 优先的语言(自然语言)
Authorization Web认证信息
Expect 期待服务器的特定行为
From 用户的电子邮箱地址
Host 请求资源所在服务器
If-Match 比较实体标记(ETag)
If-Modified-Since 比较资源的更新时间
If-None-Match 比较实体标记(与 If-Match 相反)
If-Range 资源未更新时发送实体 Byte 的范围请求
If-Unmodified-Since 比较资源的更新时间(与If-Modified-Since相反)
Max-Forwards 最大传输逐跳数
Proxy-Authorization 代理服务器要求客户端的认证信息
Range 实体的字节范围请求
Referer 对请求中 URI 的原始获取方
TE 传输编码的优先级
User-Agent HTTP 客户端程序的信息响应首部字段
Accept-Ranges 是否接受字节范围请求
Age 推算资源创建经过时间
ETag 资源的匹配信息
Location 令客户端重定向至指定URI
Proxy-Authenticate 代理服务器对客户端的认证信息
Retry-After 对再次发起请求的时机要求
Server HTTP 服务器的安装信息
Vary 代理服务器缓存的管理信息
WWW-Authenticate 服务器对客户端的认证信息
- 实体首部字段
Allow 资源可支持的HTTP方法
Content-Encoding 实体主体适用的编码方式
Content-Language 实体主体的自然语言
Content-Length 实体主体的大小(单位:字节)
Content-Location 替代对应资源的URI
Content-MD5 实体主体的报文摘要
Content-Range 实体主体的位置范围
Content-Type 实体主体的媒体类型
Expires 实体主体过期的日期时间
Last-Modified 资源的最后修改日期时间
7.1 Cache-Control
通过指定首部字段 Cache-Control 的指令,就能操作缓存的工作机制。指令的参数是可选的,多个指令之间通过“,”分隔。比如: Cache-Control: private, max-age=0, no-cache。
-
缓存请求指令
-
缓存响应指令
Pragma和Expires也与缓存相关,Pragma是旧产物,已经逐步抛弃,有些网站为了向下兼容还保留了这两个字段。优先级从高到低是:Pragma -> Cache-Control -> Expires
Cache-Control除了在响应中使用,在请求中也可以使用。我们用开发者工具来模拟下请求时带上Cache-Control:勾选Disable cache,刷新页面,可以看到Request Headers中有个字段Cache-Control: no-cache。
7.2 Connection
Connection 首部字段具备以下两个作用:
-
控制不再转发的首部字段
Connection: Upgrade
在客户端发送请求和服务器返回响应中,使用 Connection 首部字段,可控制不再转发给代理的首部字段,即删除后再转发(即Hop-by-hop首部)。
- 管理持久连接
- Connection: close
HTTP/1.1 版本的默认连接都是持久连接。当服务器端想明确断开连接时,则指定 Connection 首部字段的值为 close。 - Connection: Keep-Alive
HTTP/1.1 之前的 HTTP 版本的默认连接都是非持久连接。为此,如果想在旧版本的 HTTP 协议上维持持续连接,则需要指定 Connection 首部字段的值为 Keep-Alive。
7.3 Date
Date 表明创建 HTTP 报文的日期和时间
7.4 Accept
Accept: text/html, application/xhtml+xml, application/xml; q=0.5
- Accept 首部字段可通知服务器,用户代理能够处理的媒体类型及媒体类型的相对优先级。可使用 type/subtype 这种形式,一次指定多种媒体类型。
- 若想要给显示的媒体类型增加优先级,则使用 q=[数值] 来表示权重值,用分号(;)进行分隔。权重值的范围 0~1(可精确到小数点后三位),且 1 为最大值。不指定权重值时,默认为 1。当服务器提供多种内容时,将会首先返回权重值最高的媒体类型。
7.5 Accept-Encoding
Accept-Encoding: gzip, deflate
Accept-Encoding 首部字段用来告知服务器用户代理支持的内容编码及内容编码的优先顺序,并可一次性指定多种内容编码。同样使用 q=[数值] 来表示相对优先级。也可使用星号(*)作为通配符,指定任意的编码格式。
7.6 Accept-Language
Accept-Lanuage: zh-cn,zh;q=0.7,en=us,en;q=0.3
告知服务器用户代理能够处理的自然语言集(指中文或英文等),以及自然语言集的相对优先级,可一次性指定多种自然语言集。同样使用 q=[数值] 来表示相对优先级。
7.7 Host
Host: localhost:8001
首部字段 Host 会告知服务器,请求的资源所处的互联网主机名和端口号。Host 首部字段在 HTTP/1.1 规范内是唯一一个必须被包含在请求内的首部字段。
首部字段 Host 和以单台服务器分配多个域名的虚拟主机的工作机制有很密切的关联,这是首部字段 Host 必须存在的意义
7.8 User-AgentUser-Agent
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
- 首部字段 User-Agent 会将创建请求的浏览器和用户代理名称等信息传达给服务器。
- 由网络爬虫发起请求时,有可能会在字段内添加爬虫作者的电子邮件地址。此外,如果请求经过代理,那么中间也很可能被添加上代理服务器的名称。
7.9 Allow
Allow: GET, HEAD
- 首部字段 Allow 用于通知客户端能够支持 Request-URI 指定资源的所有 HTTP 方法。
- 当服务器接收到不支持的 HTTP 方法时,会以状态码 405 Method Not Allowed 作为响应返回。与此同时,还会把所有能支持的 HTTP 方法写入首部字段 Allow 后返回。
7.10 Content-Encoding
Content-Encoding: gzip
- 首部字段 Content-Encoding 会告知客户端服务器对实体的主体部分选用的内容编码方式。内容编码是指在不丢失实体信息的前提下所进行的压缩。
- 主要采用这 4 种内容编码的方式(gzip、compress、deflate、identity)。
7.11 Content-Language
Content-Language: zh-CN
首部字段 Content-Language 会告知客户端,实体主体使用的自然语言(指中文或英文等语言)。
7.12 Content-Type
Content-Type: text/html; charset=UTF-8
首部字段 Content-Type 说明了实体主体内对象的媒体类型。和首部字段 Accept 一样,字段值用 type/subtype 形式赋值。参数 charset 使用 iso-8859-1 或 euc-jp 等字符集进行赋值。
7.13 Expires
Expires: Mon, 10 Jul 2017 15:50:06 GMT
- 首部字段 Expires 会将资源失效的日期告知客户端。
- 缓存服务器在接收到含有首部字段 Expires 的响应后,会以缓存来应答请求,在 Expires 字段值指定的时间之前,响应的副本会一直被保存。当超过指定的时间后,缓存服务器在请求发送过来时,会转向源服务器请求资源。
- 源服务器不希望缓存服务器对资源缓存时,最好在 Expires 字段内写入与首部字段 Date 相同的时间值。
7.14 Cookie
服务器在响应头中用Set-Cookie头将Cookie的内容回送给客户端,客户端在新的请求中将相同的内容携带在cookie头中发送给服务器,从而实现会话的保持。
- 响应首部字段
setCookie: name=aaa; expires=Mon, 10 Jul 2017 15:50:06 GMT; path=/
属性 说明
NAME=VALUE 赋予 Cookie 的名称和其值(必需项)
expires=DATE Cookie 的有效期(若不明确指定则默认为浏览器关闭前为止)
path=PATH 将服务器上的文件目录作为Cookie的适用对象(若不指定则默认为文档所在的文件目录)
domain=域名 作为 Cookie 适用对象的域名 (若不指定则默认为创建 Cookie的服务器的域名)
Secure 仅在 HTTPS 安全通信时才会发送 Cookie
HttpOnly 加以限制,使 Cookie 不能被 JavaScript 脚本访问 - 请求首部字段 Cookie
Cookie: status=enable
首部字段 Cookie 会告知服务器,当客户端想获得 HTTP 状态管理支持时,就会在请求中包含从服务器接收到的 Cookie。接收到多个 Cookie 时,同样可以以多个 Cookie 形式发送。
7.15 CSP(content-security-policy)内容安全策略
实质是建立报名单制度,明确的告诉客户端,哪些外部资源可以加载和执行。所以使用 CSP 来防止 XSS攻击(跨域脚本攻击)。
Content-Security-Policy: 'default-src \'self\'
表示只能加载同域下资源。
Content-Security-Policy: 'default-src \'self\'; report-uri /report'
表示只能加载同域下资源, 且会发送一个违例报告。默认情况下,违规报告并不会发送。为启用发送违规报告,你需要指定 report-uri策略指令,并提供至少一个URI地址去递交报告。
如果我只想收集报告,但是不真正的去限制请求,那怎么办?除了Content-Security-Policy,还有一个Content-Security-Policy-Report-Only
字段,表示不执行限选项,只是记录违反限制的行为。将头部改为这个即可。
注: default-src
设置的是全局,如果我只想限制js的请求,可以将default-src改为script-src, 限制图片请求可用img-src
使用meta标签达到一样的效果。
详细用法可以参考Content Security Policy
7.16 Sec-Fetch-*
简单来说,就是网络请求的元数据描述,服务端根据这些补充数据进行细粒度的控制响应。浏览器自动带上的请求头,都是Forbidden header,也就是不能被篡改的。
Sec-Fetch-Dest
: 期望需要什么样的资源,比如 script。
Sec-Fetch-Mode
: 表明了一个请求的模式,比如是否跨域。
Sec-Fetch-Site
: 请求发起者的来源与目标资源来源之间的关系,比如跨域就为 cross-site
。
7.17 其它首部字段
HTTP 首部字段是可以自行扩展的。所以在 Web 服务器和浏览器的应用上,会出现各种非标准的首部字段。
例如: X-Frame-Options
: 用于控制网站内容在其他 Web 网站的 iframe 标签内的显示问题。
8. TCP长连接
短连接的操作步骤是:
建立连接——数据传输——关闭连接...建立连接——数据传输——关闭连接长连接的操作步骤是:
建立连接——数据传输...(保持连接)...数据传输——关闭连接-
持久的连接节省通信
每次进行HTTP请求的时候,都要先建立TCP连接,然后结束之后再断开TCP连接。这样如果在同一份HTML文档中有大量的图片等资源,就会建立和断开多次TCP连接,造成资源的浪费。HTTP1.1和一部分HTTP1.0想出了持久连接。持久连接的特点:只要任意一端没有明确断开连接,就保持TCP的链接状态。这样不会因为频繁的建立和断开TCP连接造成额外的开销,减轻了服务器的负载。同时减少了HTTP请求和响应的时间。
TCP connection
Connection: keep-alive/close(开启/关闭)
HTTP2只需要建立一个TCP长连接(同域下)
那是不是只需要建立一个TCP连接,然后发送多个HTTP请求就可以了? 不行。
HTTP/1.1 存在一个问题:单个 TCP 连接在同一时刻只能处理一个请求。如果一个网页上有多个资源需要请求,肯定不能只开一个TCP连接,然后按请求顺序下载,那样用户肯定等的很难受。
所以Chrome最多允许对同一个 Host 建立六个 TCP 连接。(不同的浏览器允许的连接数不同。就解释了之前我们所了解到的的浏览器请求的最大并发量是6个(以chrome为例)。
相关文章
CORS
JSONP
HTTP
你知道一个TCP连接上能发起多少个HTTP请求吗?