目录
什么是HTTP
HTTP,全称为"超文本传输协议",是一种应用非常广泛的应用层协议。
HTTP往往是基于传输层的TCP协议实现的(HTTP1.0,HTTP1.1,HTTP2.0均为TCP,HTTP3.0是基于UDP实现的)。HTTP协议的最新版本是HTTP3.0,但目前大规模使用的是还是HTTP1.1,我们这篇文章讨论的也是以HTTP1.1版本为主。
使用HTTP协议的场景主要有两个:1.浏览器打开网站(基本上);2.手机APP访问对应的服务器(大概率)。
学习HTTP协议,重点学习的是HTTP的报文格式。与前面的TCP/IP/UDP不同,HTTP的报文格式要分为两个部分来看待,一个是请求,一个是响应。HTTP协议是一种"一问一答"结构模型的协议[HTTP不止有一问一答(访问网站)结构模型,还有多问一答(上传文件),一问多答(下载文件).多问多答(远程桌面)结构模型]。
HTTP协议抓包工具----Fiddler
HTTP的请求和相应的格式是有所差异的。那如何查看到HTTP的请求和响应的格式呢?这里就需要用到HTTP抓包工具----Fiddler。
抓包工具的原理
Fiddler相当于是一个"代理"。
浏览器访问 baidu.com 时, 就会把 HTTP 请求先发给 Fiddler, Fiddler 再把请求转发给baidu 的服务器. 当 baidu 服务器返回数据时, Fiddler 拿到返回数据, 再把数据交给浏览器. 因此 Fiddler 对于浏览器和 baidu 服务器之间交互的数据细节, 都是非常清楚的。
代理就可以简单理解为一个跑腿小弟. 比如说你想买罐冰阔落, 又不想自己下楼去超市, 那么就可以把钱给跑腿小弟, 跑腿小弟来到超市把钱给超市老板, 再把冰阔落拿回来交到你手上. 这个过程中, 这 个跑腿小弟对于 "你" 和 "超市老板" 之间的交易细节, 是非常清楚的.
Fiddler的安装
Fiddler是用来专门抓HTTP的抓包工具,使用起来简单方便, 下载地址:https://www.telerik.com/fiddler/
选择经典版就可以了,下载后安装过程比较简单,一路next就好了。安装好了之后,打开Fiddler就是这样的页面。
新安装的fiddler需要手动开启HTTPS功能,并且安装证书,否则只能抓HTTP。可能有小伙伴疑惑为什么非要开启HTTPS,因为当前的互联网环境是以HTTPS为主,纯HTTP已经很少见了,如果不开启的话们只能抓到很少的HTTP。那如何开启HTTPS功能并安装证书呢?很简单,找到工具栏中的Tools选择Options...
再选择HTTPS,把小方框都勾上,再点击OK。点击OK后 ,会弹出一个窗口询问你是否要安装根证书(英文描述的),此时一定要选择"同意(Yes)",否则就只能"喜提"重装fiddler了。
Fiddler的使用
- 左侧窗口显示了所有的 HTTP(HTTPS)请求/响应, 可以选中某个请求查看详情;
- 右侧上方显示了 HTTP 请求的报文内容 (切换到 Raw 标签页可以看到详细的数据格式);
- 右侧下方显示了 HTTP 响应的报文内容(切换到 Raw 标签页可以看到详细的数据格式);
- 请求和响应的详细数据, 可以通过右下角的 View in Notepad 通过记事本打开;
- 可以使用 ctrl + a 全选左侧的抓包结果, delete 键清除所有被选中的结果.
除了fiddler之外,加速器,vpn等程序也是代理的,而代理程序之间可能会发生冲突。如果你的电脑使用fiddler时不能抓包,就需要检查是否关闭之前的代理软件(也可能是浏览器插件),还可以尝试使用不同的浏览器.edge浏览器有的时候就不行。使用fiddler的时候一定要打开浏览器,这样才会抓到包!
左侧窗口抓到的HTTP/HTTPS还有几种颜色,不同颜色的包是有区别的。
TCP,UDP,IP协议等都是二进制格式的协议,而HTTP协议是文本格式的协议(协议里的内容都是字符串)。HTTP响应也是文本的,但是直接查看往往看到的是二进制数据,这是因为响应数据被压缩了。HTTP响应经常被压缩,因为压缩之后,体积会变小,传输的时候就节省网络带宽的消耗。
解压缩之后,可以看到响应的数据其实是html。浏览器上显示的网页就是html,往往都是浏览器先请求对应的服务器,从服务器这边拿到的网页数据(html)。
HTTP请求(Request)
认识URL
URL基本格式
平时我们俗称的 "网址" 其实就是说的 URL (Uniform Resource Locator 统一资源定位符). 互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它. URL 的详细规则由因特网标准RFC1738 进行了约定. ( https://datatracker.ietf.org/doc/html/rfc1738)
关于URL Encode
像 / ? : 这样的字符,已经被url当作特殊意义理解了,因此这些字符不能随意出现。如果某个参数中需要带有这些特殊字符,就必须先对特殊字符进行转义。
转义的规则:将需要转义的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做1位,前面加上%,编码成%XY的格式。例如:
"+"被转义了"%2B"。urlencode本质上就是一种"转移字符",中文,汉字都需要转义。所以在使用url的时候,要记得针对query string的内容进行urlencode工作;如果处理不好,有些浏览器就可能会解析失败,导致请求无法正常进行。
认识"方法"(method)
方法 | 说明 | 支持的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 |
OPTIONS | 询问支持的方法 | 1.1 |
TRACE | 追踪路径 | 1.1 |
CONNECT | 要求用隧道协议连接代理 | 1.1 |
LINK | 建立和资源之间的联系 | 1.0 |
UNLINE | 断开连接关系 | 1.0 |
1.GET方法
GET是最常用的HTTP方法,常用于获取服务器的上的某个资源。在浏览器中直接输入URL,此时浏览器就会发送出一个GET请求;另外,HTML中的link,img,script等标签也会触发GET请求。
使用Fiddler观察GET请求
打开FIddler,访问百度主页,观察抓包结果
在上面的结果中可以看到:
最上面的是通过浏览器地址栏发送的GET请求,
下面的和baidu域名相关的请求,有些是通过html中的link/script/img标签产生的,例如:
选中第一条观察详细请求结果
GET https://www.baidu.com/ HTTP/1.1
Host: www.baidu.com
Connection: keep-alive
Cache-Control: max-age=0
sec-ch-ua: "Chromium";v="118", "Google Chrome";v="118", "Not=A?Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://baidu.lianghi.com/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: BIDUPSID=79F813F246038BE54094317A1201810A; PSTM=1646541110; sug=3; sugstore=0; ORIGIN=0; bdime=0; BAIDUID=7C2E90E71943EB65815B8439683C3DDE:FG=1; MCITY=-132%3A; BD_UPN=12314753; H_WISE_SIDS=40079_40303_40381_40367_40416_40466_40513_40398_40446_60044_60026_60048_40510; H_WISE_SIDS_BFESS=40079_40303_40381_40367_40416_40466_40513_40398_40446_60044_60026_60048_40510; H_PS_PSSID=40303_40381_40367_40416_40513_40398_40446_60044_60026_60048_40510; H_PS_645EC=4073MW%2FR8Rwj7zGcBEBGZvw5SrlssBbBY%2BCQob5J2GOeABi0ls3wGfgvn5nphyPuZ0f5tCTH7UmDag; delPer=0; BD_CK_SAM=1; PSINO=7; COOKIE_SESSION=4495423_12_8_8_9_47_1_4_4_8_0_5_314_777_0_0_1708435125_1707235834_1712930514%7C9%23953_168_1707235783%7C9; BAIDUID_BFESS=7C2E90E71943EB65815B8439683C3DDE:FG=1; BDRCVFR[ELcT9xRAHcn]=eeLTGPPn8OcUA-9UhICpi4WUvY; BA_HECTOR=a4a10h8h8k00002105alag8huupcpc1j1igj81t; ZFY=AjeyjQ2sO8VFcM33qq5gEB3DIPgQm2JtRU11NOSYSKw:C; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598
GET请求的特点
- 首行第一部分为GET
- URL的query string可以为空也可以不为空
- header部分有若干个键值对结构
- body部分为空
2.POST方法
POST 方法也是一种常见的方法. 多用于提交用户输入的数据给服务器(例如登陆页面). 通过 HTML 中的 form 标签可以构造 POST 请求, 或者使用 JavaScript 的 ajax 也可以构造 POST 请求.
使用 Fiddler 观察 POST 方法
在Gitee的登陆页面,输入用户名和密码,点击登录就可以看到POST请求:
点击这个请求查看详情:
POST https://gitee.com/login HTTP/1.1
Host: gitee.com
Connection: keep-alive
Content-Length: 451
Cache-Control: max-age=0
sec-ch-ua: "Chromium";v="118", "Google Chrome";v="118", "Not=A?Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
Origin: https://gitee.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://gitee.com/login?redirect_to_url=%2F
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: user_locale=zh-CN; oschina_new_user=false; sensorsdata2015jssdkchannel=%7B%22prop%22%3A%7B%22_sa_channel_landing_url%22%3A%22%22%7D%7D; remote_way=http; slide_id=10; visit-gitee--2024-03-06=1; BEC=1f1759df3ccd099821dcf0da6feb0357; Hm_lvt_24f17767262929947cc3631f99bfd274=1711546573,1711803626,1712455685,1712905788; user_return_to_0=%2F; tz=Asia%2FShanghai; csrf_token=C3f70Gm%2FA%2BYSy6vVSAyQxCaDKxjnl38R18CnowRWZnFI2JRuu%2F89mgMdlWDDv6k9%2F%2FN%2FH9iHFDmv4WcH89%2BN7w%3D%3D; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2218ed2d273201ea-0554d2fb0371014-26031151-1327104-18ed2d273211a0d%22%2C%22first_id%22%3A%22%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%24latest_referrer%22%3A%22%22%7D%2C%22%24device_id%22%3A%22185753f3df8af2-0501c17e118eecc-6b3e555b-1327104-185753f3df9ba3%22%2C%22identities%22%3A%22eyIkaWRlbnRpdHlfY29va2llX2lkIjoiMTg1NzU1YzJiOGJiNTYtMGI4MzAwYTFkMTM5ODU4LTZiM2U1NTViLTEzMjcxMDQtMTg1NzU1YzJiOGMxMjU5IiwiJGlkZW50aXR5X2xvZ2luX2lkIjoiMTIyOTI0NjEifQ%3D%3D%22%2C%22history_login_id%22%3A%7B%22name%22%3A%22%24identity_login_id%22%2C%22value%22%3A%2212292461%22%7D%7D; Hm_lpvt_24f17767262929947cc3631f99bfd274=1712933991; gitee-session-n=aENXeXRIeW1ncWVZUWY4bDFRQitMSjl3WHZiaGNKYTJoWVpsbS9RRkZQUkU4Uy81a2JlMGpuMkhwRlNLSDFWY0N1UDdLZEtNZ3FJd0hqK21EQ0M5NGxHQXptVUNhcG5xSmdZQ0lKNEgyMHZUbndsZU1RZzBTaW02Sk85M2Z4S0xHbnEzQVVmaFVEbE5yRmxQemdkRTRuOEQvS0JqS2phaGp3Q29FTkNPOCtxRTJ0aUVRMHRHaFo1U3RJQXphOHdUckF3RnJIVUs1S29McGlKQnllVnNoOWxEQ2IrVkZkbDlYcHdrdjRSV1cwSG4zZ2hUYXBzclkxN1ZMUVRjdHFYWkY1ZnMyOURNaUkzdVNHc2RQMG1ESStlU1ArUjd5UFZqNU5Da2lUUWhqNDFoYmFQM05VS2h1RVB6anZOSGJodWZUQWNjWWJ2Wk1Cb3kzZEl0dklNeEI4TmtlcFc1bDZUU0J5aGZVd3U4eUdsMldMQ2pqbittSURiNmVCN0x1bHI3MlFBc1RnN1o2bHdnbG9La0liRVV5Q2FIdHFpWmkvWHN0aWVlSTZyZ1FsUU9aajZkL0FPb0lIZUlhTkwrUEt0OU1qQWwzVHRUQ0doZ3hpSld3SGVnL3J2WGl0YmpMZFgyY0hVZXNwbDZlMm1sYmsvdmFYbG90cDlNc2R1c3dMQmFzWXp5YmExL2d6bWxpL0E5ekxmVk84bmF4b0NYQzQzUHd6ZnorT3ZqZEZ3PS0tdjMrRUp3NDFiVVJTcmhSQ25ZbjdVUT09--9c96a252f9e0eaec9a3d74575763c3bc0377173cencrypt_key=password&utf8=%E2%9C%93&authenticity_token=qW1TX2jod3XXr7MRMb5d08GHRvxk1wLEd41U%2BmXxbyTqwjzhuqhJCcZ5jaS6DWQqGPcS%2B1vHaewPrJRekniEug%3D%3D&redirect_to_url=%2F&user%5Blogin%5D=13594515074&encrypt_data%5Buser%5Bpassword%5D%5D=rzTAwGtEBttIPjf1aTEANoKi0hGKi0f%2FvP9dTwh5Oef4dhhumybuG%2FY04kTknnwRZ4WML3F1ZiJNpg5JB0z%2FmVW0bnuoP6nJeWgXONE5QIh%2F5y9Y1Y%2FhwWXteoDVDsZ%2BqYFij%2FdHrtcR8LnUHYRTjsdd4IOU34Z2kLuo1E%2Bwqao%3D&user%5Bremember_me%5D=0
POST请求的特点
- 首行的第一部分为POST
- URL的query string一般为空(也可以不为空)
- header部分有若干个键值对结构
- body部分一般不为空,boby内的数据格式通过header的Content_Type的指定,body的长度有header的Content-Length指定。
GET和POST的区别(经典面试题)
其实GET和POST没有本质上的区别(双方可以替换对方的场景),但是在使用习惯上还是有差别的:
1.语义上的差异:GET一般用来获取数据,POST一般用来提交数据
2.GET经常把传递给服务器的数据放在query string中,POST则是经常放到body中.(上述情况并不是绝对的,GET也可以使用body,POST也可以使用query string,但使用的前提是客户端服务器都得按照一样的方式来处理代码)
3.其他方法
- PUT和POST相似,一般用于更新
- DELETE删除服务器指定资源
- OPTIONS返回服务器所支持的请求方法
- HEAD类似于GET,只不过响应体不返回,只返回响应头
- TRACE回显服务器段收到的请求,测试的时候会用到
- CONCECT预留,暂无使用
认识请求头"报头"(header)
header的整体格式也是键值对结构,每个键值对独占一行.建和值之间只用分号分割。
报头的种类有很多,这里介绍几个常见的:
1.HOST
表示服务器主机的地址和端口
2.Content-Length
表示body中的数据长度
3.Content-Type
表示请求的body中的数据格式,body中的格式可选择的方式是很多的:
请求:1) json; 2) form表单的格式 ; 3) form-data的格式
响应:1) html; 2) css; 3) js; 4) json; 5) 图片....
注:请求里有body才会有Content-Length和Content-Type这两个属性,通常情况下,GET请求没有body,POST请求有body。
之前说过TCP数据包在传输时会涉及到粘包问题,而HTTP在传输层就是基于TCP的。如果使用同一个TCP连接,传输多个HTTP数据包,此时就会使多个HTTP数据包粘在一起,所以接收方解析的时候,就需要能够清楚知道HTTP数据包之间的边界。
对于GET这种没有body的请求,直接用使用空行(分隔符)来区分边界;对于POST这种有body的请求,就结合空行和Content-Length来进行区分。
4.User-Agent(简称UA)
描述了使用什么设备上网。UA以前是用来区分浏览器的,但现在浏览器之间的差异已经很小了,UA的作用也没那么关键了。现在的UA主要用来区分是PC端还是移动端。
5.Referer
描述当前这个页面是从哪个页面跳转过来的。
如果直接在浏览器中输入url,或者直接通过收藏夹访问页面时是没有Referer的。
6.Cookie
Cookie可以认为是浏览器在被本地存储数据的一种机制。
浏览器的数据来自于服务器,浏览器的后续操作也是要交给服务器的,可以说,服务器管理了一个网站的各种核心数据。但是程序运行过程中,也会有一些数据是需要在浏览器这边存储的,并且在后续的请求的时候数据可能需要再发给服务器。比如上次登录的时间,上次访问的时间,用户的身份信息等这种临时性的数据,存储在浏览器中是比较合适的。
这样更容易想到的是把数据直接存储在本地文件中,但实际上是不可行的,如果访问的网站里有病毒,直接入侵你的硬盘,带来的后果是很严重的,所以浏览器为了安全性,禁止网页直接访问电脑的文件系统。为了保证安全性,又能进行存储数据,于是就引入了Cookie。Cookie也是按照硬盘文件的方式保存的,但是浏览器那操作文件给封装了,网页只能王Cookie中存储键值对(键值对中是简单的字串)。
Cookie往往存储的是从服务器返回的数据(也可以是页面自己生成的),Cookie存储到浏览器主机所在的硬盘上,并且按照域名为维度来存储。每个不同的域名下都可以有不同的Cookie,不同网站之间的Cookie并不冲突。
Cookie是按照键值对的形式来存储的,这些键值对也是程序员自定义的(和query string差不多)。键值对之间使用 ; 分割,键和值之间使用 = 分割。后续在请求服务器的时候,就会把Cookie中的内容自动带入到请求中,服务器通过Cookie的内容做一些逻辑上的处理就可以了。
请求格式
1)首行
HTTP请求的第一行有三个部分信息,三个部分使用空格分隔
(1)GET HTTP请求的"方法"(method)
(2)URL 唯一资源定位符,描述了一个资源在网络中的位置
(3)版本号 可以看到www.baidu.com网站使用的是HTTP/1.1
2)请求头(header)
请求头记录的是键值对结构的数据(不止一个键值对),这里的键值对都是属于"标准规定"的,每个键值对都是独占一行的,建和值之间使用 :空格 来区分。
3)空行
请求头的结束标记。
4)正文(body)
body不是每个HTTP请求都有的,有的HTTP请求有,有的没有。
HTTP响应(response)
认识"状态码"(statu code)
HTTP 状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型。响应分为五类:信息响应(100–199),成功响应(200–299),重定向(300–399),客户端错误(400–499)和服务器错误 (500–599):
这里只介绍几个常见的状态码:
1.200 OK
这是一个最常见的状态码,表示访问成功。抓包抓到的大部分结果都是200
2.404 Not Found
表示没有找到资源。在浏览器中输入一个URL,目的就是为了访问服务器上的一个资源,如果这个URL标识的资源不存在,那么就会出现404这样的响应。
3.403 Forbidden
表示访问被拒绝。有的页面通常需要用户具有一定的权限才能访问(登陆后才能访问). 如果用户没有登陆直接访问, 就容易见到 403。
4.405 Method Not Allowed
前面我们已经学习了 HTTP 中所支持的方法, 有 GET, POST, PUT, DELETE 等. 但是对方的服务器不一定都支持所有的方法(或者不允许用户使用一些其他的方法).
5.500 Internal Server Error
服务器出现内部错误. 一般是服务器的代码执行过程中遇到了一些特殊情况(服务器异常崩溃)会产生这个 状态码.
6.504 Gateway Timeout
当服务器负载比较大的时候, 服务器处理单条请求的时候消耗的时间就会很长, 就可能会导致出现超时的情况。
7.301 Moved Permanently
永久重定向,当浏览器收到这种响应时, 后续的请求都会被自动改成新的地址。响应报文的 header 部分会包含一个 Location 字段, 表示要跳转到哪个页面.
理解重定向:请求中访问的是A这样的地址,响应返回了一个重定向报文,告诉你应该要访问B地址。
很多时候,页面跳转就可以通过重定向来实现,还有的时候,某个网站的服务器迁移了(IP/域名变了)就可以给旧的地址挂一个重定向响应,访问旧地址的用户就会自动跳转到新的地址。\
8.302 Move temporarily
临时重定向,在登陆页面中经常会见到 302. 用于实现登陆成功后自动跳转到主页。也通过 Location 字段来表示要重定向到的新地址。
状态码小结
认识响应"报头"(header)
响应报头的基本格式和请求报头的格式基本一致.。类似于 Content-Type, Content-Length 等属性的含义也和请求中的含义一致。
响应格式
1)首行
HTTP响应的第一行也有三个部分信息,三个部分使用空格分隔
(1)版本号 HTTP/1.1
(2)状态码 (200) 描述了请求的结果
(3)状态码描述(OK) OK就是表示成功了
2)响应头(header)
响应头也是键值对结构(不止一个键值对),这里的键值对都是属于"标准规定"的,每个键值对都是独占一行的,建和值之间使用 :空格 来区分。
3)空行
响应头的结束标记。
4)正文(body)
响应正文里的内容可能会比较长,可以是多种格式,比如HTML,CSS,JS,JSON,XML,图片,音频,视频等等。
这次的文章就分享到这里了,有问题小伙伴可以留言评论,我们一起共勉