文章目录
- 什么是Http协议?
- HTTP报文格式
- HTTP 请求格式
- HTTP响应格式
- 什么是 URL
- 请求和响应中的“方法”
- GET 和 POST 的区别
- 认识“Header”
- 状态码详解
什么是Http协议?
Http协议是“超文本传输协议”(不仅可以传输文本,也可以传输图片,音频,视频等),属于应用层协议,并且它是一种无状态协议,这就表示,服务器不会保存任何关于客户端状态信息,也就是说服务器处理的每个请求都是独立的。其次它默认使用的是80端口进行通信,而且,HTTP协议定义了客户端和服务器之间请求和响应的格式,支持多种请求方法,和响应状态码。
HTTP报文格式
HTTP的工作原理:
是一种“一问一答”结构模型的协议。客户端(通常是Web浏览器)向服务器发送一个HTTP请求,请求包含请求的方法、URL、协议版本、请求头部和请求数据。服务器接收到请求后,会以一个状态行作为响应,响应的内容包括协议的版本、成功或者错误代码、服务器信息、响应头部和响应数据。
如何查看 HTTP 请求和响应的格式
可以通过 Fiddler 工具 对发出的请求和响应进行抓包,查看请求和响应的协议格式,这种抓包工具也是程序员分析调试程序的重要手段,下面先讲解一下如何使用 Fiddler 工具:
Fiddler 工具下载链接:Fiddler Classic | Original Web Capturing Tool for Windows (telerik.com)
下面介绍 Fiddler 工具的界面:
1️⃣、打开 Fiddler 工具,可以看到以下页面
❗**注意:**打开 Fiddler 后,还需要手动开启 HTTPS 功能,并且安装证书,这样才能够抓到HTTPS的协议包,否则只能抓HTTP的。开启步骤如下图:
勾选上之后,会出来一个弹框,是一个全英文的,意思是问你是否确定安装证书,选择确定完成了,这里因为我的已经安装了,所以不会出来这个弹框。
2️⃣、抓包案例
以打开爱奇艺网站为例,查看fiddler抓到的请求
可以看到在下图的 fiddler上,有很多域名为 /iqiyi 的包,这些都是访问爱奇艺网站时发起的请求,一个网页在打开时,不只是和服务器进行一次交互操作,而是多次交互,这些大部分请求都不用管,主要是看蓝色字体的请求,这里的不同颜色的请求都是代表了不同的含义:
蓝色的:得到的响应是 html(网页)
黑色的:获取到一些普通的数据,具体数据是啥,不知道,要看人家程序员是咋写的
灰色的:直接忽略
绿色的:
3️⃣、点击这个蓝色请求,查看请求的原始数据
可以看出,HTTP协议是一个文本式的协议,协议里的内容都是字符串,和TCP、UDP、IP这些二进制格式的协议完全不同
4️⃣、查看响应
查看响应的步骤和查看请求的步骤一样,可以看到里面还包含了一些乱码,HTTP 响应也是文本的,直接查看,往往能看到二进制的数据(乱码的数据),通过 Raw 标签查看文本格式,通过 View in Notepad 标签在记事本打开。
通过解压缩就可以将 body(正文) 中的乱码翻译成文本
这时候再通过记事本打开,就不再是乱码了,同时也可以看到,响应数据是 html格式的,所以,浏览器上显示的网页就是html,浏览器向对应的服务器发起请求后,然后从服务器这边拿到html。
HTTP 请求格式
根据下图所抓到的包 (以爱奇艺为例) 来讲解请求包都分成了哪几部分!
Http 请求分为以下四部分:
1️⃣ 请求行
首行是由三个部分组成分别是:
- GET :HTTP请求方法
- URL : 唯一资源定位符,描述了一个资源在网络上的位置
- 版本号 : HTTP协议的版本(最主流的就是1.1版本)
2️⃣请求头(Header)
- 除第一行,剩下的数据中,直到遇见空行为止的数据,就是请求头,请求头是一个 键值对结构 的数据
- 每个键值对都占一行
- 键和值之间使用 : + 空格 隔开
请求头里面就包含的数据的长度,数据的格式,cookie等信息。
3️⃣.空行
请求头下面还有一个空行,表示请求头结束的标记
4️⃣.正文
也就是上述的空行下面的部分就是正文,对于请求来讲,一般不含有正文,对于响应,一般都含有正文,这只是习惯问题,并不是硬性要求!
HTTP响应格式
以爱奇艺的响应包为例进行讲解,如下图:
响应也是由四部分组成:
1️⃣.响应行
响应的首行也是由三部分组成,但是含义就和请求的首行有区别了
- 版本号(HTTP/1.1)
- 状态码(200) :描述了请求的结果,是成功了还是失败了还是其他
- 状态码解释(ok):对状态码使用文本又进一步的进行了解释
2️⃣响应头(Header)
- 除首行以外,下面的数据中,直到空行为止的这一部分的内容,就是响应头
- 响应头也都是键值对
- 键和值之间使用 : + 空格 隔开
3️⃣.空行
响应头的结束标记
4️⃣.正文
空行下面的部分就是正文,也就是对请求的内容进行响应的数据,这个数据可能是多种格式的,可能是文本,图片,视频,音频等
⭕为什么 响应头/请求头 和 正文之间都要使用空格隔开呢❓❓❓
因为 HTTP 协议并没有规定报头部分的键值对有多少个,空行就相当于是 “报头的结束标记”, 或者是 “报头和正文之间的分隔符”,因为HTTP 在传输层依赖 TCP 协议, TCP 是面向字节流的. 如果没有这个空行, 就会出现 “粘包问题”.
为什么请求行和请求头之间不使用空行隔开呢?
HTTP协议中,请求行和请求头之间不使用空行隔开,而是直接通过特定的字符(空格和回车换行符)来分隔各自的部分。这是因为HTTP协议的设计者为了简化协议的解析过程,特别是在早期的HTTP/0.9版本中,HTTP请求只包含请求行和消息体,而不包含请求头。随着HTTP协议的发展,HTTP/1.0引入了请求头,但为了保持向后兼容性,请求行和请求头仍然通过相同的字符集进行分隔。
什么是 URL
我们俗称的 “网址”其实就是 URL(Uniform Resource Locator 统一资源定位符 ),如下图:
通过下图来讲解 URL 每部分都代表了什么意思:
https:协议名,常见的有 http 和 https,也有其他类型,比如在访问mysql时,使用 jdbc:mysql
user:pass:登录信息,用于进行身份验证,但是现在的网站进行身份验证一般不会再通过URL进行了,所以一般会省略
cn.bing.com:服务器地址,此处的地址是一个域名(例如:www.baidu.com),域名会通过 DNS 系统解析成一个具体的 ip 地址,通过 cmd 输入 ping 命令可以看到某个域名的ip地址
/images/search:文件路径,用来描述数据在服务器的哪个位置qs=m&form=QBIR&SP=-1&lq=0:查询字符串(query string),是一个键值对结构,键值对之间使用 & 分割,键和值之间使用 = 分割,由程序猿自己定义,一般用于对请求的内容进行一个补充。
关于URL encode!
因为有些特殊符号已经被URL 使用,所以这些特殊的字符会被翻译成其他的一些字符,如下图所举得例子:
如果 query string 中的 value 值包含一些特殊的字符就需要进行 urlencode(进行转义),就比如通过百度搜索 C++,URl 中的 query string 就包含这样的键值对:https://cn.bing.com/search?q=c%2B%2B,这里面的 c%2B%2B,就是进行了转义,前面的 ‘%’ 表示这是一个转移字符 ,
, ‘+’ 转成16进制就是 2B, 同样也可以使用urlencode 编码工具对这些被转义的字符进行还原。
请求和响应中的“方法”
方法 | 说明 | Http版本 |
---|---|---|
GET | 获取资源 | 1.0、1.1 |
POST | 传输实体 | 1.0、1.1 |
PUT | 传输文件 | 1.0、1.1 |
HEAD | 获得报文首部 | 1.0、1.1 |
DELETE | 删除文件 | 1.0、1.1 |
TRACE | 追踪路径 | 1.1 |
CONNECT | 要求用隧道协议连接代理 | 1.1 |
LINK | 建立和资源之间的联系 | 1.1 |
UNLINE | 断开连接 | 1.0 |
OPTIONS | 询问支持方法 | 1.1 |
HTTP中最常用的方法就是 GET 和 POST。
GET 方法主要用来获取服务器上的资源,例如下图,通常使用 URL 发起的就是一个GET方法的请求,例如,通过URL 获取到对应的b站页面,通过抓包就可以观察到是一个 GET 方法的请求。
POST 方法主要用于传输数据给服务器,例如下面的登录页面:
以上的HTTP请求方法,最初的初心只是表示不同的语义,但在使用时并不是硬性要求的,因为,使用什么样的请求方法是由程序猿任意使用的,例如表格中的 POST 和 PUT 方法,其实两个是一样的,还有上述的 GET 和 POST ,也可以用POST方法来获取资源,用GET方法传输实体,这些都是可以的,只不过,在习惯用法上,都是用GET来获取服务器资源,POST传输资源。所以就诞生出了一道面试题:
GET 和 POST 的区别
GET 和 POST 的区别???
首先,GET 方法的含义是用于获取资源,在访问一个网页时,使用 URL 向服务器发送了一个GET方法请求,从而获取到网页资源,POST方法的含义是用于传输实体,比如在上传图片时,发送的就是一个 POST方法的请求,但是,传输实体使用GET方法的请求也是没有问题的,获取资源使用POST方法请求也是没有过问题的,所以,它们是没有本质区别的,只是在使用习惯上是有区别的;
- GET 请求经常把传递给服务器的数据放到URL中,POST 请求经常把传递的数据放到body中,但是这种情况也并不是绝对的,对于 GET 请求,也可以把数据放到body中,POST请求也可以放到URL中,但前提是,客户端和服务器都得按照一样的方式来处理代码,就像,你使用 POST 方法了,数据都放在 body中,那么在服务器这边,就要获取 body 中的数据进行处理,如果使用 GET 方法,那么在服务器这里,就要拿到 URL 中的数据进行处理。
- 语义上的差别
对于 GET 和 POST,网上会有一些比较错误的说法❌:
1、GET请求能传递的数据量有上限,POST请求传递的数据量没有上限
因为早期的浏览器,对URL的长度是有所限制的,限制了URL不能太长,但是呢,RFC标准文档中并没有对URL的长度进行规定,在当前的浏览器上,URL也是可以非常长的~~
2、GET请求传递数据不安全,POST请求传递数据更安全
这句话的依据是,在登录的场景下,如果使用GET 请求的话,用户名和密码都是可以在地址栏中看到的,而POST请求的话,账号和密码都是看不到的,这种现象,也就是哄一哄小白,对于程序员来讲,通过抓包就可以简单的获取到body中的账号和密码,而真正的安全措施是,要对账号和密码进行加密,而这个加密也就做到了相对来说比较安全一点,所以,此处的安全性是和POST无关的
3、GET 只能传输文本数据,POST 可以传输文本和二进制数据,这句话也是不准确的,因为:
也可以直接把二进制数据放到GET 的body中,body中是可以直接放二进制数据的,也可以将二进制数据通过base64转码放到query string中的
认识“Header”
Header 是由许多的键值对组成的,下面主要挑一些 Header 中比较重要的键值对进行解释;
host:host中的内容就是服务器主机的地址,例如下图, 但是,如果有代理的情况下,那么里面的host中内容可能和URL不一样;
Content-Length:body中数据的长度
Content-Type:body中数据的格式
User-Agent:表示浏览器/操作系统的属性,如下图:
Referer:描述了当前页面是从哪个页面跳转来的;
需要注意的是,从地址栏搜索的页面或从收藏夹中的点击某个页面时,是没有Referer的,如下图通过搜索栏访问百度页面:
只有从页面进行跳转时,才会有Referer,下面通过从百度页面跳转搜狗页面时,就可以看到 Referer 中百度的 URL
Cookie:Cookie 可以认为是浏览器在本地存储数据的一种机制
我们知道,进入浏览器的页面时,浏览器会向服务器发送一个获取页面请求,服务器就会给浏览器返回一个页面数据的响应,所以,浏览器中的核心数据都是来自服务器的,而有的时候,在运行的过程中,也就会将一些数据在浏览器中这边进行存储,并且在后续请求时,再将数据发送服务器,服务器再根据这些数据进行逻辑上的处理,就比如想登陆的时间,用户的身份信息等,像这种临时的输数据,存储在浏览器中是比较合适的,而为了考虑到安全性,就禁止网页直接访问电脑的文件系统,所以就引入了Cookie这种机制,这种机制也是按照硬盘文件的方式保存的,也是需要访问文件系统的,但是,浏览器把操作文件进行了封装,让网页只能访问规定的硬盘文件,无法随便访问硬盘中的其他文件,并且网页只能向Cookie中存储键值对,所以,Cookie是将服务器返回的一些数据或者页面生成的一些数据进行存储,方便后续再发送给服务器进行逻辑处理,而Cookie存储到浏览器所在的硬盘上,每个域名下都可以存自己的Cookie, 就比如,百度有自己的Cookie,搜狗有自己的Cookie,它们之间不会互相影响;
状态码详解
状态码表示这次请求所获得的响应是一个什么样的状态,表示这次请求是成功,还是失败,还是其他………
状态码的种类非常多,不需要全部都记住,只需要记住一些比较常用的即可,例如下图:
状态码主要分为五大类:
一些比较重要的状态码:
200:表示请求成功
202:表示请求已经收到,但还未响应
301(永久重定向):表示请求资源的URL已经永久更改,在响应中给出了新的URL,当浏览器收到这种响应时,后续的请求都会自动更改成新的地址;
302(临时重定向):表示请求资源的URL被暂时更改,后续还有可能会改成其他的
重定向的意思:相当于电话号码中的 “呼叫转移”,例如我原来的手机号码是 123456, 现在我换了新的手机号456789, 那么,我就不用告诉朋友我的新手机号,只需要办理一个呼叫转移,后续朋友们通过123456手机号给我打电话时,就会自动跳转到456789这个手机号上
在重定向的响应报文中,会使用 Location 这个属性表示当前新的URL地址
404:表示服务器找不到请求的资源,在浏览器中,这也意味着无法识别URL
403:表示客户端没有访问的权限,也就是说,资源存在,但是你没有访问权限,因此服务器拒绝提供请求资源
500:表示服务器内部错误,无法处理请求
501:表示服务器不支持请求方法
504:表示扮演网关或者代理的服务器无法在规定的时间内获得想要的响应。例如在双11活动中,请求比较多的时候,服务器在短时间内无法进行处理,就会报这样的状态码
上述提到的都是经常可以见到的,如果在学习中见到或者需要使用其他的一些状态码,可以进入这个网站进行查询:504 Gateway Timeout - HTTP | MDN (mozilla.org)