前言
立志做前端人员的小summer,对HTTP总是浅尝辄止,一些细节东西了解的很模糊,那么就来整理一下吧😊,借助,三元大神的(建议精读)HTTP灵魂之问,巩固你的 HTTP 知识体系 - 掘金 (juejin.cn)
正文
HTTP报文结构是怎样的
什么是HTTP报文
HTTP报文是在应用程序之间发送的数据块,这些数据块将通过以一些文本形式的元信息开头,用于HTTP协议交互
- 客户端的HTTP报文叫做请求报文
- 服务器端的HTTP报文叫做响应报文
报文一般都是由:header+body
起始行+头部+空行+实体
请求报文
起始行
在起始行中,没两个部分用空格隔开
方法+ 路径+
http版本一般用于描述,用户希望如何请求资源(采用什么措施,什么版本)
GET /home HTTP/1.1
请求头
- 里面包含了若干属性,格式:
属性:值 - 并且他们的属性,是不区分大小写的
- 属性里面不可以出现,空格和下划线
请求头大致分为四个类型
- 通用首部字段
- 请求首部字段
- 响应首部字段
- 实体首部字段
空行
用于区分
头部和实体
空行后面的全部都是实体
假如你在头部里故意加一个空行,
那么,空行后面的所有内容都会被认为是实体
实体(请求体)
就是具体的数据
HTTP可以承载很多类型的数据:HTML,图片,音频等
响应报文
起始行
响应报文的起始行和请求报文的起始行还是有区别的
http版本+状态码+原因
http1.1 200 ok
那么我们先来聊一聊状态码
状态码
RFC规定了状态码一共为3位数,一共有5类
| 状态码 | 原因 |
|---|---|
1xx | 当前协议处于中间状态 |
2xx | 成功状态 |
3xx | 重定向状态,资源发生改变,需要重新请求 |
4xx | 请求报文有误 |
5xx | 服务端发生错误 |
这边详细说说几个特殊的
2xx:
-
200:OK,请求成功的状态码,这个我们通常用于请求会数据,会在响应体里面放数据 -
204:no content,也是表示请求成功,但是他是没有实体的,也就是,没有数据 -
206:partial Content,用于HTTP分块下载和断点继承一般用于解决:
- 大文件的下载问题
CDN和原始HTTP服务器问题
3xx:
-
301:表示永远重定向大概可以理解为,你这个网站的
url改变了,并且原来的站点,不会再维护,而是使用一个新的站点,那么我们就可以永久重定向 -
302:临时重定向
浏览器对于301,会进行缓存优化,当你第二次访问的时候,就会自动访问重定向的那个地址,但是,因为302是临时的,那么他是不会进行缓存的
响应头
和请求头一样,都是键值对的形式
空行
用于区分,响应头和响应实体
响应实体
影响的实体,就是服务器返回给浏览器的数据,它返回的类型一般和content-Type来决定
这个是由MIME类型决定的,简单说说,就是它是一种定义返回类型的东西,你这个值设置为什么类型,那么我响应体里面,相应的数据就只可以是这个类型,具体可以参考:MIME 类型 | 菜鸟教程 (runoob.com)
总结
HTTP报文结构,就是类似于Header+body这种
- 起始行
- 头部
- 请求头
- 响应头
- 空行
- 实体
- 响应体
- 请求体
HTTP的请求方法
HTTP/0.9:只有一个GET命令
HTTP/1.0:
GET:用于获取资源HEAD:用于获取资源的元信息POST:提交数据
HTTP/1.1:
PUT:修改数据patch:打补丁式修改数据OPTIONS:一般用于跨域请求DELETE:删除数据
get和Post有什么区别?
-
语义上其实就有很大区别
get:是获取资源Post:是上传资源,一种Update/Insert的感觉
-
缓存角度
Get:是会被浏览器主动缓存的Post不会被缓存
首先我们先来了解一下
HTTP缓存就是不更新服务端数据的请求
因为我们的
Get,就是直接获取数据,不会对数据进行修改,自然就不需要更新服务端数据请求了,那么就可以使用HTTP缓存但是因为
POST,其实是将数据发送到服务器端去存储,那么肯定是会对服务器数据产生变化的,那么就不会去使用缓存 -
编码角度
Get:只进行URL编码。所以只接受ASCII字符POST:没有限制
我的理解是:我们会将ASCII码进行转码,变为
URL,然后进行请求,假如这时候我们使用的是非ASCII码,那么转码的时候,就没法转为对应的URL,那么请求就出错了 -
参数角度
-
GET:将参数放在了URL里面,不安全其实就是那个
Query -
POST:会将数据放在请求体里面,比较安全浏览器像服务器发送,那么就是进行请求,数据放在响应体里面
-
-
幂等性角度
Get:无论你请求多少次,我的数据都不会发生变化Post:它是一种相当于upDate的感觉,会对服务器数据库造成修改的
-
TCP角度GET:只会发送一次,它会将请求报文,一次性发出去Post:会分两次进行发送,第一次发送请求头,返回100,那么我才发送请求体,然后200,返回数据,但是火狐,只会发送一次
但是目前来说
- 在网络状态比较好的时候,其实发送一次数据包和发送两次数据包没什么差别
- 假如在网络差的时候,两次包的
TCP在验证包完整性上,有着非常大的优势
但是在这篇文章中,作者介绍到,其实GET和POST并没有本质上的区别:99%的人都理解错了HTTP中GET与POST的区别 (qq.com)
书中介绍:
GET和POST本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同
- 无论是
GET还是POST,其实他们都是属于TCP链接,所以其实GET和POST做的事情差不多 - 假如我们将
GET上添加request body,给POST添加url参数,其实是可以的 - 他说,我们可以将
TCP比作汽车,我们将HTTP看成是交通规则,HTTP定义了好几种服务,GET,POST等 Get:他要求我们将传送的数据放在车顶上Post:要求将传送的数据放在车厢里面- 但是我们也完全可以在
GET的时候,将数据悄悄的放在车厢里面送过去,Post的时候,完全可以在车顶放一些东西 - 但是在那个世界里,这么干,是不被人认可的,但是是可行的
- HTTP,他只是一个行为准则,但是
TCP才是实现的基本
总结
其实可以将HTTP,理解为一种行为准则,她告诉你,你可以进行GET,POST,PUT,Patch操作,这是一种规范的感觉
理解URI
举个例子:
https://www.baidu.com/s?wd=HTTP&rsv_spt=1
scheme | 协议,比如HTTP,HTTPS,FTP啥的,后面一定需要:// |
|---|---|
user:passwd@ | 登录主机用的信息,一般不显示出来 |
host:port | 主机名和端口号 |
path | 表示请求的路径,标记资源所在位置 |
query | 查询,key = value这种形式,用&来隔开 |
fragement | 表示定位锚点 |
在这边:
scheme是HTTPShost:www.baidu.comport:对于http,一般都是80端口,对于https,一般都是443端口path:/squery:wd=HTTP&rsv_spt=1
URI编码
URI里面只可以使用ASCII,这也从另一个方面说明了get请求,只接受ASCII,
因此URI引入了编码机制,它会将非ASCII码和界定符转换为十六进制字节符,在前面加上%
会将空格转变为%20
那么什么是我们平时理解的URL呢?
可以很形象的看出,URI比URL多了一个定位锚点