一.初识HTTP协议
HTTP(HyperText Transfer Protocol,超文本传输协议)是用于在客户端(如浏览器)和服务器之间传输超媒体文档(如HTML)的应用层协议。
HTTP协议发展至今发布了多个版本,其中1.0,1.1,2.0是基于传输层TCP协议实现的,3.0是基于UDP实现的
版本 | 关键特性 |
---|---|
HTTP/1.0 | 基本请求-响应模型,短连接(每次请求新建TCP连接) |
HTTP/1.1 | 持久连接(默认复用TCP连接)、管线化、分块传输、缓存优化(如ETag ) |
HTTP/2 | 二进制分帧、多路复用、头部压缩、服务器推送(Server Push) |
HTTP/3 | 基于QUIC协议(UDP实现,解决TCP队头阻塞)、更快的连接建立和传输 |
目前广泛使用的是1.1和2.0版本,本文最主介绍1.1版本
我们平时打开一个网站就是通过HTTP/HTTPS协议(这个后面介绍)来传输数据的
二.理解 HTTP 协议的工作过程
当我们在浏览器输入一个网址(URL),浏览器就会根据网址向对应的服务器发起HTTP请求,服务器接收请求后就会返回HTTP响应
但实际上访问一个网站可能涉及不止一次的HTTP请求和响应,总之HTTP协议的特点是:发送一个请求,返回一次响应
三.HTTP协议格式
3.1 HTTP请求
HTTP请求包含首行,请求头,空行,请求正文四个部分
这个响应只有首行和请求头
3.1.1URL和方法
3.1.1.1 URL(唯一资源定位符)
(1)服务器地址:定位服务器(主机)
(2)服务器端口号:定位到具体的应用程序
(3)文件路径:定位访问的资源。该路径可以对应真实的硬盘文件,也可以是虚拟的文件
(4)query string:针对请求的内容(正文)进行补充说明
query string 中的键值对是程序员自定义的
(5)片段标识符:以#开始,不会发送到服务器,用于定位当前页面的某个部分
3.1.1.2URL编码(URL Encoding)
URL编码是一种将特殊字符转换为安全传输格式的机制。它确保URL中仅包含合法字符,避免歧义或解析错误
例如:
URL编码规则
保留字符必须编码
以下字符在URL中有特殊用途,若要在非结构位置使用,必须编码:! * ' ( ) ; : @ & = + $ , / ? # [ ] %
- 示例:
&
→%26
,空格
→%20
,?
→%3F
。
- 示例:
非保留字符无需编码
字母(A-Z, a-z)、数字(0-9)以及- _ . ~
可直接使用。非ASCII字符编码
非英文字符(如中文)先按UTF-8转换为字节,再对每个字节编码:- 示例:
北
→ UTF-8字节为E5 8C 97
→%E5%8C%97
。
- 示例:
空格的特殊处理
空格可编码为%20
或+
(仅查询参数中允许+
,路径中必须用%20
)
3.1.1.3方法
HTTP协议的请求和响应数据绝大部分是使用GET和POST方法,所以主要介绍GET和POST方法
GET:从服务器获取资源(如请求网页,查询数据)
POST:向服务器提交数据(如提交表单,上传文件)
以上GET和POST方法的作用是HTTP标准文档的建议,但HTTP协议是应用层协议,程序员有很大操作空间。如果程序员非要让POST方法获取服务器资源,让GET方法提交数据,实际上是可以这么做的。所以GET和POST方法没有硬性的区分规则,主要看程序员如何使用。不过从使用习惯上来说,GET和POST方法也有区别
(1)GET习惯于将数据放在query string;POST习惯将数据放在body(正文)里
(2)GET方法一般没有body,因为数据放在query string里了;
POST一般有body,因为body里面存放着数据(除非这次请求没数据)
(3)GET方法是幂等的,POST方法是非幂等的
每次输入的内容一致,输出的结果也一致,就叫幂等
每次输入的内容一致,输出的结果不一致,就叫非幂等
但是搜购的广告请求使用的GET就不是幂等的,只能说幂等这件事不绝对
(4)因为GET是幂等的,所以支持缓存;而POST不支持
以上区别只是从使用习惯上来划分的,这些区别都不绝对
(5)GET方法的请求可以被浏览器收藏夹收藏,而POST方法的请求不行。这和浏览器的实现有关,原因我可以简略说一下:
浏览器收藏夹收藏的是URL,当用户通过收藏夹来访问的时候本质上是拿到收藏夹中的URL来进行访问。
根据GET方法的使用习惯,GET方法的数据是放在query string里的,所以访问URL可以正常访问到上次的页面
而POST方法的数据一般是存放在body中的,收藏夹不会收藏body,只会收藏URL,这就导致收藏夹收藏的信息不全,那通过收藏夹来访问,可能无法访问到上次的页面
对于GET和POST方法的区别,以下的说法不太严谨
(1)GET方法比POST方法更安全。当登录账号的时候,使用GET方法密码会显示在query string上,能直接被看到;而POST方法会把密码保存在body中,不会被直接看到。所以POST比GET安全
我的看法:放在body中也不安全,一个抓包照样能看到,如果使用HTTPS协议来加密,即便把密码显示在query string中,也是安全的
(2)GET方法传输的数据量上限比POST低
我的看法:这种说法有一定道理。因为在多年前,IE浏览器限制了URL的长度,GET方法是把数据放在query string中的,这可能会限制GET方法的传输上限。但是HTTP标准文档上面明确说了,对于URL长度不做限制。而且在今天,比较长的URL也是挺常见的。所以这个说法在今天不太适用了
(3)GET方法只能携带文本数据,POST方法可以携带二进制数据
我的看法:不全对。
因为GET方法通过query string来携带数据,query string只能携带文本数据。但是可以将二进制数据URL Encoding转码,到达服务器后再URL Decoding还原成二进制数据
虽然POST方法的body可以直接携带二进制数据,但很多时候也使用了URL Encoding来转码
3.1.2请求头
请求头的格式是键值对,键值对的种类很多,这里介绍几个常见的
(1)Host:表示目的服务器的地址和端口号
这里的Host没有显示端口号,但其实端口号被设置了一个默认值,和协议的类型有关(HTTP是80,HTTPS是443)。绝大多数情况下,Host中的地址和URL中的地址是一样的。
根据RFC 7230,当请求行中的URL为绝对URI(例如GET http://example.com/index.html HTTP/1.1
)时,客户端必须在Host头中设置与URI中完全一致的域名(Host: example.com
),且不允许不一致。
如果请求行中使用相对路径(例如GET /index.html HTTP/1.1
),Host头必须明确指定目标域名(如Host: example.com
),此时两者通过不同方式指向同一域名,逻辑上一致
(2)Content-Length:表示body的长度
用于处理粘包问题。因为HTTP(1.0/1.1/2.0)都是基于TCP协议实现的,TCP传输的单位是字节,当发送方发送多个HTTP请求时,接收方的接收缓冲区就会积累多个数据包,这时候就需要明确包与包之间的边界
(3)Content-Type:表示body中数据的格式
body的格式很多,甚至可以由程序员自定义,这里介绍三个常见的:
1.application/x-www-form-urlencoded:这是form表单提交的数据格式,此时body的格式就类似于query string
2.application/json:此时body数据为json格式
3.multipart/from-data:通常用于HTML提交图片或者文件
(4)User-Agent表示浏览器或者操作系统的属性,简称UA
UA 在早年是一个非常有用的字段,网站的开发者可以根据它来检测页面的兼容性。例如 :某程序员发开出的网页使用了某些新特性,通过UA检测用户的设备类型。如果是老设备,那么返回的页面就不显示新特性,保证正常显示;如果是新设备,那就显示新特性,以提高用户体验
(5)Referer:表示这个页面从哪个页面跳转过来的,这个字段很有用
当在浏览器输入"蛋糕"时,会弹出很多广告,这些广告是蛋糕厂商投射到某个浏览器的。我们点击搜狗的蛋糕广告,搜狗就能赚广告费;点击百度的蛋糕广告,百度就能赚广告费。到时候收取广告费的时候就需要通过Referer字段来判断搜狗的点击量有多少,百度的点击量有多少
注:如果直接在浏览器中输入URL, 或者直接通过收藏夹访问页面时是没有Referer的
(6)Cookie:是一个浏览器本地持久化保存数据的机制(数据写入硬盘)
浏览器上运行的网页能否通过浏览器提供的API来读写硬盘?
理论上是可以的,但是浏览器禁止这么做(因为安全性)。打开一个网站只需要鼠标点一下,如果打开的是一个黑客开发的恶意网站,此时黑客通过网页来读写你的硬盘(删除重要的文件/资料),那就麻烦了,所以浏览器禁止网页直接读写硬盘。
但是某些情况下确实需要再浏览器本地长期保存部分信息(比如当前登录的用户的身份信息),所以就引入了Cookie。Cookie能够有限度的存储一些数据,但不能直接访问文件系统
Cookie的结构:Cookie通过键值对来存储字符串。键值对之间使用分号分割,键和值之间使用等号分割
Cookie的发送和设置:
3.2 HTTP响应
HTTP请求包含首行,响应头,空行,响应正文四个部分
3.2.1状态码
作用:响应状态码用于表示客户端HTTP请求的结果,由三位数字组成
状态码大全
这里介绍几种常见的状态码:
(1) 200 OK:请求成功
(2) 404 Not Found:请求的资源没找到(URL中的路径不存在)
(3) 403 Forbidden:请求的资源没有权限访问/权限不够
(4) 405 Method Not Allowed:请求的方法对资源不被允许(比如服务器只允许GET方法,你发的请求使用的是POST方法)
(5) 500 Internal Server Error:服务器内部错误(服务器挂了)
(6) 504 Gateway Timeout:访问服务器超时(可能是服务器挂了/负载较大导致处理单条请求的时间过长,也可能是网挂了)
(7) 302 Move temporarily(临时重定向):临时重定向表示请求的资源暂时位于不同的URI下。由于是临时的,客户端在之后的请求中仍应继续使用原有的URI。例如,网站在进行维护时,可以使用302重定向到维护页面
(8) 301 Moved Permanently(永久重定向):永久重定向表示请求的资源已经被永久地移动到新的URI。搜索引擎会更新其索引,将旧URL替换为新URL。适用于那些你知道资源已经永久移动到新的位置
3.2.2响应头
请求头和响应头的数据格式都差不多,但是响应头的Content-Type和请求头有所不同,这里就简单介绍一下
text/html:表示数据格式是 HTML
text/css:表示数据格式是 CSS
application/javascript:表示数据各式是 JavaScript
application/json:表示数据格式是 JSON
四.小结
HTTP协议就先暂时介绍到这里,下篇博文来讲讲HTTPS