目录
1. HTTP 协议
1.1 HTTP 协议格式
HTTP 协议是服务器与客户端之间通信模式中的一问一答的方式,请求和响应是一一对应的.
🍃1.左侧窗口显示了所有的 HTTP请求/响应, 可以选中某个请求查看详情.
🍃2.右侧上方显示了 HTTP 请求的报文内容 . ( 切换到 Raw 标签页可以看到详细的数据格式 )🍃3.右侧下方显示了 HTTP 响应的报文内容 . ( 切换到 Raw 标签页可以看到详细的数据格式 )🍃4.请求和响应的详细数据 , 可以通过右下角的 View in Notepad 通过记事本打开 .
Fiddler 相当于是一个 "代理" ,在中间传话.如果电脑上还有其他的代理程序,就可能会导致 Fiddler 无法正常工作.
【响应乱码?】
我们之前学过的 TCP,UDP,IP 这些都属于 "二进制协议", 协议中的数据,是以二进制的方式来组织的,如果拿记事本打开,里面就会出现一堆乱码,而 HTTP 则是 "文本协议", 所以用记事本打开不会出现乱码.
但是为什么返回来的响应也可能出现乱码的现象呢?
因为网络上传输的数据是可以进行压缩的,对于 HTTP 来说, 请求数据数据一般比较简短,就不必压缩,响应数据可能会比较长!! 通过压缩就可以节省传输的带宽.
Fiddler 内置了加压缩功能,如果出现乱码的时候,我们可以点击右侧中间部分,就可以进行解压缩了:
1.2 HTTP 请求 (Request)
HTTP请求分为四个部分, 就拿 Fiddler 抓到的包来分析:
🍁首行: 请求的第一行
首行分为三个部分,中间使用空格分割.
🍁请求报头 header
中间这一段都是请求报头,header 里面都是 "键值对" ,并且这里的键值对都是有固定含义的,每一行都是一个键值对,键和值之间用 冒号,空格 来分割.
🍁空行 - 结束标记
仔细观察 Fiddler 抓到的那张图,可以发现中间有一行是空着的,这是请求报头 (header) 的结束标记. 报头里有多少个键值对 (有多少行? ),是不确定的.遇到空行就认为是结束了.
🍁正文 (body)
我们可以看到这里是通过 json 来组织的, 格式化之后观察的更清楚:
1.2.1 认识 URL
🍃1.http: 协议名,常见的有 http 和 https, 也有其他的类型. (例如访问 mysql 时用的
jdbc:mysql )🍃2.登录信息:历史遗留下来的,现在的网站一般都没有这个了🍃3.服务器地址:此处是一个 " 域名 ", 域名会通过 DNS 系统解析成一个具体的 IP 地址 .🍃4.端口号:IP 确定主机后,还需要知道地址上对应的应用程序是啥,就可以通过端口号来区分。如果端口号被省略了,就会按照对应的默认值:http:// 默认端口 80 https:// 默认端口是443.🍃5.带层次的文件路径:一个应用程序下,可能管理着很多的资源,一次请求,只能访问一个具体的资源.具体访问哪一个资源,就需要通过带层次的文件路径来明确.🍃6.查询字符串: 请求发给服务器时带上的一些 "参数" , ? 作为查询字符串的起始标志, ?后面的内容就是查询字符串的本体了,通过键值对的方式进行组织.键值对之间用 & 来分割, 键和值之间使用 = 来分割. 键值对里面的含义,咱们是不清楚的,是由程序员自定义的. (查询字符串,,就给咱们写代码的时候留下了一些自定义的空间,就可以根据需求,来实现一些特定的效果了.)🍃7.片段标识符:有些 "文档类" 网站有,起到页面内部跳转的效果,定位到一个网页的某个章节.
1.2.2 关于 URL encode
URL 里面有一些符号,带有特定的含义,如果在 query string 中也出现同样的符号,此时就容易产生误会!! 此时就需要把这些特殊符号进行 "转码", 就叫做 URL encode.
类似的像 %2B%2B 这种符号就是 + 这个 URL encode 之后得到的内容.
这个 URL encode 操作是非常有意义也是有必要的, 如果查询字符串中带有了特殊符号, 就很容易导致浏览器对 URL 解析失败,可能无法跳转到对应的页面.
1.2.3 认识 "方法" (method)
掌握前两个最重要的: GET, POST
🍁GET
GET 是最常用的 HTTP 方法. 通常用于获取服务器上的某个资源. 在浏览器中直接输入 URL, 此时浏览器就会发送出一个 GET 请求. 另外, HTML 中的 link, img, script 等标签, 也会触发 GET 请求.
(虽然建议 GET 用于获取资源, 但实际使用的时候,也不一定完全遵守,也可以使用 GET 让服务器新增一个数据/删除一个护具/修改一个数据, 具体还要看代码怎么写的. )
GET 请求的特点:
-
首行的第一部分为 GET
-
URL 的 query string 可以为空 , 也可以不为空
-
header 部分有若干个键值对结构 .
-
body 部分为空 .
网上有些说法 : get 请求长度最多为 1024kb, 这样的说法是错误的 .HTTP 协议 RFC 2616 标准里 , 明确说明 : "Hypertext Transfer Protocol -- HTTP/1.1," does not specify any requirement for URL length.没有对 URL 的长度有任何的限制 . 实际 URL 的长度取决于浏览器的实现和 HTTP 服务器端的实现 . 在浏览器端 , 不同的浏览器最大长度是不同的, 但是现代浏览器支持的长度一般都很长 ; 在服务器端 , 一般这个长度是可以配置的 .
POST 方法也是一种常见的方法 . 通常 用于提交用户输入的数据给服务器 (登录,上传文件 ).通过 HTML 中的 form 标签可以构造 POST 请求 , 或者使用 JavaScript 的 ajax 也可以构造 POST 请求 . (也可以使用 POST 来 获取/删除/修改 数据,并不是绝对的)
- 首行的一个部分是 POST
- URL 里通常没有 query string
- 通常没有 body
浏览器和服务器交互的时候,总是需要传递一些数据给服务器的。在提交的过程中,相关的信息,可以放到 query string 里,也可以放到 body 中。query string 是固定的键值对格式,body 中则是可以使用更多的格式来组织。
GET 和 POST 二者没有本质区别,彼此之间是可以相互替代的,但是使用习惯上还是存在区别的。 主要掌握前两点区别:🍃1.GET 通常用来获取数据,POST 通常用来给服务器提交数据。(习惯用法)🍃2.GET 主要通过 query string 来传递数据,POST 则是使用 body 传递数据。(习惯用法)🍃3.GET 请求一般建议实现成 "幂等的",POST 则不要求 "幂等"。(如果多次输入的内容相同,多次得到的结果也完全相同,称为 "幂等")(习惯用法)🍃4.GET 一般是可以被缓存的 / 可以放到收藏夹中的,而 POST 一般不要求被缓存 / 不能放入收藏夹。(习惯用法)
1.2.4 常见的报头种类
🍔HOST : 表示服务器主机的地址和端口.
Content-Length 和 Content-Type 要搭配 body 使用.
我们在学 TCP 的时候, 知道 TCP 是一个面向字节流的协议, 所以务必要明确数据报和数据报之间的边界, 否则就会出现 "粘包问题". 而 HTTP 也是基于 TCP 的, 当 HTTP 报文带有 body 的时候就需要显示的明确出, body 到哪是结束.
明确边界
- 要么指定长度 (Content-Length)
- 要么是指定分隔符 (空行...)
- (Windows NT 10.0; Win64; x64) 表示操作系统的信息.
- AppleWebKKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36 表示浏览器信息.
由于现代的浏览器: chrome, edge, Safari, 已经差距很小了, 所以现在 UA 起到的作用, 主要是区分, 请求是来自于 PC 还是移动端. (操作系统), 但也不是很准.
Referer 不一定 100% 有, 主要还是看从哪个页面跳转过来, 如果是直接从浏览器地址栏输入或者直接点击收藏夹, 那么就不会有 Referer.
【Referer 的用处?】
当用户在浏览器 (搜狗) 点击广告的时候, 广告主就得给广告平台付钱 (几块,几十 或者 上百), 相当于是搜狗给广告主的网站引流了 (让更多的人访问到这个网站).
那么搜狗是如何计费的呢?
按照点击次数计费. 当然要根据投入产出比来看 (ROI) , 每次点击让搜狗赚钱, 也得让广告主赚钱,所以故意点击是不生效的, 搜狗会有严格的 "反作弊" 策略. 这个广告被点击了多少次, 搜狗和广告主双方都要计算. 搜狗这里每次点击都会先跳转到搜狗的费服务器; 而广告主的网站也有日志, 网站中哪些请求 referer 是来自于搜狗的.
referer 是否可以被更改? 有些 referer 不是搜狗的, 搜狗是否有办法, 把这些 referer 给改成自己?
在 2015 年之前, 这种情况是存在的, 当然搜狗自己改不了 referer, 但是网络运营商可以做到, 因为你所有的网络访问操作, 都是要经过人家运营商的设备的, 因此网络运营商有能力, 解析出你的请求的内容,并且篡改其中的内容的. (运营商劫持), 网络运营商也有自己的广告平台, 也想给自己增加一些收益, 这就相当于是 "明抢", 那么抢流量算犯法吗? 在当时, 法律上还没有明确的定义. 后来, 搜狗, 百度, 神马这些大厂考虑利益关系, 选择技术上反制, 那就是使用 HTTPS. (虽然打官司能赢,但是赢了官司,输了买卖)
使用 HTTPS 加密的效果: 1.让运营商劫持, 进行破解, 提高了难度. 2. 即使破解了,进行篡改, 客户端浏览器也是容易识别出篡改的结果.
2015年之后, 这些搜索公司就纷纷升级为 HTTPS 了.
当我们使用浏览器去访问页面的时候, 一个用户的相关数据信息都是在服务器里存储, 有的时候, 我们希望在浏览器这边也能存下来, 简化一些操作. 最典型的需要在浏览器这里存储的, 就是用户的身份信息, 这样就可以避免反复重复的进行登录.但是浏览器为了保证用户的安全, 浏览器针对页面上运行的代码, 做出了很多的限制. 最典型的, 就是禁止浏览器页面代码 访问本地磁盘. (如果不限制,后果非常严重, 可能会导致你访问一些网站,不小心就把你本地磁盘清空了)如果浏览器不让你访问磁盘. 你要想持久化的在浏览器这边保存一些信息,又得访问磁盘, 所以大家各退一步.
- 浏览器不是完全将你限制死, 允许页面在限定条件下, 能够使用一点点,但是不能访问到磁盘的其他文件.
- 同时页面代码, 也不能任意存储数, 只能存储简单的键值对.
浏览器查看 Cookie:·
浏览器为了进一步的保证安全, 就会将这些 Cookie 分别存放, 每个网站(每个域名)有一组自己的 cookie,彼此之间不干扰. 而且页面代码只能存储和修改 cookie 这样的简单键值对.
【问题】Cookie 的内容从哪来? 到哪去?
从哪来?
Cookie 的内容, 从服务器来, 网页上面主要的数据存储仍然是在服务器上的, 数据也就是从服务器写回给浏览器的
到哪去?
从服务器来的内容再传回给服务器. 例如网站登录之后, 明确了用户的身份信息, 就把身份标识返回给了浏览器. 浏览器下次访问服务器的时候, 就会带着身份标识, 服务器就可以认出用户是谁了.
Cookie 里面的键值对内容是啥含义?
是由程序员自定义的. 只有实现这里功能的程序员才知道.
🍁使用抓包工具演示 Cookie 内容的来去:
【登录前的请求】
【响应】
【登录后的请求】
当我们清空浏览器中的 Cookie 时, 再次登录, 并抓包时, 会发现请求里面是没有 Cookie 的. 此时在响应中可以看到 Set-Cookie, 而 Set-Cookie 的效果 就是服务器给客户端写 Cookie. 当响应来到浏览器这边时, 登录后的请求中的 header 里就出现了 Cookie . 浏览器保存了这些 Cookie 后, 就会在后续的请求中, 带上这个 Cookie 内容.
举例理解上述流程:
假设张三第一次去某医院, 他先要办理一个就诊卡. 办理就诊卡的时候, 就要将身份证给工作人员验证你的身份信息, 此时医院这边就会在医院系统中建立一个患者的档案, 然后给张三一张就诊卡. 就诊卡里保存了当前这个用户的身份标识 (id), 通过 id 就可以在患者的档案中查询出具体的信息, 例如姓名, 年龄, 性别, 以往病史....
上述建档的过程,, 就是浏览器首次访问网站的时候, 网站进行身份验证, 生成对应的信息, 并返回一个身份标识给浏览器的 Cookie 中. 接下来, 张三要去外科, 内科或者影视科看病时, 就只要刷卡, 医生就可以知道他的既往信息了.
除了就诊卡之外, 这些信息都是保存在医院的系统中的, 医院的系统针对张三, 建立的这份档案, 就成为 "会话" - session, session 就相当于银行的保险柜, 里面存了很多钱; 而 Cookie 就相当于一张银行卡, 通过银行卡就可以找到对应的保险柜, 从而把钱取出来.
很多时候, Cookie 和 session 是要搭配使用的, 但也不绝对, 单独的 Cookie 也有用, 不一定保存身份信息, 也可以随意保存程序猿想要保存的信息, 单独的 session 也有用....
1.2.5 HTTP 请求中正文的数据格式
🍃1. json.🍃2.urlencoded. 格式就和 query string 是一样的. (键值对, 键和值之间使用 & 分割, 键和值之间使用 = 分割)🍃3.form-data. 等等.....
结合抓包工具理解....
1.3 HTTP 响应 (Response)
响应也是分为四个部分,结合下图进行分析:
🍁 首行:响应的第一行
使用空格对首行分割成三部分
🍁响应报头 header
同样也是键值对结构.
🍁空行 - 结束标记
响应报头的结束标记.
🍁正文 (body)
正文不一定是 JSON 格式,也可以是 CSS ,JS 或者 图片等.
1.3.1 认识 "状态码"
响应首行中的 "200 就是状态码, OK 则是状态码描述.
🍁常见的状态码
- 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
临时重定向. 就相当于手机号码中的 "呼叫转移" 功能. (假如我换号码了,
我去办理一个呼叫转移的业务,其他人拨打我的旧号码时, 就可以自动转移到我的新号码)
在登陆页面中经常会见到 302. 用于实现登陆成功后自动跳转到主页.
响应报文的 header 部分会包含一个 Location 字段, 表示要跳转到哪个页面.
- 301 Moved Permanently
永久重定向. 当浏览器收到这种响应时, 后续的请求都会被自动改成新的地址.
301 也是通过 Location 字段来表示要重定向到的新地址.
🍁状态码分类
1.3.2 认识响应 "报头" (herder)
🍔Content-Type
HTTP 响应中 Content-Type 和 HTTP 请求中的 Content-Type 差别还是挺大的.
响应中的 Content-Type 常见取值有以下几种:
- text/html : body 数据格式是 HTML
- text/css : body 数据格式是 CSS
- application/javascript : body 数据格式是 JavaScript
- application/json : body 数据格式是 JSON
除了以上四种, 还可以是图片等等, 取值种类很多, 主要还是看返回的响应数据是什么.
1.3.3 认识响应 "正文" (body)
其他格式都可以通过抓包工具来查看, 要注意的是, 有的时候写代码要手动指定字符编码, 保证返回的内容, 不是乱码!
1.4 通过 form 表单构造 HTTP 请求
1.4.1 form 发送 GET 请求
<form action="https://www.sogou.com/index.html" method="get">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit" name="发送">
</form>
当我们运行这个代码, 并输入类容, 按下提交键后, 此时就会构造出 HTTP 请求并发送给服务器.
使用抓包工具查看:
1.form 的 action 属性对应 HTTP 请求的 URL2.form 的 method 属性对应 HTTP 请求的方法3.input 的 name 属性对应 query string 的 key4.input 的 内容 对应 query string 的 value
1.4.2 form 发送 POST 请求
上述代码只修改 method ,将其改为 POST.
<form action="https://www.sogou.com/index.html" method="post">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit" name="发送">
</form>
还是原来的页面:
使用抓包工具查看:
主要区别:
1.method 从 GET 变成了 POST2.数据从 query string 移动到了 body 中 .
当使用 GET 的方式提交的时候, 用户名和密码就显示到浏览器地址栏中了, 容易被别人一眼就瞄走了. 所以一般登录都是基于 POST 实现.那么是不是就认为 POST 比 GET 更安全呢?这种说法是不成立的!! 保证安全的关键, 是针对密码进行加密. 而不是放到 body 里, 就认为不能直接看到就算安全; 放到 body 中, 如果不加密的话, 虽然浏览器不能直接显示, 但是随便一抓包, 就抓出来了, 也是掩耳盗铃.
1.4.3 通过 ajax 构造 HTTP 请求
ajax 是一个更强大, 更灵活的构造 HTTP 请求的方式.
ajax 全称 Asynchronous Javascript And XML
浏览器和服务器之间异步交互数据的方式.
此处的 Asynchronous 的 是 "异步" 的意思, 和学习多线程中的 "同步" , "异步" 不是一回事, 此处的 "同步", "异步" 描述的是进行 IO 操作的时候, 结果是发送方自己来主动获取, 还是接收方把结果推送给发送方.
- 准备 jQuery:
ajax 是浏览器给 JS 提供的一个和服务器交互数据的机制, 浏览器就提供了一组原生的 API - XMLHttpRequest, 但是这个东西用起来非常不方便, 于是很多第三方库, 就针对 ajax 进行了封装, 最典型的就是 jQuery.我们使用 ajax 构造 HTTP 请求时, 在写代码之前, 要先加载 jQuery, 然后才能编写 jQuery 相关的代码. 加载 jQuery 时, 建议把 jQuery 文件内容拷贝到本地.
- 使用 jQuery 构造请求 (认识 ajax 代码的基本形式)
<script src="jquery.min.js"></script>
<script>
$.ajax({
type: 'GET',
url: 'http://www.baidu.com',
// data: '这是 body 部分的内容, 可以没有'
success: function(body) {
// 参数 body 表示 HTTP 响应的 正文部分
console.log(body);
}
});
</script>
🍃1. ajax 函数中使用对象作为参数, 这样做的好处是让这些参数是自解释的, 同时参数顺序都没有限制, 参数有和没有都很灵活.
🍃2.为啥 ajax 叫做 "异步", 就是在上述代码中的回调函数 (success: function(body) {}) 里体现出来的. 向服务器发送请求的程序员, 只管发送, 不必主动去获取结果, 等到结果回来, 浏览器自然会来通知咱们, 然后触发回调函数.
程序运行结果:
会发现控制台里会报错, 这个报错是一个典型的 "跨域" 问题. 当前上述代码的 HTML 对应的 "域名" 是一个本地路径, 而 ajax 访问的请求, 是百度的服务器. 可以理解为 "张家人莫管李家事".
张家的页面, 想要通过 ajax 访问李家的服务器, 默认是不允许的!! 这个操作就称为 "跨域". 浏览器为了保证网络安全, 禁止 ajax 的跨域访问.
但是跨域操作也不是 100% 禁止的, 只要百度服务器支持, 我就可以跨域访问. 由于我和百度不是 "儿女亲家" 关系, 百度自然不会允许我跨域访问. 后期等我学会自己搭建一个自己的服务器, 再来使用 ajax 演示程序的执行效果.
本篇博客就到这里了, 谢谢观看!!