HTTP有哪些方法?
- HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法
- HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT
这些方法的具体作用是什么?
- GET: 通常用于请求服务器发送某些资源
- HEAD: 请求资源的头部信息, 并且这些头部与 HTTP GET 方法请求时返回的一致. 该请求方法的一个使用场景是在下载一个大文件前先获取其大小再决定是否要下载, 以此可以节约带宽资源
- OPTIONS: 用于获取目的资源所支持的通信选项
- POST: 发送数据给服务器
- PUT: 用于新增资源或者使用请求中的有效负载替换目标资源的表现形式
- DELETE: 用于删除指定的资源
- PATCH: 用于对资源进行部分修改
- CONNECT: HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器
- TRACE: 回显服务器收到的请求,主要用于测试或诊断
GET和POST有什么区别?
- 数据传输方式不同:GET请求通过URL传输数据,而POST的数据通过请求体传输。
- 安全性不同:POST的数据因为在请求主体内,所以有一定的安全性保证,而GET的数据在URL中,通过历史记录,缓存很容易查到数据信息。
- 数据类型不同:GET只允许 ASCII 字符,而POST无限制
- GET无害: 刷新、后退等浏览器操作GET请求是无害的,POST可能重复提交表单
- 特性不同:GET是安全(这里的安全是指只读特性,就是使用这个方法不会引起服务器状态变化)且幂等(幂等的概念是指同一个请求方法执行多次和仅执行一次的效果完全相同),而POST是非安全非幂等
PUT和POST都是给服务器发送新增资源,有什么区别?
PUT 和POST方法的区别是,PUT方法是幂等的:连续调用一次或者多次的效果相同(无副作用),而POST方法是非幂等的。
除此之外还有一个区别,通常情况下,PUT的URI指向是具体单一资源,而POST可以指向资源集合。
举个例子,我们在开发一个博客系统,当我们要创建一篇文章的时候往往用POST https://www.jianshu.com/articles
,这个请求的语义是,在articles的资源集合下创建一篇新的文章,如果我们多次提交这个请求会创建多个文章,这是非幂等的。
而PUT https://www.jianshu.com/articles/820357430
的语义是更新对应文章下的资源(比如修改作者名称等),这个URI指向的就是单一资源,而且是幂等的,比如你把『刘德华』修改成『蔡徐坤』,提交多少次都是修改成『蔡徐坤』
ps: 『POST表示创建资源,PUT表示更新资源』这种说法是错误的,两个都能创建资源,根本区别就在于幂等性
PUT和PATCH都是给服务器发送修改资源,有什么区别?
PUT和PATCH都是更新资源,而PATCH用来对已知资源进行局部更新。
比如我们有一篇文章的地址https://www.jianshu.com/articles/820357430
,这篇文章的可以表示为:
article = {
author: 'dxy',
creationDate: '2019-6-12',
content: '我写文章像蔡徐坤',
id: 820357430
}
复制代码
当我们要修改文章的作者时,我们可以直接发送PUT https://www.jianshu.com/articles/820357430
,这个时候的数据应该是:
{
author:'蔡徐坤',
creationDate: '2019-6-12',
content: '我写文章像蔡徐坤',
id: 820357430
}
复制代码
这种直接覆盖资源的修改方式应该用put,但是你觉得每次都带有这么多无用的信息,那么可以发送PATCH https://www.jianshu.com/articles/820357430
,这个时候只需要:
{
author:'蔡徐坤',
}
http的请求报文是什么样的?
请求报文有4部分组成:
- 请求行
- 请求头部
- 空行
- 请求体
- 请求行包括:请求方法字段、URL字段、HTTP协议版本字段。它们用空格分隔。例如,GET /index.html HTTP/1.1。
- 请求头部:请求头部由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔
- User-Agent:产生请求的浏览器类型。
- Accept:客户端可识别的内容类型列表。
- Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。
- 请求体: post put等请求携带的数据
http的响应报文是什么样的?
请求报文有4部分组成:
- 响应行
- 响应头
- 空行
- 响应体
- 响应行: 由协议版本,状态码和状态码的原因短语组成,例如
HTTP/1.1 200 OK
。 - 响应头:响应部首组成
- 响应体:服务器响应的数据
聊一聊HTTP的部首有哪些?
内容很多,重点看标『✨』内容
通用首部字段(General Header Fields):请求报文和响应报文两方都会使用的首部
- Cache-Control 控制缓存 ✨
- Connection 连接管理、逐条首部 ✨
- Upgrade 升级为其他协议
- via 代理服务器的相关信息
- Wraning 错误和警告通知
- Transfor-Encoding 报文主体的传输编码格式 ✨
- Trailer 报文末端的首部一览
- Pragma 报文指令
- Date 创建报文的日期
请求首部字段(Reauest Header Fields):客户端向服务器发送请求的报文时使用的首部
- Accept 客户端或者代理能够处理的媒体类型 ✨
- Accept-Encoding 优先可处理的编码格式
- Accept-Language 优先可处理的自然语言
- Accept-Charset 优先可以处理的字符集
- If-Match 比较实体标记(ETage) ✨
- If-None-Match 比较实体标记(ETage)与 If-Match相反 ✨
- If-Modified-Since 比较资源更新时间(Last-Modified)✨
- If-Unmodified-Since比较资源更新时间(Last-Modified),与 If-Modified-Since相反 ✨
- If-Rnages 资源未更新时发送实体byte的范围请求
- Range 实体的字节范围请求 ✨
- Authorization web的认证信息 ✨
- Proxy-Authorization 代理服务器要求web认证信息
- Host 请求资源所在服务器 ✨
- From 用户的邮箱地址
- User-Agent 客户端程序信息 ✨
- Max-Forwrads 最大的逐跳次数
- TE 传输编码的优先级
- Referer 请求原始放的url
- Expect 期待服务器的特定行为
响应首部字段(Response Header Fields):从服务器向客户端响应时使用的字段
- Accept-Ranges 能接受的字节范围
- Age 推算资源创建经过时间
- Location 令客户端重定向的URI ✨
- vary 代理服务器的缓存信息
- ETag 能够表示资源唯一资源的字符串 ✨
- WWW-Authenticate 服务器要求客户端的验证信息
- Proxy-Authenticate 代理服务器要求客户端的验证信息
- Server 服务器的信息 ✨
- Retry-After 和状态码503 一起使用的首部字段,表示下次请求服务器的时间
实体首部字段(Entiy Header Fields):针对请求报文和响应报文的实体部分使用首部
- Allow 资源可支持http请求的方法 ✨
- Content-Language 实体的资源语言
- Content-Encoding 实体的编码格式
- Content-Length 实体的大小(字节)
- Content-Type 实体媒体类型
- Content-MD5 实体报文的摘要
- Content-Location 代替资源的yri
- Content-Rnages 实体主体的位置返回
- Last-Modified 资源最后的修改资源 ✨
- Expires 实体主体的过期资源 ✨
聊一聊HTTP的状态码有哪些?
2XX 成功
- 200 OK,表示从客户端发来的请求在服务器端被正确处理 ✨
- 201 Created 请求已经被实现,而且有一个新的资源已经依据请求的需要而建立
- 202 Accepted 请求已接受,但是还没执行,不保证完成请求
- 204 No content,表示请求成功,但响应报文不含实体的主体部分
- 206 Partial Content,进行范围请求 ✨
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,表示在服务器上没有找到请求的资源 ✨
- 408 Request timeout, 客户端请求超时
- 409 Confict, 请求的资源可能引起冲突
5XX 服务器错误
- 500 internal sever error,表示服务器端在执行请求时发生了错误 ✨
- 501 Not Implemented 请求超出服务器能力范围,例如服务器不支持当前请求所需要的某个功能,或者请求是服务器不支持的某个方法
- 503 service unavailable,表明服务器暂时处于超负载或正在停机维护,无法处理请求
- 505 http version not supported 服务器不支持,或者拒绝支持在请求中使用的 HTTP 版本
同样是重定向307,303,302的区别?
302是http1.0的协议状态码,在http1.1版本的时候为了细化302状态码又出来了两个303和307。
303明确表示客户端应当采用get方法获取资源,他会把POST请求变为GET请求进行重定向。 307会遵照浏览器标准,不会从post变为get。
HTTP的传输原理
HTTP想要发送一条报文的时候,需要经过以下两个步骤:
- TCP三次握手建立起连接管道,HTTP报文会以流的形式通过该管道按顺序传输;
- TCP会将这些数据分别切割成数据块,并且封装在IP分组中,通过IP去传输;
使用TCP作为传输层:
- 传输可靠
- 有序
一个典型的HTTP请求过程如下图所示:
HTTP协议首部
标准的HTTP协议共有GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE
。
GET
- 无副作用
- 可被缓存
- 请求参数附带在query中
POST
- 有副作用
- 不可被缓存
- 请求参数在body中
HEAD
- 只会传输HTTP首部
OPTIONS
- 嗅探请求,用于判断服务器支持的方法
从字面上理解GET
、POST
,一个是获取,一个是发送,所以一般情况下我们在想读取一个服务器资源的时候我们会用GET
请求,当需要修改服务器数据的时候,用POST
提交操作。
我们来看一个典型的GET
协议,
我们来看里面几个重要字段:
Connection
在http1.0中一个http在传输完成之后就会断开tcp链接,受到tcp慢启动的特点,每次建立http都会消耗大量的时间,所以各个浏览器定义了一个不标准的协议叫keep-alive,当然在http1.1中已经默认开启keep-alive,标识该请求在结束之后不会被断开,也就是下一个请求可以不用进行DNS查询,TCP三次握手,直接利用上一个通道进行传输。
上面两张图是我抓的天猫的两个接口请求,可以看到,在第二个请求比第一个请求中少了DNS Lookup、Initial connection与SSL的过程,提升了差不多100ms左右的时间,性能提升非常明显。
值得注意的是,因为keep-alive会复用一个tcp通道进行数据传输,怎样知道一个数据传输完成了呢,这就必须用到Content-length,通过该属性客户端可以知道一个资源在什么时候结束。
Cache-Control
上面的keep-alive对请求中的链路做了优化,在浏览器还有一个非常重要的字段,Cache-control,该消息头被用于在http 请求和响应中通过指定指令来实现缓存机制。
在response中服务器可以通过max-age=x指定该资源的过期时间,标识在x秒之后同样的请求直接走客户端缓存逻辑。
当然客户端可以通过加入cache-control:no-cache
去强制强求服务器资源。
上图是浏览器的一些操作对缓存的影响,实际原理就是强制修改request头去影响缓存,具体每个浏览器实现不一样,这里给出的是chrome浏览器的操作影响。
协商缓存
当客户端的cache-control过期了怎么办,是否必须向服务器请求资源呢?
HTTP的设计者们当然没有那么傻,这个时候就要用到协商缓存了。
Last-Modified
在服务端第一次返回资源的时候,如果带上一个last-modified参数,也就是告知客户端,这个资源在这个时间我更新过了,下次你记得给我带过来,我验证一下在这个时间之后是否有被更新过,如果没有,那就返回304,你客户端直接取本地缓存即可,如果有更新,那会返回200,并且附上最新的last-modified值。
Etag
用Last-Modified有个问题,比如说我在一秒钟更新了多次资源,那这个资源只要第一次被缓存了,1秒钟更新再多次请求的时候还是会返回304。另外有些文件会被定时touch,这个时候文件内容可能没有变化,但是也会返回200。针对以上问题,出现了Etag,在第一次Response的时候,服务端会返回一个Etag,一般Etag是根据文件散列计算出来的,所以只要文件内容没变,该Etag也唯一,这样客户端下次请求的时候带上上次服务器返回的Etag给服务器校验,如果两次一样,服务器就会返回304。
encoding
客户端通过Accept-Encoding字段告知服务器支持哪些压缩算法,服务器收到后会选出一个最优算法对数据进行压缩,然后通过Content-Encoding返回给客户端,告知客户端去调用相关的算法进行解压。
cookie
用户状态追踪器,一般在浏览一个网站的时候,该网站都会通过set-cookie植入一个sessionId在我们的cookie中来标识用户身份。因为cookie会自动附带在同域或者子域的请求上,通过cookie,广告联盟可以在任何站点嵌入一个iframe页,植入广告,这就是为什么我们在上网的时候经常看到在某度、某东搜索的信息,当然我们可以打开浏览器的隐私模式来避免信息被盗取与滥用。
HTTPS
为什么要进行升级HTTPS?
在互联网出现之前,如果远在天边的两个人想要联系只能通过写信。让我们看一下在中国的A要寄一封信给美国的B要经过哪些步骤。
A->中国邮局->邮递员A.....->邮递员Z->美国邮局->B
可以看到中间经过了很多链路,在每个环节都可以被任意偷窥甚至篡改,那么信件到了B很可能就不是A的信了。
同样在HTTP传输的过程中,我们可以把运营商类比为邮局,路由类比为邮递员,因为HTTP在网络上是明文传输,可以被任何偷窥修改,典型的运营商劫持就是通过这种手段去操作的。
为了偷窥的问题,A跟B事先约定了一个办法,A给了B一个密码本,每个单词字母都用对应的密码表示,每次A按照密码本写信,B收到后再通过密码本解密,这样在传输的过程中只要保证密码本不落入他人手里,其他人就没法看得懂这封信了,这就是对称加密。这样看起来不错,但是有个非常严重的问题,A的密码本怎么给到B,如果还是通过邮寄的方式,这样密码本被copy了,后面的所有的加密也是白瞎。
为了解决这种问题,B放出了一个公开的密码本,说所有跟我通信的人都按照这个密码本的方式去加密,但是因为不是一一映射的关系,所以A加完密后连A自己都无法解密,但是B自己有密钥,通过该密钥可以解密信件。
这样看起来解决了被偷窥的问题了,但是有一天B收到了一峰信件,发现用自己的密钥解密后看不懂信件的内容,跟A沟通后,发现信件被篡改了。
为了解决这个问题,A每次寄信的时候都会按上自己的指纹,B收到信后首先确定这个指纹是不是A,然后再决定是否去解密,这样问题差不多就解决了。
HTTPS的原理
HTTPS缺点
- 慢,初次建立SSL连接,算法复杂,消耗资源
- 贵,需要每年交一定的费用给证书颁发机构
HTTP2相对于HTTP1.x有什么优势和特点?
二进制分帧
帧:HTTP/2 数据通信的最小单位消息:指 HTTP/2 中逻辑上的 HTTP 消息。例如请求和响应等,消息由一个或多个帧组成。
流:存在于连接中的一个虚拟通道。流可以承载双向消息,每个流都有一个唯一的整数ID
HTTP/2 采用二进制格式传输数据,而非 HTTP 1.x 的文本格式,二进制协议解析起来更高效。
服务器推送
服务端可以在发送页面HTML时主动推送其它资源,而不用等到浏览器解析到相应位置,发起请求再响应。例如服务端可以主动把JS和CSS文件推送给客户端,而不需要客户端解析HTML时再发送这些请求。
服务端可以主动推送,客户端也有权利选择是否接收。如果服务端推送的资源已经被浏览器缓存过,浏览器可以通过发送RST_STREAM帧来拒收。主动推送也遵守同源策略,服务器不会随便推送第三方资源给客户端。
头部压缩
HTTP/1.x会在请求和响应中中重复地携带不常改变的、冗长的头部数据,给网络带来额外的负担。
- HTTP/2在客户端和服务器端使用“首部表”来跟踪和存储之前发送的键-值对,对于相同的数据,不再通过每次请求和响应发送
- 首部表在HTTP/2的连接存续期内始终存在,由客户端和服务器共同渐进地更新;
- 每个新的首部键-值对要么被追加到当前表的末尾,要么替换表中之前的值。
你可以理解为只发送差异数据,而不是全部发送,从而减少头部的信息量
多路复用
HTTP 1.x 中,如果想并发多个请求,必须使用多个 TCP 链接,且浏览器为了控制资源,还会对单个域名有 6-8个的TCP链接请求限制。
HTTP2中:
- 同域名下所有通信都在单个连接上完成。
- 单个连接可以承载任意数量的双向数据流。
- 数据流以消息的形式发送,而消息又由一个或多个帧组成,多个帧之间可以乱序发送,因为根据帧首部的流标识可以重新组装