HTTP(全程为"超文本传输协议")是一种给应用广泛的 应用层协议.
HTTP往往是基于传输层的TCP协议实现的.(HTTP1.0, HTTP1.1,HTTP2.0均为TCP,HTTP3基于UDP实现)
目前我们主要使用的是HTTP1.1和HTTP2.0
我们在浏览器中输入一个"网址"(URL)时,浏览器就会给服务器发送一个HTTP请求,服务器就会返回一个HTTP响应.这个响应结果就会被浏览器解析之后,就会展示成我们看到的页面内容(这个过程中浏览器可能会给浏览器发送多个HTTP请求,服务器会对应返回多个响应,这些响应里包含了页面HTML,CSS,JavaScript,图片,字体等信息)
我们已经学过TCP/IP,已经知道了目前数据能从客户端进程经过路径选择跨网络传送到服务器端进程[IP+Port]
可是仅仅是把数据从A主机传送到B主机就完了吗?
这好比我们买一个科研仪器,我们只是让快递把商品从卖家手中,送到了卖家手中.但是这个科研仪器具体是怎么使用的,我们也要告诉对方.
所以,我们把数据从A主机发送到B主机,TCP/IP解决的是发送数据的问题,而两端还要对数据进行加工处理或使用,这层协议叫做应用层协议.
应用层协议有着不同的种类,其中最经典协议之一是HTTP
当我们在浏览器中输入一个网址,此时浏览器就会给对应的服务器发送一个HTTP请求.对方服务器接收到这个请求之后,经过处理,就会返回一个HTTP响应.
事实上我们访问一个网站的时候,我们可能涉及不止一次的HTTP请求/响应的过程
我们通过chrome的开发者工具或者Fiddler(或者其他的抓包工具),以下是打开百度浏览器发送的部分请求,我们重点看蓝色的部分
[方法一]如何打开开发者工具(Microsoft Edge):我们按F12,点击网络,即可查看,如果里面什么都没有,我们强制刷新网页(cltrl+R 或者 cltrl+F5)
[方法二]下载Fiddler,下载地址:Download Fiddler Web Debugging Tool for Free by Telerik
HTTP是一个文本格式的协议.可以通过Chrome开发者工具或者Fiddler抓包,分析HTTP请求/响应的细节
Fiddler相当于一个"代理"
当浏览器访问网站的时候,会先将HTTP请求发送给Fiddler,Fiddler再把相关的请求转发给相应的服务器.当响应的服务器返回数据的时候,Fiddler拿到返回数据,再把数据交给浏览器.
[通俗的栗子]我有一串钥匙要交给同城的小张同学,我可以选择自己送给快递小哥,也可以选择交给快递小哥,让他帮忙交给小张同学.不论什么方式送给小张的钥匙是不会改变的,小张收到要是的结果也不会改变的.
此处的快递员就相当于Fiddler.
以下是一个HTTP请求/响应的抓包结果
HTTP请求
- 首行:[方法] + [URL] + [版本号]
- Header:请求的属性,冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分结束(如图中倒数第二行,表示Header的结果)
- Body:空行后面的内容都是Body.Body允许空字符串.如果Body存在,则在Header中会有一个Content-Length属性来标识Body长度
HTTP响应
- 首行:[版本号] + [状态号] + [状态码解释]
- Header:请求的属性,冒号分割的简直对;每组属性之间使用\n分割;遇到空行表示Header部分结束
- Body:空行后面的内容都是Body.Body允许是空字符串.如果Body存在,则在Header中会有一个Content-Length属性来标识Body的长度;如果服务器返回了一个html页面,那么html页面内容就在body中
思考题:为什么HTTP报文中要存在"空行"
因为HTTP协议并没有规定报头部分的键值对有多少个,空行相当于"报头的结束标志"或者"报头和正文之间的分隔符".
HTTP在传输层依赖的是TCP协议,TCP是面向字节流的.如果没有空行,会出现粘包问题.
平时我们俗称的"网址"其实就是说的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当作特殊意义理解了.因此这些字符不能随意的出现
比如,在某个参数中需要带有这些特殊字符,就先对特殊字符进行转义.
转义的规则如下:将需要转码的字符转化为16进制,然后从右到左,取4位(不足的按4位处理),每两位做1一位,前面加上%,编码成%XY格式
"+"被转义成了"%2B","\"被转义成了"%5C"
方法 | 说明 |
---|---|
get | 获取资源 |
post | 传输实体主体 |
[注]:http其实有很多的方法,但是这两种是最重要,也是绝大多数时候用到的.
get是最常用的HTTP方法,常用于获取服务器上的某个资源
在浏览器中直接输入URL,此时浏览器就会发送一个get请求
另外,HTML中link,img,script等标签,也会触发get请求.
我们抓取一个搜狗主页的包,分析以下get请求的特点.
GET https://www.sogou.com/ HTTP/1.1
Host: www.sogou.com
Connection: keep-alive
Cache-Control: max-age=0
sec-ch-ua: "Microsoft Edge";v="113", "Chromium";v="113", "Not-A.Brand";v="24"
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/113.0.0.0 Safari/537.36 Edg/113.0.1774.50
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,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: https://cn.bing.com/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cookie: SUID=780395277050A00A0000000063A2F2CD; ssuid=8450928704; IPLOC=CN2102; cuid=AAEs48D8QwAAAAqgKmwzIgEANgg=; SUV=1680508908817178; SNUID=5143F881ABAE53C55547B0ABAC8AA1BE; LSTMV=257%2C179; LCLKINT=4516; ABTEST=4|1685002660|v17; browerV=3; osV=1
[get请求的特点]
post方法也是一种常见的方法,多用于提交用户输入的数据给服务器(例如登录页面).
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,like Gecko) Chrome/91.0.4472.77 Safari/537.36Access-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,Accept, X-Requested-With , yourHeaderFeildOrigin: 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: username=123456789; rememberMe=true{"username":"123456789","password":"xxxx","code":"jw7l","uuid":"d110a05ccde64b16a861fa2bddfdcd15"}
[post请求的特点]
经典面试题:谈谈get和post的区别
- 语义不同:get一般用于获取数据,post一般用于提交数据
- get的body一般为空,需要传递的数据通过query string传递,post的query string一般为空,需要传递的数据通过body传递
- get请求一般是幂等的,post请求一般是不幂等的(幂等:多次请求结构一样)
- get是可以被缓存的,post不能被缓存
补充说明
- 安全性:有些资料会说"post比get更安全"这个说法是不科学的,关键在于你的信息是否加密
- 传输数据量:有些资料会说"get传输的数据量小,post传输的数据量大",这个也不是科学的,标准中并没有规定get的URL的长度,也没规定post的body的长度.传输数据量的多少,完全取决于不同的浏览器和不同服务器之间的实现区别
传输数据类型: 有的资料上说 "GET 只能传输文本数据, POST 可以传输二进制数据". 这个也是不科学的. GET 的 query string 虽然无法直接传输二进制数据, 但是可以针对二进制数据进行 url encode
header的整体的格式是"键值对"结构
每个键值对占一行,键和值直接使用";"分割
报头的种类有很多,此处仅介绍几个常见的
标识服务器的主机的地址和端口
表示请求中body的数据长度
表示请求中body中的数据格式的类型
常见选项:
title=test&content=hello
{"username":"123456789","password":"xxxx","code":"jw7l","uuid":"d110a05ccde64b16a861fa2bddfdcd15"}
表示浏览器/操作系统的属性.形如
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Edg/113.0.1774.50
表示这个页面是从哪个页面跳转过来的.形如
Referer: https://www.jd.com/
如果直接在浏览器中输入URL,或者直接从收藏夹访问是没有Referer.
Cookie中储存了一个字符串,这个数据就是客户端(网页)自行通过JS写入的,也可能来自于服务器(服务器在HTTP响应的header中通过Set-Cookie字段给浏览器返回数据)
往往可以通过这个字段实现"身份标识"的功能
每个不同的域名下都可以有不同的Cookie,不同网站之间的Cookie并不冲突
【理解登录过程】
这个过程和去医院看病很相似的
- 到了医院先挂号,挂号的时候需要提供身份证,同时得到了一张“就诊卡”,这个就诊卡相等于患者的“令牌”
- 后序去各个科室进行检查,诊断,开药等操作,都不必再出示身份证了,只要就诊卡可识别出当前患者的身份。
- 看完病以后,不想要这个“就诊卡”,就可以注销这个卡。此时患者的身份和就诊卡的关联就销毁了(类似于网站的注销操作)
- 又来看病, 可以办一张新的就诊卡,此时就得到了一个新的“令牌”
状态码标识访问一个页面的结果。(是访问成功,还是失败,还是其他的一些情况)
状态码 | 解释 |
---|---|
200 | OK ,表示访问成功 |
404 | Not Found ,没有找到资源 |
403 | Forbidden ,表示访问被拒绝(原因:没有权限等原因,比如管理员才能访问的页面) |
405 | Method Not Allowed ,对方的服务器不一定支持所有的方法(请求的方法没有被实现,比如:没有实现PUT方法,发送的是PUT请求) |
500 | Internal Server Error ,服务器出现内部错误 |
504 | Gateway Timeout ,当服务器负载比较大的时候,服务器处理单条请求就会消耗较长的时间,就会导致超时状况 |
302 | Move temporarily ,临时重定向,资源临时被转移到别处,会再次发送HTTP请求访问新地址的资源 |
301 | Moved Permanently ,永久重定向,资源永久被转移到新的地址,后序的请求会被自动改成新的地址 |
大致可以分为以下几类:
类别 | 原因短语 | |
---|---|---|
1XX | Informational(信息性状态码) | 接收的请求正在处理 |
2XX | Success(成功状态码) | 请求正常处理完毕 |
3XX | Redirection(重定向状态码) | 需要附加操作以完成请求 |
4XX | Client Error(客户端错误状态码) | 服务器无法处理请求 |
5XX | Server Error(服务器错误状态码) | 服务器处理请求出错 |
响应中的Content-Type常见取值有以下几种:
form(表单)是HTML中一个常用的标签。可以用于给服务器发送GET或者是POST请求。
注意是form不是from,注意拼写!!
from的重要参数:
input的重要参数:
Document
注意:由于我们的服务器的地址是随便写的,随意提交后,会访问不到。
我们修改上面的代码,把form的method修改为POST即可
主要区别:
从前端角度,除了浏览器地址构造GET请求 ,form构造GET和POST之外,还可以通过ajax的方式来构造HTTP请求,并且功能更加强大。
ajax全程Asychronous Javascript And XML,是2005年提出的一种JavaScript给服务器发送HTTP请求的方式
js提供的原生ajax的api,这个api使用很不方便,我们使用jquery这种方式来使用ajax,jquery还可以使用“$"符来表示。
引入jquery的方式:
在其他语言中引入其他库是很难的,但是在html中我们只需要输入响应库的下载地址即可(链接)
Document
>
我们打开网页,会发现这是个空白页面或者是其他的不正常的东西(这个是关于跨域问题,是正常现象),我们打开F12,发现出现个报错,这个就是ajax的缺点,我们请求的东西,服务器不给我们响应。这种方法我们了解即可
我们使用postman进行构造HTTP请求,这个是相当简单的方法。
postman9.2.0下载地址:https://dl.pstmn.io/download/version/9.2.0/win64
中文补丁:Releases · hlmd/Postman-cn (github.com)
这个并不是最新版的postman,最新版的现在并没有中文补丁,我们下载9.2.0版本即可。如果对英文非常的了解可以下载最新版:Releases · hlmd/Postman-cn (github.com)
对应的不同版本的postman要使用响应的中文补丁(zip),不能混用。下载完之后,我们将中文补丁
重启postman,我们发现就是中文的了。
同时我们要关闭更新,这第一个目录下面删除update.exe文件,同时软件内设置禁止更新。
我们创建请求的时候我们点击+号即可创建请求,用postman创建各种HTTP请求是相当简单的。