使用的工具:fiddler
一、请求和响应报文的结构
1.请求
- ⾸⾏: [⽅法] + [url] + [版本]
- Header: 请求的属性, 冒号分割的键值对;每组属性之间使⽤\n分隔;遇到空⾏表⽰Header部分结束
- Body: 空⾏后⾯的内容都是Body. Body允许为空字符串. 如果Body存在, 则在Header中会有⼀个Content-Length属性来标识Body的⻓度;
2.响应
- ⾸⾏: [版本号] + [状态码] + [状态码解释]
- Header: 请求的属性, 冒号分割的键值对;每组属性之间使⽤\n分隔;遇到空⾏表⽰Header部分结束
- Body: 空⾏后⾯的内容都是Body. Body允许为空字符串. 如果Body存在, 则在Header中会有⼀个 Content-Length属性来标识Body的⻓度; 如果服务器返回了⼀个html⻚⾯, 那么html⻚⾯内容就是在body中.
二、认识URL
URL 基本格式平时我们俗称的 "⽹址" 其实就是说的 URL (Uniform Resource Locator 统⼀资源定位符).互联⽹上的每个⽂件都有⼀个唯⼀的URL,它包含的信息指出⽂件的位置以及浏览器应该怎么处理它. URL 的详细规则由 因特⽹标准RFC1738进⾏了约定. ( https://datatracker.ietf.org/doc/html/rfc1738 )
一个具体的URL:https://v.bitedu.vip/personInf/student?userId=10000&classId=100可以看到, 在这个 URL 中有些信息被省略了
- https : 协议⽅案名. 常⻅的有 http 和 https, 也有其他的类型. (例如访问 mysql 时⽤的 jdbc:mysql )
- user:pass : 登陆信息. 现在的⽹站进⾏⾝份认证⼀般不再通过 URL 进⾏了. ⼀般都会省略
- v.bitedu.vip : 服务器地址. 此处是⼀个 "域名", 域名会通过 DNS 系统解析成⼀个具体的 IP 地址. (通过 ping 命令可以看到, v.bitedu.vip 的真实 IP 地址为 118.24.113.28 )
- 端⼝号: 上⾯的 URL 中端⼝号被省略了. 当端⼝号省略的时候, 浏览器会根据协议类型⾃动决定使⽤哪个端⼝. 例如 http 协议默认使⽤ 80 端⼝, https 协议默认使⽤ 443 端⼝.
- /personInf/student : 带层次的⽂件路径
- userId=10000&classId=100 : 查询字符串(query string). 本质是⼀个键值对结构. 键值对之间使⽤ & 分隔. 键和值之间使⽤ = 分隔.
- ⽚段标识: 此 URL 中省略了⽚段标识. ⽚段标识主要⽤于⻚⾯内跳转. (例如 Vue 官⽅⽂档: https://cn.vuejs.org/v2/guide/#%E8%B5%B7%E6%AD%A5, 通过不同的⽚段标识跳转到⽂档的不同章节)
使⽤ ping 命令查看域名对应的 IP 地址
关于 query stringquery string 中的内容是键值对结构. 其中的 key 和 value 的取值和个数, 完全都是程序猿⾃⼰约定的. 我们可以通过这样的⽅式来⾃定制传输我们需要的信息给服务器URL 中的可省略部分
- 协议名: 可以省略, 省略后默认为 http://
- ip 地址 / 域名: 在 HTML 中可以省略(⽐如 img, link, script, a 标签的 src 或者 href 属性). 省略后表⽰服务器的 ip / 域名与当前 HTML 所属的 ip / 域名⼀致.
- 端⼝号: 可以省略. 省略后如果是 http 协议, 端⼝号⾃动设为 80; 如果是 https 协议, 端⼝号⾃动设为443.
- 带层次的⽂件路径: 可以省略. 省略后相当于 / . 有些服务器会在发现 / 路径的时候⾃动访问 /index.html
- 查询字符串: 可以省略
- ⽚段标识: 可以省略
三、认识方法
1. GET ⽅法
GET 是最常⽤的 HTTP ⽅法. 常⽤于获取服务器上的某个资源. 在浏览器中直接输⼊ URL, 此时浏览器就会发送出⼀个 GET 请求. 另外, HTML 中的 link, img, script 等标签, 也会触发 GET 请求
使用FIddler观察GET请求
GET 请求的特点
- ⾸⾏的第⼀部分为 GET
- URL 的 query string 可以为空, 也可以不为空.
- header 部分有若⼲个键值对结构.
- body 部分为空
关于 GET 请求的 URL ⻓度问题⽹上有些资料上描述: get 请求⻓度最多 1024kb 这样的说法是错误的.HTTP 协议由 RFC 2616 标准定义, 标准原⽂中明确说明: "Hypertext Transfer Protocol -- HTTP/1.1,"does not specify any requirement for URL length.没有对 URL 的⻓度有任何的限制.实际 URL 的⻓度取决于浏览器的实现和 HTTP 服务器端的实现. 在浏览器端, 不同的浏览器最⼤⻓度是不同的, 但是现代浏览器⽀持的⻓度⼀般都很⻓; 在服务器端, ⼀般这个⻓度是可以配置的
2. POST ⽅法
POST ⽅法也是⼀种常⻅的⽅法. 多⽤于提交⽤⼾输⼊的数据给服务器(例如登陆⻚⾯).
通过 HTML 中的 form 标签可以构造 POST 请求, 或者使⽤ JavaScript 的 ajax 也可以构造 POST 请求
使⽤ Fiddler 观察 POST ⽅法

POST 请求的特点
- ⾸⾏的第⼀部分为 POST
- URL 的 query string ⼀般为空 (也可以不为空)
- header 部分有若⼲个键值对结构
- body 部分⼀般不为空. body 内的数据格式通过 header 中的 Content-Type 指定. body 的⻓度由 header 中的 Content-Length 指定
get和post的区别:
- 语义不同:get一般用于获取数据,post一般用于提交数据
- get:body一般为空,数据一般通过query string传递,post:query string 一般为空,需要传递的数据通过body传输
- GET 请求⼀般是幂等的, POST 请求⼀般是不幂等的. (如果多次请求得到的结果⼀样, 就视为请求是幂等的).
- GET 可以被缓存, POST 不能被缓存. (这⼀点也是承接幂等性)
补充说明:
- 关于语义: GET 完全可以⽤于提交数据, POST 也完全可以⽤于获取数据.
- 关于幂等性: 标准建议 GET 实现为幂等的. 实际开发中 GET 也不必完全遵守这个规则(主流⽹站都有 "猜你喜欢" 功能, 会根据⽤⼾的历史⾏为实时更新现有的结果.
- 关于安全性: 有些资料上说 "POST ⽐ GET 请安全". 这样的说法是不科学的. 是否安全取决于前端在传输密码等敏感信息时是否进⾏加密, 和 GET POST ⽆关.
- 关于传输数据量: 有的资料上说 "GET 传输的数据量⼩, POST 传输数据量⼤". 这个也是不科学的, 标准没有规定 GET 的 URL 的⻓度, 也没有规定 POST 的 body 的⻓度. 传输数据量多少, 完全取决于不同浏览器和不同服务器之间的实现区别.
- 关于传输数据类型: 有的资料上说 "GET 只能传输⽂本数据, POST 可以传输⼆进制数据". 这个也是不科学的. GET 的 query string 虽然⽆法直接传输⼆进制数据, 但是可以针对⼆进制数据进⾏ url encode.
四、认识请求 "报头" (header)
header 的整体的格式也是 "键值对" 结构.每个键值对占⼀⾏. 键和值之间使⽤分号分割.
报头的种类有很多, 此处仅介绍⼏个常⻅的.
Host
表⽰服务器主机的地址和端⼝
Content-Length
表⽰ body 中的数据⻓度
Content-Type
表⽰请求的 body 中的数据格式
常⻅选项:
application/x-www-form-urlencoded: form 表单提交的数据格式. 此时 body 的格式形如:
title=test&content=hello
multipart/form-data:form 表单提交的数据格式(在 form 标签中加上enctyped="multipart/form-data" . 通常⽤于提交图⽚/⽂件. body 格式形如
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3Trw------WebKitFormBoundaryrGKCBY7qhFd3TrwAContent-Disposition: form-data; name="text"title------WebKitFormBoundaryrGKCBY7qhFd3TrwAContent-Disposition: form-data; name="file"; filename="chrome.png"Content-Type: image/pngPNG ... content of chrome.png ...------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
application/json:数据为 json 格式. body 格式形如:
{"username":"123456789","password":"xxxx","code":"jw7l","uuid":"d110a05ccde64b16
User-Agent (简称 UA)
表⽰浏览器/操作系统的属性. 形如
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
其中 Windows NT 10.0; Win64; x64 表⽰操作系统信息AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36 表⽰浏览器信息
Referer
表⽰这个⻚⾯是从哪个⻚⾯跳转过来的. 形如
https://v.bitedu.vip/login
如果直接在浏览器中输⼊URL, 或者直接通过收藏夹访问⻚⾯时是没有 Referer 的
Cookie
Cookie 中存储了⼀个字符串, 这个数据可能是客⼾端(⽹⻚)⾃⾏通过 JS 写⼊的, 也可能来⾃于服务器 (服务器在 HTTP 响应的 header 中通过 Set-Cookie 字段给浏览器返回数据).
往往可以通过这个字段实现 "⾝份标识" 的功能.
每个不同的域名下都可以有不同的 Cookie, 不同⽹站之间的 Cookie 并不冲突
五、认识请求 "正⽂" (body)
正⽂中的内容格式和 header 中的 Content-Type 密切相关. 上⾯也罗列了三种常⻅的情况
application/x-www-form-urlencoded
抓取码云上传头像请求
POST https://gitee.com/profile/upload_portrait_with_base64 HTTP/1.1Host: gitee.comConnection: keep-aliveContent-Length: 107389sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"Accept: */*X-CSRF-Token: 6ROfZGr4Y7Qx8td1TuKCnrG8gbODLCSUqUBZSw2b+ac=X-Requested-With: XMLHttpRequestsec-ch-ua-mobile: ?0User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,Content-Type: application/x-www-form-urlencoded; charset=UTF-8Origin: https://gitee.comSec-Fetch-Site: same-originSec-Fetch-Mode: corsSec-Fetch-Dest: emptyReferer: https://gitee.com/HGtz2222Accept-Encoding: gzip, deflate, brAccept-Language: zh-CN,zh;q=0.9,en;q=0.8Cookie: oschina_new_user=false; user_locale=zh-CN; yp_riddler_id=1ce4a551-a160-4avatar=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAPgAAAD4CAYAAADB0Ss
实际的抓包结果⽐较⻓, 此处没有全部贴出
multipart/form-data
"上传简历" 功能
POST https://v.bitedu.vip/tms/oss/upload/file HTTP/1.1Host: v.bitedu.vipConnection: keep-aliveContent-Length: 293252sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjFiYThjMDM5Lsec-ch-ua-mobile: ?0User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,Content-Type: multipart/form-data; boundary=----WebKitFormBoundary8d5Rp4eJgrUSS3Accept: */*Origin: https://v.bitedu.vipSec-Fetch-Site: same-originSec-Fetch-Mode: corsSec-Fetch-Dest: emptyReferer: https://v.bitedu.vip/personInf/student?userId=665Accept-Encoding: gzip, deflate, brAccept-Language: zh-CN,zh;q=0.9,en;q=0.8Cookie: rememberMe=true; username=18691491410; Admin-Token=eyJhbGciOiJIUzUxMiJ9.------WebKitFormBoundary8d5Rp4eJgrUSS3wTContent-Disposition: form-data; name="file"; filename=" 李星亚 Java 开发⼯程师 .pdf"Content-Type: application/pdf%PDF-1.7%³1 0 obj<</Names <</Dests 4 0 R>> /Outlines 5 0 R /Pages 2 0 R /Type /Catalog>>endobj3 0 obj<</Author ( N v~N ) /Comments () /Company () /CreationDate (D:20201122145133+06'endobj13 0 obj<</AIS false /BM /Normal /CA 1 /Type /ExtGState /ca 1>>endobj
实际的抓包结果⽐较⻓, 此处没有全部贴出
application/json
登陆⻚⾯
POST https://v.bitedu.vip/tms/login HTTP/1.1Host: v.bitedu.vipConnection: keep-aliveContent-Length: 105sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"sec-ch-ua-mobile: ?0User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,Access-Control-Allow-Methods: PUT,POST,GET,DELETE,OPTIONSContent-Type: application/json;charset=UTF-8Access-Control-Allow-Origin: *Accept: application/json, text/plain, */*Access-Control-Allow-Headers: Content-Type, Content-Length, Authorization, AccepOrigin: https://v.bitedu.vipSec-Fetch-Site: same-originSec-Fetch-Mode: corsSec-Fetch-Dest: emptyReferer: https://v.bitedu.vip/loginAccept-Encoding: gzip, deflate, brAccept-Language: zh-CN,zh;q=0.9,en;q=0.8Cookie: rememberMe=true; username=123456789{"username":"123456789","password":"xxxx","code":"u58u","uuid":"9bd8e09ea27b48cd
六、状态码
200 OK
这是⼀个最常⻅的状态码, 表⽰访问成功
404 Not Found
没有找到资源.
403 Forbidden
表⽰访问被拒绝. 有的⻚⾯通常需要⽤⼾具有⼀定的权限才能访问(登陆后才能访问). 如果⽤⼾没有登陆直接访问, 就容易⻅到 403
405 Method Not Allowed
前⾯我们已经学习了 HTTP 中所⽀持的⽅法, 有 GET, POST, PUT, DELETE 等.
但是对⽅的服务器不⼀定都⽀持所有的⽅法(或者不允许⽤⼾使⽤⼀些其他的⽅法)
500 Internal Server Error
服务器出现内部错误. ⼀般是服务器的代码执⾏过程中遇到了⼀些特殊情况(服务器异常崩溃)会产⽣这个状态码
504 Gateway Timeout
当服务器负载⽐较⼤的时候, 服务器处理单条请求的时候消耗的时间就会很⻓, 就可能会导致出现超时的情况.
302 Move temporarily
临时重定向.
理解 "重定向"
就相当于⼿机号码中的 "呼叫转移" 功能.
⽐如我本来的⼿机号是 186-1234-5678, 后来换了个新号码 135-1234-5678, 那么不需要让我的朋友知
道新号码,
只要我去办理⼀个呼叫转移业务, 其他⼈拨打 186-1234-5678 , 就会⾃动转移到 135-1234-5678 上.
301 Moved Permanently
永久重定向. 当浏览器收到这种响应时, 后续的请求都会被⾃动改成新的地址.
301 也是通过 Location 字段来表⽰要重定向到的新地址
