💖 欢迎来阅读子豪的博客(JavaEE篇 🤴)
👉 有宝贵的意见或建议可以在留言区留言
💻 欢迎 素质三连 点赞 关注 收藏
🧑🚀码云仓库:补集王子的代码仓库
不要偷走我小火车哦~ ~ ~
HTTP协议目录
- HTTP协议
- Fiddler
-
- 查看详情
- HTTP请求报文格式
-
- HTTP方法
-
- GET 请求
- POST 请求
-
- GET 和 POST的区别
- URL
-
- URL类比
- Head
- Host
- length 和 Type
- UA(User-Agent)
- Refer
- Cookie
-
- Cookie从哪里来?
- Cookie存在哪?
- Cookie到哪里去?
- HTTP响应
-
- HTTP状态码
- HTTP 报文格式
- 构造 HTTP 求情
- GET
-
- POST
- ajax 异步(Asynchronous Javascript And XML)
-
- ajax使用
- postman
HTTP协议
HTTP (全称为 “超文本传输协议”) 是一种应用非常广泛的 应用层协议.
HTTP 诞生与1991年. 目前已经发展为最主流使用的一种应用层协议. 是应用层最广泛使用的协议之一,浏览器获取到网页,就是基于HTTP协议
HTTP1.0, HTTP1.1, HTTP2.0 均为TCP, HTTP3 基于 UDP 实现
HTTP是"浏览器"和"服务器"之间的桥梁
HTTP/1.1(1997-1999)是最常见的版本
浏览器发送 HTTP 请求,本质上就是给tcp Socket 里写了一个符合http格式的字符串给服务器,此http格式类似于tcp/udp报文格式(协议:组织数据的格式)
我们常见的例如 baidu.com 网址(URL),浏览器就会根据这个URL构造出一个HTTP请求,发送给服务器.服务器就会返回一个HTTP响应(包含了html,css,js,图片等),浏览器再把得到的html等数据进行显示出来(渲染)
http协议的交互详细过程,可以借助第三方的(抓包)工具来看到,这里展示最常用的fiddler(专注于http,使用起来更简单方便)
Fiddler
Download Fiddler Web Debugging Tool for Free by Telerik
下载 Fiddler Classic 经典版可以白嫖
启动过后会自动实时的抓包, 会立即显示出当前点脑上某应用程序使用http和服务器交互的过程
客户端有时候不方便直接访问服务器,就可以找一个代理间接的访问服务器,Fiddler相当于服务器和客户端中间的代理,代理分两种:
- 正向代理:代表着客户端的代理
- 反向代理:代表着服务器的代理
在使用 Fiddler 的时候要注意两个事项:
- Fiddler可能和别的代理程序冲突! 使用的时候要关闭其他的代理程序(包括一些浏览器插件)
- 需开启 HTTPS 功能才能正确抓包,https是基于HTTP研发出来的进化版协议,当前的互联网绝大部分服务器都是基于HTTPS研发的,Fiddler默认不能抓取https的包,
需要手动启用https并安装相应证书
注意:在首次使用 Fiddler 的时候,设置一下环境
勾选这几个复选框,Fiddler才能抓取https
首次勾选的时候会弹出会话框,问是否要安装对应的证书(英文)!!! 一定要勾选:是!!!
-
蓝色:html页面,在请求搜索过的首页页面,其他的请求都是基于这个请求产生的
-
绿色:js代码,
-
灰色 黑色:单纯返回数据
这些结果就是在浏览器访问百度页面的时候产生的http请求.浏览器打开一个页面,对应的http请求可能是一个,也可以是多个
查看详情
蓝色背景框内内容可能不方便看,用记事本打开
上述"红圆圈4" Raw 就是view in Notepad 用记事本打开此抓包数据
上面框里的数据是"求情数据",下面是"响应数据"
响应本来是文本格式,为了节省带宽,通常把数据进行压缩压缩,变成了二进制,我们想更直观的看就得解压缩弄成文本
HTTP请求报文格式
- 首行包含三个部分,之间使用空格分隔(下面以get报文演示), 例如 GET https://www.baidu.com/ HTTP/1.1
- GTE : HTTP的方法(method)
- https://www.baidu.com/ : URL俗称网址
- HTTP/1.1 : 版本号
- 请求头(header)
- 空行
- 正文(body)
GET 请求,一般没有body. POST请求,一般有body
空行后面是body,body里是程序员自定义的,想传什么由程序定
HTTP方法
方法描述了这次请求的语义(想干啥), 实际开发中,这里的方法,大部分都是用不到的.最常见的就是两个GET,POST
GET 请求
POST 请求
POST典型场景: 1. 登陆 2. 上传文件
GET 和 POST的区别
其实, GET和POST没有本质区别, 这只是一个习惯用法, GET和POST这两者在使用习惯上有差异
典型区别:
- LRU可见性差别
GET : 参数LRU可见;
POST : LRU参数不可见
- 数据传输上:
GET : 一般是从服务器读取数据通过拼接LRU (query string)进行传递参数;
POST : 一般是给服务器提交数据 通过body体传输参数
GET也不是不能有body, POST也不是不能有query string只是非常少见(在大部分场景下,彼此之间都能相互替代)只是在使用习惯上有差异
- 缓存性差别:
GET : 请求是可以缓存的
POST : 请求一般不能被缓存
缓存 : 把数据结果保存下来, 下次用的时候就直接读取缓存结果, 速度更快
- 后退页面的反应
GET : 请求页面后退时, 不产生影响
POST : 请求页面后退时, 会重新提交请求
- 传输数据的大小
GET : 一般传输数据大小不超过2k-4k(根据浏览器不同, 限制不一样, 但相差不大)
POST : 请求传输数据的大小根据php.ini 配置文件设定, 也可以无限大。
- 设计差别
- GET : 通常会被设计为幂等
- POST : 通常不要求幂等
幂等:输入的数据相同, 输出的结果是确定的稳定的
- 安全性差别
这个也是最不好分析的, 原则上POST肯定要比GET安全, 毕竟传输参数时LRU不可见, 但也挡不住部分人闲的没事在那抓包玩。安全性差别个人觉得是没多大区别的, 防君子不防小人就是这个道理。对传递的参数进行加密, 其实都一样。
- 数据包差别
GET产生一个TCP数据包;POST产生两个TCP数据包。对于GET方式的请求, 浏览器会把http header和data一并发送出去, 服务器响应200(返回数据);而对于POST, 浏览器先发送header, 服务器响应100 continue, 浏览器再发送data, 服务器响应200 ok(返回数据)。在网络环境好的情况下, 发一次包的时间和发两次包的时间差别基本可以无视。而在网络环境差的情况下, 两次包的TCP在验证数据包完整性差别上, 有非常大的优点。并不是所有浏览器都会在POST中发送两次包, Firefox就只发送一次。
URL
URL是唯一资源定位符(表示文件在哪个服务器的哪个目录下的哪个文件),表示互联网上的唯一的具体的资源的位置
而容易混淆的URI是唯一资源标识符,是身份标识,为了和别的资源区分开
实际上URL也可以起到身份标识的效果,URL也可以视为是一个URI,实际开发中经常把这两个词混用
首行如:GET https://www.baidu.com/s?tn=68018901_17_oem_dg&ie=utf-8&wd=%E7%99%BE%E5%BA%A6 HTTP/1.1
分为三部分:
- HTTP 的方法(method): GET
- URL: 俗称的网址https://www.baidu.com/s?tn=68018901_17_oem_dg&ie=utf-8&wd=%E7%99%BE%E5%BA%A6
- 版本号: HTTP/1.1
URL不是HTTP专属,很多协议都可以使用URL
URL最关键的四个部分:
- 域名/IP
- 端口号
- 带层次的路径
- 查询字符串
URL可以定位到网络上唯一资源
URL类比
IP 地址:端口号/带层次的路径?查询字符串(以键值对的方式来组织,键值用=连接, 两键值对用&)
如: 四川大学食堂:2号窗口/东北大饼?辣度=微辣&葱=多葱&香菜=加
一个URL有几个部分也是可以省略的
如: https://www.baidu.com/
此处就忽略了"端口号" (浏览器会提供默认的端口,对于http来说,默认端口80; 对于HTTP来说,默认端口是443)
Tips: 上述URL的" / "也是路径, 代表HTTP服务器的根目录, HTTP是服务器系统上的一个进程,委托这个服务器管理系统上的一个特定的目录(菜单), 这个目录里的资源都可以让外面进行访问
" / "管理的根目录, 可以是系统上的任意一个目录(基于HTTP服务器具体配置)
基于HTTP协议通信,约定好的数据交互的格式
url有些字符是有特定含义的, urIcode(转义)
如:%E7%99%BE%E5%BA%A6
就需要对内容进行URLcode重新编码需要借助%和十六进制数字来进行转义, 注意这里的URLcode不是字符集,而是转义工具, 如果不编码,直接写中文,可能浏览器就无法正确识别了
Head
每一行是一个键值对, 键和值用" : "分隔
这些键值对都是HTTP事先定义好的, 有特殊的含义
Host
大概描述了服务器所在的 地址 和 端口, 用来反映你最终想访问的目标, 这里内容跟URL差不多(如果是用的代理服务器间接访问就不一样)
length 和 Type
-
Content-Length : 表示 body中的数据长度.
-
Content-Type : 表示请求的 body 中的数据格式.
如果是GET请求,没body,请求中没有这两字段
如果是POST请求,有body,则必须要有这两字段
Content-Type取值有很多
文本的
- text/html
- text/cssimage/pngimage/jpg
应用程序的
- application/javascript
- application/json
…
UA(User-Agent)
描述当前用户浏览器和操作系统版本
用法例子 : 浏览器会获取这些数据,根据类别返回不同响应式页面(PC端 or 移动端)
Refer
描述当前页面的来源(如果直接通过地址栏输入地址, 或者直接点击搜藏夹 无法显示)
常用与浏览器广告, 买家与广告公司按点击广告次数计费, 买家可能在多个平台上部署广告, 就可以根据refer来判定是哪个平台提供了广告访问服务, 广告公司和买家都记录日志,最终进行核对
正常情况下是如此, 但在互联网发展的初期, 存在这"运营商劫持"的现象, 早期HTTP是明文传输, 很容易获取到请求内容,于是不法分子就对其数据进行了篡改, 本来是A公司提供了广告请求, 某些网络运营商就把refer被改成B公司, 就形成了"抢钱"行为, 于是后来为了避免此恶劣行为, 大家纷纷使用了更为安全的"HTTPS"
Cookie
cookie是非常重要的header属性
本质上是浏览器给网页提供的本地存储数据的机制
网页,默认是不允许访问你计算机的硬盘的!!(保证安全)
cookie浏览器对于访问硬盘做出了明确的限制
cookie就是通过键值对的方式来组织数据的
cookie以文件的形式放在硬盘上的
不同的域名里有不同的cookie
注意!! Cookie 中具体存啥内容?也就是程序猿自定 义的部分
Cookie是以键值对方式储存的, 键值之间用" = “连接, 键值对之间用” ; "分隔
Cookie从哪里来?
Cookie中的数据是来自于服务器的
服务器会通过HTTP响应的报头部分(Set-Cookie字段)获取Cookie, 由服务器来决定浏览器Cookie的内容
Cookie存在哪?
Cookie存在于硬盘中
Cookie在存储的时候,是按照 浏览器+域名维度 来进行细分的, Cookie里的内容不光是键值对还存有过期时间, 不同的浏览器,各自存各自的Cookie, 同一个浏览器不同的域名,对应不同的Cookie
Cookie到哪里去?
Cookie最终回到服务器里
通常一台服务器在同一时刻会对应多个客户端, 客户端这边就会通过Cookie来保存当前用户使用的中间状态, 当客户端访问浏览器的时候, 就会自动的把Cookie的内容带入到请求中, 服务器就能够知道现在客户端当前的状态了
Cookie里存的往往"上下文"这样的状态
当浏览器保存好Cookie之后
后续再给服务器发送请求的时候,就会自动带上这个Cookie, Cookie就像是服务器在浏览器这边搞的个寄存处一样, 存储客户端的前后状态
Tips :
浏览器保存账号密码是另外的功能,和 http协议 关联不大, 不要混淆
HTTP响应
打开Fiddler抓包, 上面框里是请求, 下面框里是响应
响应分为四个部分
- 首行
依次表示版本号/状态码 状态码描述 - header
- 空行
表示header的结束标记 - body
HTTP状态码
描述了这次响应的结果(成功/失败 原因)
常见的HTTP状态码(一下都是解压缩过后的状态码):
- 200 OK
这是一个最常见的状态码, 表示访问成功
- 404 Not Found
没有在服务器上找到资源
浏览器输入一个 URL, 目的就是为了访问对方服务器上的唯一资源. 如果这个 URL 标识的资源不存在, 那么就会出现 404
- 403 Forbidden
表示访问被拒绝, 没有权限
有的页面通常需要用户具有一定的权限才能访问(登陆后才能访问). 如果用户没有登陆, 直接访问, 就容易见到 403
- 405 Method Not Allowed
不支持此方法
常见的HTTP方法有 GET, POST, PUT, DELETE 等, 但是对方的服务器不一定都支持所有的方法(或者不允许用户使用一些其他的方法)
- 500 Internal Server Error
服务器出现内部错误
一般是服务器的代码执行过程中遇到了一些特殊情况(服务器异常崩溃)会产生这个状态码
- 504 Gateway Timeout
请求超时
当服务器负载比较大的时候, 服务器处理单条请求的时候消耗的时间就会很长, 就可能会导致出现超时的情况(例如双十一秒杀)
- 302 Move temporarily
临时重定向
需要客户端采取进一步的操作才能完成请求。后续的请求地址(重定向目标)在本次响应的 Location 域中指明。
就相当于手机号码中的 “呼叫转移” 功能, 访问这个网站, 这个网站不提供次服务但他"知道"谁可以提供就跳转到另一个网站, 在"登陆页面"中经常会见到 302. 用于实现登陆成功后自动跳转到主页, 响应报文的 header 部分会包含一个 Location 字段, 表示要跳转到哪个页面
- 301 Moved Permanently
永久重定向
当浏览器收到这种响应时, 后续的请求都会被自动改成新的地址
301也是通过 Location 字段来表示要重定向到的新地址
HTTP状态码
简单来看, 大致分为这么几个种类
2** 成功
3** 重定向
4** 客户端错误
5** 服务器错误
HTTP 报文格式
构造 HTTP 求情
GET
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- from表单标签,允许用户与服务器之间交互数据 , 要求提交的数据以键值对的结构来组织 -->
<form action="https://www.baidu.com" method="get">
<input type="text" name="studentName">
<!-- 点击按钮触发form表单的提交操作, 构造HTTP请求发给服务器 -->
<input type="submit" value="提交">
</form>
</body>
</html>
POST
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- from表单标签,允许用户与服务器之间交互数据 , 要求提交的数据以键值对的结构来组织 -->
<form action="https://www.baidu.com" method="post">
<input type="text" name="studentName">
<!-- 点击按钮触发form表单的提交操作, 构造HTTP请求发给服务器 -->
<input type="submit" value="提交">
</form>
</body>
</html>
从text 文本中可以看出post请求里没有querystring键值对, 但body里的数据格式和querystring很类似都是键值对形式存在
ajax 异步(Asynchronous Javascript And XML)
上述 form 标签,只能构造GET和POST,无法构造PUT,DELETE,OPTIONS等方法的请求, 想要构造更多的请求得借助浏览器提供的一种基于 js 功能更多的HTTP请求构造方式," ajax"
注意观察ajax的名字 熟悉的sychronize前面加了个"a", 这个a就代表"异步"
A等待B
同步:A一直关注着B, 直到B就绪
异步:A不一直关注B, 等B就绪之后主动通知A
html 中,通过 ajax 发起 http 请求, 就属于"异步"的方式
当一行代码执行"发送请求"操作之后, 不必等待服务器响应回来, 就可以立即先往下执行, 当服务器的响应回来了之后, 再由浏览器通知到咱们代码中, 类似于"懒汉模式"
ajax使用
- js 原生提供ajax的api, 但是原生api特别难用
- jquery 提供的 ajax, api针对原生api的封装,简单很多(这里我们介绍这个)
在网上找到 jQuery 的原码 引入
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
jquery中,$ 是一个特殊的全局对象, jquery 的 api 都是以$的方法的形式来引出的
<script>
$.ajax();
</script>
用ajax发送请求例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 引入jQuery -->
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
<script>
$.ajax({
// 定义参数
type: 'get',
url: 'https://www.baidu.com?studentName=YZH',
// success函数是声明一个回调函数, 会在服务器响应返回的时候触发该函数
// 此处的"回调"就体现了"异步"
success: function(data){
console.log("触发回调函数")
}
});
console.log("浏览器立即执行后续的代码");
</script>
</body>
</html>
报错正常, 因为目标服务器没有对我们的请求作出相应
Tips:
如果构造了多组ajax请求, 发送出去的顺序依照代码编写顺序, 但是收到相应/回调的顺序依照网络来定
js直观上看没有多线程, 但内核中应该还是涉及到了的
如果是发送请求之前,就出异常了,异常在主线程中的话,此时无法继续执行后面的代码
如果是发送请求之后,异常出现在响应的回调里,就是另外的回调线程异常不影响主线程
同form表单相比, ajax功能更强
- 支持 put, delete等方法
- ajax发送的请求可以灵活设置header / body
postman
接下来我们写几组测试数据看看效果, 这里会用到更简单的构造HTTP请求的第三方工具postman
我们每次请求数据后,可以按Save或者Ctrl + S将请求保存到云端