HTTP
HTTP基本概念
HTTP是什么
HTTP 超文本传输协议
- 传输:两点之间,可以是本地浏览器和服务器,也可以是服务器和服务器
- 超文本:文字、图片、视频等文本的混合体,并且有超链接,能从一个超文本跳转到另一个超文本
HTTP常见状态码
五大类HTTP状态码
1XX:提示信息,表示协议处理的一种中间状态
2XX:报文已经被收到并被正确处理
- 200 OK:表示一切正常,如果是非 HEAD 请求,服务器返回的响应头都会有 body 数据。
- 204 No Content:与 200 OK 基本相同,但响应头没有 body 数据
- 206 Partical 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:笼统的错误码,表示服务器发生错误,发生什么错误不知道
- 501 Not Implemented:客户端请求的功能还不支持,“即将开业,敬请期待”
- 502 Bad Gateway:服务器作为网关或者代理时返回的错误码,表示服务器自身工作正常,访问后端服务器时发生了错误
- 503 Service Unavailable:表示服务器当前正忙,暂时无法响应,“网络服务正忙,请稍后再试”
HTTP常见字段
host
:客户端发送请求时,指定服务器的域名Content-Length
:本次回应数据的长度,解决“粘包”
HTTP协议解决粘包的方法:1. 设置回车符、换行符作为http header的边界;2.通过
Conten-Length
字段作为http body的边界
Connection
:用于客户端要求服务器使用“HTTP长连接”机制,以便其他请求复用
HTTP长连接的特点:只要任意一端没有明确提出断开连接,则保持TCP连接状态
HTTP/1.1版本默认使用长连接,为了兼容旧版本,所以设定Connection
字段的值为Keep-Alive
ps:注意 HTTP Keep-Alive 和 TCP Keepalive 不是一个东西
Accept
:客户端请求的时候,声明自己可以接受哪些数据格式,Accept: */*
:客户端声明自己可以接受任何格式的数据Content-Type
:服务器回应时,告诉客户端,本次数据是什么格式,Content-Type: text/html; Charset=utf-8
:表明,发送的是网页,而且编码是UTF-8Accept-Encoding
:客户端在请求时,说明自己可以接受哪些压缩方法,Accept-Encoding: gzip, deflate
Content-Encoding
:说明数据的压缩方法,表示服务器返回的数据使用了什么压缩格式,Content-Encoding: gzip
GET与POST
GET和POST的区别
GET和POST的语义区别
(根据RFC规范)
- GET:从服务器获取指定的资源,请求的参数位置一般是写在 URL 中,URL 规定只能支持 ASCII,所以 GET 请求的参数只允许 ASCII 字符 ,而且浏览器会对 URL 的长度有限制(HTTP协议本身对 URL长度并没有做任何规定)。
- POST:根据请求负荷(报文body)对指定的资源做出处理,POST 请求携带数据的位置一般是写在报文 body 中,body 中的数据可以是任意格式的数据,只要客户端与服务端协商好即可,而且浏览器不会对 body 大小做限制
安全和幂等的概念:
- 安全:HTTP协议里所谓的安全是请求方法不会破坏服务器上的资源
- 幂等:多次执行相同的操作,结果都是相同的
GET 和 POST 方法是否安全和幂等
(RFC 规范定义)
- GET 方法就是安全且幂等的,因为它是只读操作,无论操作多少次,服务器上的数据都是安全的,且每次的结果都是相同的。所以,可以对 GET 请求的数据做缓存,这个缓存可以做到浏览器本身上(彻底避免浏览器发请求),也可以做到代理上(如nginx),而且在浏览器中 GET 请求可以保存为书签
- POST 因为是新增或提交数据的操作,会修改服务器上的资源,所以是不安全的,且多次提交数据就会创建多个资源,所以不是幂等的。所以,浏览器一般不会缓存 POST 请求,也不能把 POST 请求保存为书签。
注意: 上面是从 RFC 规范定义的语义来分析的,但是实际过程中,开发者不一定会按照 RFC 规范定义的语义来实现 GET 和 POST 方法。比如:
- 可以用 GET 方法实现新增或删除数据的请求,这样实现的 GET 方法自然就不是安全和幂等。
- 可以用 POST 方法实现查询数据的请求,这样实现的 POST 方法自然就是安全和幂等。
Q:GET 请求可以带 body 吗?
A:RFC 规范并没有规定 GET 请求不能带 body 的。理论上,任何请求都可以带 body 的。只是因为 RFC 规范定义的 GET 请求是获取资源,所以根据这个语义不需要用到 body。
另外,URL 中的查询参数也不是 GET 所独有的,POST 请求的 URL 中也可以有参数的
HTTP缓存技术
HTTP缓存的实现方式
重复性的HTTP请求,每次都会得到相同的结果——>[请求-响应]——>缓存在本地,下次直接从缓存读取,不用通过网络从服务器获取,提升性能
HTTP缓存的实现方式:1.强制缓存;2.协商缓存
强制缓存
强制缓存:浏览器判断缓存没有过期,则直接使用浏览器的本地缓存,主动权在浏览器
实现字段:Cache-Control
:相对时间,优先级更高,建议使用Expires
:绝对时间
实现流程:
- 浏览器第一次请求访问时,服务器返回资源的同时,在响应报文头部加上
Cache-Control
,设置了过期时间的大小 - 浏览器再次请求访问资源时,先通过请求资源的时间和过期时间,判断资源是否过期,如果没过期就使用缓存,否则重新请求服务器
- 服务器再次返回资源时,会更新response头部的
Cache-Control
协商缓存
响应码304:告诉浏览器可以使用本地缓存
协商缓存:通过服务器告知客户端是否可以使用缓存,即浏览器和服务端协商之后,通过协商结果判断是否使用本地缓存
注意:协商缓存这两个字段都需要配合强制缓存中 Cache-Control 字段来使用,只有在未能命中强制缓存的时候,才能发起带有协商缓存字段的请求。
实现字段:
- 请求头部中的
If-Modified-Since
和响应头部中的Last-Modified
字段实现
a.If-Modified-Since
:资源过期,发现响应头中具有Last-Modified
声明,则再次发起请求的时候带上Last-Modified
的时间,服务器收到请求后发现有If-Modified-Since
则与被请求资源的最后修改时间进行对比(Last-Modified
),如果最后修改时间较新(大),说明资源又被改过,则返回最新资源,HTTP 200 OK;如果最后修改时间较旧(小),说明资源无新修改,响应 HTTP 304 缓存。
b.Last-Modified
:响应资源的最后修改时间
2.请求头部中的 If-None-Match
字段与响应头部中的 ETag
字段
a. ETag
:唯一标识响应资源
b. If-None-Match
:资源过期时,浏览器发现响应头里有 Etag,则再次向服务器发起请求时,会将请求头 If-None-Match 值设置为 Etag 的值。服务器收到请求后进行比对,如果资源没有变化返回 304,如果资源变化了返回 200
第一种实现方式是基于时间实现的,第二种实现方式是基于一个唯一标识实现的,相对来说后者可以更加准确地判断文件内容是否被修改,避免由于时间篡改导致的不可靠问题。
如果在第一次请求资源的时候,服务端返回的 HTTP 响应头部同时有 Etag 和 Last-Modified 字段,那么客户端再下一次请求的时候,如果带上了 ETag 和 Last-Modified 字段信息给服务端,这时 Etag 的优先级更高,也就是服务端先会判断 Etag 是否变化了,如果 Etag 有变化就不用在判断 Last-Modified 了,如果 Etag 没有变化,然后再看 Last-Modified。
为什么 ETag 的优先级更高?
这是因为 ETag 主要能解决 Last-Modified 几个比较难以解决的问题:
- 在没有修改文件内容情况下文件的最后修改时间可能也会改变,这会导致客户端认为这文件被改动了,从而重新请求;
- 可能有些文件是在秒级以内修改的,If-Modified-Since 能检查到的粒度是秒级的,使用 Etag就能够保证这种需求下客户端在 1 秒内能刷新多次;
- 有些服务器不能精确获取文件的最后修改时间
使用 ETag 字段实现的协商缓存的过程:
- 当浏览器第一次请求访问服务器资源时,服务器会在返回这个资源的同时,在 Response 头部加上 ETag 唯一标识,这个唯一标识的值是根据当前请求的资源生成的;
- 当浏览器再次请求访问服务器中的该资源时,首先会先检查强制缓存是否过期:
- 如果没有过期,则直接使用本地缓存;
- 如果缓存过期了,会在 Request 头部加上 If-None-Match 字段,该字段的值就是 ETag 唯一标识;
- 服务器再次收到请求后,会根据请求中的 If-None-Match 值与当前请求的资源生成的唯一标识进行比较:
- 如果值相等,则返回 304 Not Modified,不会返回资源;
- 如果不相等,则返回 200 状态码和返回资源,并在 Response 头部加上新的 ETag 唯一标识;
- 如果浏览器收到 304 的请求响应状态码,则会从本地缓存中加载资源,否则更新资源