目录
[1 HTTP 协议](#1 HTTP 协议)
[1.1 HTTP 协议是什么](#1.1 HTTP 协议是什么)
[1.2 HTTP 协议格式](#1.2 HTTP 协议格式)
[1.3 HTTP 请求](#1.3 HTTP 请求)
[1.3.1 请求的 URL](#1.3.1 请求的 URL)
[1.3.2 请求的方法](#1.3.2 请求的方法)
[1.3.3 请求的 Header](#1.3.3 请求的 Header)
[1.3.4 请求的 body](#1.3.4 请求的 body)
[1.4 HTTP 响应](#1.4 HTTP 响应)
[1.4.1 响应状态码](#1.4.1 响应状态码)
[1.4.2 响应 Header](#1.4.2 响应 Header)
[1.4.3 响应 body](#1.4.3 响应 body)
[2 抓包工具 fiddler](#2 抓包工具 fiddler)
[2.1 fiddler 的下载安装](#2.1 fiddler 的下载安装)
[2.2 fiddler 的使用](#2.2 fiddler 的使用)
1 HTTP 协议
1.1 HTTP 协议是什么
HTTP,全称为超文本传输协议,是一种应用层协议。
HTTP 诞生于1991年,是目前主流的应用层协议,HTTP1.0,HTTP1.1,HTTP2.0 是基于传输层的 TCP 协议实现的,而 HTTP3 是基于传输层的 UDP 协议实现的。
应用层的协议是在乎的与传输层的协议不同,对于传输层协议来说,它们关注的是如何将信息船传递出去,而应用层协议关注的是如何应用这些信息。
下面举一个例子来说明 HTTP 协议的工作过程:
当我们再浏览器中输入一个百度的网址(也就是 URL)时,浏览器就会给百度的服务器发送一个 HTTP 请求,百度的服务器就会返回一个 HTTP 响应。这个响应被浏览器解析之后就会展现出我们看到的模样。

1.2 HTTP 协议格式
那么 HTTP 协议肯定有自己的格式,所以浏览器才能进行解析。为了看到 HTTP 协议的格式,我们需要使用抓包工具来抓到一个 HTTP 协议的包,然后查看 HTTP 协议的格式,这里我们使用 fiddler 抓包工具,这个软件的下载和安装在本篇博客的第 2 部分。
下面我们简单介绍一下 HTTP 协议的格式:
HTTP 的一个请求/响应包括以下几部分:
- 首行
- Header
- 空行
- body
在请求中,首行也称为请求行,包含的信息是 [方法] + [URL] + [HTTP版本号];Header 在请求中称为"请求头",Header中是请求的属性,由许多对键值对组成,每个键值对占一行;空行用来标识 Header 的结束;body 可以为空,也可以不为空。
在响应中,首行也称为状态行,包含的信息是 [HTTP版本号] + [状态码] + [状态码含义];Header 在响应中称为"响应头",Header中是响应的属性,由许多对键值对组成,每个键值对占一行;空行用来标识 Header 的结束;body 可以为空,也可以不为空,一般响应的 body 就是服务器给浏览器返回的东西。
用一个图来简单表示:

1.3 HTTP 请求
1.3.1 请求的 URL
URL 全称 Uniform Resource Locator (统一资源定位符),也就是我们经常说的网址。一个网址包含了很多信息,下面我们使用一个例子来进行具体的介绍。

如果在浏览器中搜索C++,那么对应的 URL 为:
https://cn.bing.com/search?q=C%2B%2B&qs=n&form=QBRE&sp=-1&lq=0&pq=c%2B%2B&sc=12-3&sk=&cvid=9E87968622DA4EADB9AD51D528E2B885
在这个 URL 中,C++ 被写成了 C%2B%2B,这是因为在 URL 中本来就存在像&、=这些特殊字符,所以 + 也可能会被 URL 认为是查询字符串中的某个特殊字符,但是这个只是我们要查询的东西,所以就通过 URL encode 将 + 这样的特殊字符进行了转码(将需要转码的字符按照一个字节一个字节取出来之后转为16进制,并且在前面加上%符号),这里的%2B就是因为 + 被转码转为了2B。
1.3.2 请求的方法
HTTP 请求有不同的方法:
|---------|-------------|-----------------|
| 方法 | 说明 | 支持的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 |
虽然有这么多方法,但是我们这里主要对 GET 和 POST 进行介绍:
1. GET
以下面的这个请求为例:
java
GET https://gitee.com/notifications/unread_count HTTP/1.1
Host: gitee.com
Connection: keep-alive
sec-ch-ua-platform: "Windows"
X-CSRF-Token: ET5SjYglMDhDW6c1T9r92vtAT/IS+SX38NhWj1jRLxnm8BD2cLEm7x0+MO/SMZn/M38Ev8IKmEawu4Krg6bnEQ==
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36
Accept: */*
sec-ch-ua: "Chromium";v="136", "Google Chrome";v="136", "Not.A/Brand";v="99"
sec-ch-ua-mobile: ?0
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://gitee.com/HGtz2222/classroom-blackboard-writing/blob/master/java113/java113_1120_http.png
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: zh-CN,zh;q=0.9
Cookie: oschina_new_user=false; user_locale=zh-CN; remote_way=http; close_wechat_tour=true; remember_user_token=BAhbCFsGaQNWs6JJIiIkMmEkMTAkYkJtVFlCVG9RcmxZOUQyZ0RyVnRoLgY6BkVUSSIVMTc2MTQ4MTYyNS40MTU4MwY7AEY%3D--6d4ee6a23dfa3bab7d786013bd8d446d9f6af304; BEC=1f1759df3ccd099821dcf0da6feb0357; gitee_user=true; tz=Asia%2FShanghai; Hm_lvt_24f17767262929947cc3631f99bfd274=1761482788,1761548493,1761555834,1761649809; HMACCOUNT=2C8A7F768C9710DE; Hm_lpvt_24f17767262929947cc3631f99bfd274=1761649816; gitee-session-n=TUFHS01Oc0h5Z09ESmg1OGFhcW9LMzBvbFU4am5UV2t2LyswWFk0STZIVG1SejVDMjcwUHNleDd1L2FkQzJYc2xRK05QNUlxcEU1UEhQcXVHWWRRS3I0Qjh6ZC95MnljTExES0Q3emliOXpRVmNQMmM4enJrZVpPUU5sbTErWnpvV1ZEdjc5YW93RnA1akllY3dFczNSZ2I0a29HWEtjWTFzWGdsK0Q1Tk1PYVAzNkVwM2w4NGZhVHYxN0tEWmlLbGNoN0w0cVR1dHFqWnBrb1JKZW9WNDhJcjRDVXI4R3doRzZjcXFCRXpvVWtrYng0ZncrNFZLUjAxNlVsQ0RlRXBlbGpVQ3pGTWVuVHpmemgxZ1o4S1Z2SjBmQ2RHZG5QWVd0b1lEaTcyRTUvVHE0c0NTMlh5TklyN1I3ZFRkek9Xbi9LZ1pnb1d4eERXSEV0S0lKUFlFQm5TOExlYmlwVDlTdEJObXYvaVJvPS0tRkxGS2MyRmF4S3kzVHhiOXpTbGR6dz09--7579211ee893e351ed08c836d16e0eb1d34e09e8
在这个请求中,首行的方法为 GET,URL 的查询字符串可以为空也可以不为空,Header中包含多个键值对,在 Header 结束后有一个空行。可以看到的是这个请求中并没有 body ,这也是 GET 方法的特点之一。GET 方法中如果有需要传送的数据一般也是通过 URL 中的查询字符串进行传送的。
2. POST
以下面这个请求为例:
java
POST https://eva2.csdn.net/v3/06981375190026432f77c01bfca33e32/lts/groups/dadde766-b087-42da-8e67-d2499a520ee7/streams/ea448b34-0491-4546-87aa-059120b54c53/logs HTTP/1.1
Host: eva2.csdn.net
Connection: keep-alive
Content-Length: 1578
sec-ch-ua-platform: "Windows"
sec-ch-ua: "Chromium";v="136", "Google Chrome";v="136", "Not.A/Brand";v="99"
sec-ch-ua-mobile: ?0
X-Sdk-date: 20251028T114357Z
Lts-Sdk-Request-Id: b57db1b90920494599d89c0626e2b212
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36
Content-Type: application/json
Lts-Sdk-Version: 1.0.15
Accept: */*
Origin: https://mp.csdn.net
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://mp.csdn.net/
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: zh-CN,zh;q=0.9
{"labels":{},"logs":[{"contents":[{"pid":"mp","ref":"https://blog.csdn.net/weixin_61741406?spm=1010.2135.3001.5343","curl":"https://mp.csdn.net/mp_blog/creation/editor/153970714","dest":"","spm":"1011.2266.3001.6217","disabled":"true","extra":"{\"version\":\"new\"}","t":"1761651835","eleTop":"","cCookie":"c_dl_fref=https://so.csdn.net/so/search;c_dl_prid=1753181627589_877833;c_dl_rid=1753181639496_315210;c_dl_fpage=/download/weixin_42133452/19197026;c_dl_um=distribute.pc_search_result.none-task-download-2%7Eall%7Efirst_rank_ecpm_v1%7Erank_v31_ecpm-4-10301507-null-null.142%5Ev102%5Epc_search_result_base1;c_ab_test=1;c_session_id=10_1761646592940.225255;c_segment=4;c_sid=855d560f33eb524586de770e092950fe;c_pref=https%3A//blog.csdn.net/weixin_61741406%3Fspm%3D1000.2115.3001.5343;c_ref=https%3A//cn.bing.com/;c_first_ref=cn.bing.com;c_first_page=https%3A//blog.csdn.net/hmy123cq3/article/details/115726104;c_dsid=11_1761651761798.886020;c_page_id=default;c_tos=t4ub76;","__time__":1761651835,"urn":"1761651835323-2b7e5ca8-5cd0-4002-9448-bd717f68cbd9","pv_urn":"1761646806728-ce665ca6-fff7-48e3-91d8-34a2bca62db5","hca":"2C8A7F768C9710DE","log_id":"296","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36","cid":"10_19090224020-1738551068190-515252","uid":"weixin_61741406","sid":"10_1761646592940.225255","dc_sid":"855d560f33eb524586de770e092950fe","did":"10_19090224020-1738551068190-515252","utm":"","platform":"PC","fid":"20_73768073296-1758186484436-229557","__client_time__":1761651835325}]}]}
在这个请求中,首行的方法为 POST,URL 的查询字符串一般为空(但是也可以不为空),Header中包含多个键值对,在 Header 结束后有一个空行。POST方法的 body 一般不为空,body 不为空的时候在 Header 中就有一个 Content-Type 指定 body 的格式,Content-Length 指定 body 的长度。
3. GET 和 POST 的区别
- 语义上的区别:GET一般用于提交数据,POST一般用于获取数据
- 携带数据的方式不同:GET一般在查询字符串中携带数据,POST一般在 body 中携带数据
- GET请求通常设计为幂等的,POST没有要求:幂等的意思就是在进行多次请求的时候,每一次的返回都是相同的
- GET请求的结果允许被缓存,POST请求的结果不允许别缓存:这是因为GET实现了幂等,POST没有实现
还有一些错误的说法:
- POST 比 GET安全:这是因为如果是登录的场景,那么GET会将用户名和密码直接显示在 URL 的查询字符串中,而POST则是放在 body 中,但是这并不能说明 POST 就是安全的,它只是没有放在 URL 中,如果在传输中是通过明文传输,那么 POST 也是不安全的。
- GET 传输数据有长度限制:在HTTP 协议标准中说到对 URL 的长度是没有限制的,实际的 URL 长度取决于浏览器的实现,在浏览器中,不同浏览器的最大长度是不同的,可能有的会比传输的数据短,所以造成了 GET 传输数据有长度限制的错误印象。
- GET 只能传输文本,POST可以传输二进制:GET 方法确实只能通过 URL 传输文本,但是可以把二进制转成文本在查询字符串中进行传输,而且 GET 也不是完全不能有 body ,对于有 body 的GET来说,就可以传输二进制数据了。
4.其他方法
- PUT 方法与 POST 类似,但是 PUT 具有幂等性,一般用来更新
- DELETE 方法用来删除服务器指定资源
- OPTIONS 方法返回服务器所支持的请求方法
- HEAD 方法类似于 GET,只不过响应体不返回,只返回响应头
- TRACE 方法回显服务器端收到的请求
- CONNECT 方法用于建立隧道连接,可以传送非 HTTP 协议的数据
1.3.3 请求的 Header
Header 包含很多行,每一行是一个键值对,每个键值对中间用:连接。键和值的内容是标准规定的,并不是随便写一个键值对就可以放到 Header 中。
这里介绍几个常见的:
- Host:标识服务器主机的地址和端口
- Content-Type:表示请求中 body 的数据格式(有 body 才有 Content-Type)(有很多种,例如:html、css、js、json等)
- Content-Length:表示 body 的数据长度,单位是字节
- User-Agent:表示浏览器/操作系统的信息
- Referer:用来描述当前页面是从哪个页面跳转来的
- Cookie:Cookie种存储了一个字符串,这个数据可能是客户端自行通过js写入的,也可能是来自于服务器。
Cookie 是浏览器允许网页在本地存储数据的一种机制,它通过键值对的方式存储数据。Cookie 一般在登录的时候经常被用到。它相当于一个令牌,就是在登录一个网站的时候,将自己的用户名密码输入进去,登录页面将这个登录请求发送给服务器,服务器在数据库中进行查询,如果查到存在这个用户,那么就生成一个 session 对象将用户信息存到这个 session 对象中(这个session 对象是唯一的),session 对象和 sessionId 作为一个键值对通过 Set-Cookie 返回给登录页面。Cookie 存储了这个 sessionId ,那么在之后访问其他页面的时候,都会带着这个 Cookie 通过 Cookie 查看 sessionId 就知道是哪个用户在访问页面了,就不需要再次验证你的身份了。
1.3.4 请求的 body
body 中的内容就是获取到的页面信息,这里边的数据格式也有很多种(例如:json、form等),具体是哪一种可以通过 Header 中的Content-Type 看到。
像下面这个请求中的 body 就是用的 json 的格式:

1.4 HTTP 响应
1.4.1 响应状态码
状态码表示访问一个页面的结果,下面是一些常见的状态码分类:
- 1xx(信息性状态码):表示接收的请求正在处理
- 2xx(成功状态码):表示请求正常处理完毕
- 3xx(重定向状态码):需要后续操作才能完成这一请求
- 4xx(客户端错误状态码):表示请求包含的语法错误或者无法完成
- 5xx(服务器错误状态码):服务器在处理请求的过程中发生了错误
具体的每一类中还有一些常用的状态码:
|---------------------------|-----------------------------------------------------|
| 状态码 | 含义 |
| 200 OK | 表示访问成功(是最常见的一种状态码) |
| 301 Moved Permanently | 永久重定向(当浏览器收到这种响应之后,后续的请求都会被自动改成新的地址,访问也是访问这个新地址的数据) |
| 302 Move temporarily | 临时重定向(与永久重定向类似,只是一次的请求被改成新的地址) |
| 403 Forbidden | 表示访问被拒绝(有的页面必须要有一定的权限才能进行访问,如果没有权限就直接访问就会出现这个状态码) |
| 404 Not Found | 没有找到资源(根据请求发送的 URL 没有找到对应的资源) |
| 405 Method Not Allowed | 服务器不支持方法(有的服务器会不支持某一种访问的方法就会出现这个状态码) |
| 500 Internal Server Error | 服务器内部出现错误(一般是服务器的代码在执行过程中出错导致服务器崩溃会出现这个状态码) |
| 504 Gateway Timeout | 网关超时(在有很多客户端给服务器同时发送大量请求时,服务器处理不过来的时候就导致出现这种状态码) |
1.4.2 响应 Header
响应 Header 与请求 Header 的格式基本一致,一些键值对的含义也一致,其中 Header 中的Content-Type中有常见的下面几种类型:
- text/html:body 的数据格式是 HTML
- text/css:body 的数据格式是 CSS
- application/javascript:body 的数据格式是 JavaScript
- application/json:body 数据格式是 JSON
1.4.3 响应 body
和请求 body 一样,body 的格式由 Header 中的 Content-Type 决定的。
2 抓包工具 fiddler
Fiddler 是一个 HTTP 协议调试代理工具(也就是我们上面说的抓包工具),通过代理服务器截获并分析计算机与互联网之间的 HTTP/HTTPS通信数据(也就是我们说到的抓包)。
2.1 fiddler 的下载安装
下载这个软件可以直接去官网进行下载(Fiddler官网),但是要注意的是这里有两种 fiddler。(推荐使用Fiddler Classic 因为是免费的)

下载之后安装就很简单了,一路 next 就可以了。
2.2 fiddler 的使用
打开 fiddler 之后,点击 Tools -> Options,点击 HTTPS ,然后把这些都进行勾选就好了。要注意的是,如果有弹出是否接受 fiddler 证书这种弹框,一定要选 yes。不然就用不了了。


这个软件的页面整体上被分为两块:左边的是一些 URL 是 fiddler 抓取到的一些 HTTP 的包;右边的是左边某一个包的具体信息,其中右边又被分为上下两块:上面的是发送的 HTTP 请求,下面的是 HTTP 响应。
如果要在看的更清楚一点,可以用打开一个文本文档,点击"View in Notepad"即可。在响应中,有乱码的情况,那么点击这个"Response body is encoded。Click to decode"即可,响应也可以用同样的方式使用文本文档打开。
