目录
一、HTTP 协议是什么
二、HTTP协议格式
1.抓包工具的使用(以 Fiddler 为例)
2. 抓包工具的原理 (以 Fiddler 为例)
3. 抓包结果
① HTTP 请求(request)
②HTTP响应(response)
三、HTTP 请求(request)
1.URL
①URL 基本格式
② 关于 URL encode
2. HTTP 方法
①GET 方法
②POST方法
③其他方法
3.认识请求(request)报头(Header):
① Host
② Content-Length
③ Content-Type
④ User-Agent(简称 UA)
⑤ Referer
⑥ Cookie
4.认识请求(request)正文(body)
四、HTTP 响应
1.认识状态码
① 200 OK
② 404 Not Found
③ 403 Forbidden
④ 405 Method Not Allowed
⑤ 500 Internal Server Error
⑥ 504 Gateway Timeout
⑦ 302 Move Temporarily
⑧ 301 Moved Permanently
⑨ 状态码小结
2.认识报头(Header)
Content-Type
3.认识响应(response)正文(body)
哥几个来学 HTTP 协议 啦 !!!!!!!
HTTP (全称为 "超文本传输协议") 是一种应用非常广泛的 应用层协议。
所谓 “超文本” 的含义,就是传输的内容不仅仅是文本(比如 html,css 这个就是文本),还可以是一些 其他的资源,比如图片,视频,音频等二进制的数据。
我们平时打开一个网站, 就是通过 HTTP 协议来传输数据的:
当我们在浏览器输入一个 CSDN的“网址”(URL)时,浏览器就给 CSDN 的服务器发送了一个 HTTP 请求,CSDN 的服务器返回了一个 HTTP 响应。
这个响应结果被浏览器解析之后,就展示成我们看到的页面内容。(这个过程中,浏览器可能会给服务器发送多个 HTTP 请求,服务器会对应返回多个响应,这些响应里就包含了页面 HTML,CSS,JavaScript,图片,字体等信息)
TP 是一个文本格式的协议。可以通过 Chrome 开发者工具或者 Fiddler 抓包,分析 HTTP 请求/响应 的细节。
左侧窗口:显示了抓到的所有 HTTP请求/响应,可以选中某个请求查看详情。
右侧上方:显示了 HTTP 请求的报文内容。(切换到 Raw 标签页可以看到详细的数据格式)
右侧下方:显示了 HTTP 响应的报文内容。(切换到 Raw 标签页可以看到详细的数据格式)
直接抓取的HTTP响应的话,我们看到的响应报文都是乱码:
原因是在网络传输中,响应数据一般较大,二宽带的资源是非常宝贵的的 ,为了尽可能地减少带宽资源的消耗,HTTP对正文部分进行了压缩。
Content-Encoding: gzip 这个键值对表示正文部分是压缩状态:
点击 "Response body is encoded.Click to decode." 即可解压缩:
请求和响应的详细数据,可以通过右下角的 View in Notepad 通过记事本打开:
Fiddler 相当于一个 “代理”。
浏览器访问 CSDN 时,就会把 HTTP 请求先发送给 Fiddler,Fiddler 再把请求转发给 CSDN 的服务器,当 CSDN 服务器返回数据时,Fiddler 拿到返回数据,再把数据交给浏览器。
因此,Fiddler 对 浏览器 和 CSDN 服务器之间的交互的数据细节,是非常清楚的。
以下是一个 HTTP 请求:
一个 HTTP 请求包含了 4 个部分:
首行:方法 + url + 版本
Header(报头):请求的属性,冒号 “:” 分隔的键值对;每组属性之间使用换行 “\n” 分隔;遇到空行表示 Header 部分结束。
空行:因为 HTTP协议 并没有规定报头部分的键值对有多少个,空行就相当于是 “报头的结束标记”,或者是 “报头和正文之间的分隔符”。
HTTP 在传输层依赖 TCP协议,TCP 是面向字节流,如果没有这个空行,就会出现 “粘包问题”。
Body(正文):空行后面的内容都是 Body。Body 允许为 空字符串。如果 Body 存在,则在 Header 中会有一个 Content-Length属性来标识 Body 的长度。
首行:版本号 + 状态码 + 状态码解释
Header(报头):同 HTTP 请求 一样。
空行:同 HTTP 请求 一样
Body(正文):空行后面的内容都是 Body。Body 允许为 空字符串。如果 Body 存在,则在 Header 中会有一个 Content-Length属性来标识 Body 的长度。如果服务器返回了一个 HTML页面,那么 HTML 页面内容就是在 Body 中。
一个 HTTP 请求(request):
平时我们俗称的 "网址" 其实就是说的 URL (Uniform Resource Locator 统一资源定位符)。
互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。
一个具体的 URL:
https://v.bitedu.vip/personInf/student?userId=10000&classId=100
URL 有一些部分是可以省略的,可以看到,在这个 URL 中有些信息被省略了。
关于查询字符串(query string):
query string 中的内容是键值对结构。其中的 key 和 value 的取值和个数,完全都是程序猿自己约定的。我们可以通过这样的方式来自己定制传输我们需要的信息给服务器。
URL 中的可省略部分:
- 协议名 :可以省略,省略后默认为 http://
- ip 地址 / 域名 :在 HTML 中可以省略(比如 img, link, script,a 标签的 src 或者 href 属性)。省略后表示服务器的 ip / 域名与当前 HTML 所属的 ip / 域名一致。
- 端口号 :可以省略。省略后如果是 http 协议,端口号自动设为 80;如果是 https 协议, 端口号自动设为 443 。
- 带层次的文件路径 :可以省略。省略后相当于 / 。 有些服务器会在发现 / 路径的时候自动访问 /index.html
- 查询字符串 :可以省略
- 片段标识 :可以省略
使用 ping 命令查看域名对应的 IP 地址:
1. 在开始菜单中输入 cmd,打开 命令提示符。
2. 在 cmd 中输入 ping www.sogou.com ,即可看到域名解析的结果:
像 '/' 、 '?' 、 ':' 等这样的字符,已经被url当做特殊意义理解了。因此这些字符不能随意出现。
比如,某个参数中需要带有这些特殊字符,就必须先对特殊字符进行转义。
一个中文字符由 UTF-8 或者 GBK 这样的编码方式构成,虽然在 URL 中没有特殊含义,但是仍然需要进行转义。否则浏览器可能把 UTF-8/GBK 编码中的某个字节当做 URL 中的特殊符号。
转义的规则如下:将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一 位,前面加上%,编码成%XY格式。(了解即可)
"+" 被转义成了 "%2B"
urldecode就是urlencode的逆过程。
HTTP的方法只存在于请求之中,方法有很多,但是常用的只有两个 --- GET 方法 和 POST 方法。
GET 是最常用的 HTTP方法,常用于获取服务器上的某个资源,也就是从服务器上拿取什么东西。
我们在浏览器中直接输入 URL 时,浏览器就会发送一个 GET 请求。
另外,HTML 中的 link、img、script 等标签,也会触发一个 GET 请求;使用 JavaScript 中的 ajax 也能构造 GET 请求。
使用 Fiddler 观察 GET 请求:
我们打开 搜狗
观察抓包结果:
GET 请求的特点:
关于 GET 请求的 URL 长度问题:
URL 的长度没有任何限制。
实际 URL 的长度取决于浏览器的实现和 HTTP 服务器的实现。在浏览器端,不同的浏览器最大长度是不同的,但是现代浏览器支持的长度一般很长。在服务器端,这个长度是可以配置的。
谢灵运说过:天下文才十斗,曹子建独占八斗,我占一斗,余者天下共分之。
这就像 HTTP 里的方法一样:天下 HTTP方法十斗,GET方法 独占八斗,POST 占一斗,余者其他 HTTP方法 共分之。
这足以说明 GET方法之重要!!!
POST 方法也是一种常见的方法,多用于提交用户输入的数据给服务器(例如登陆页面输入账号密码)。
通过 HTML 中的 form 标签可以构造 POST 请求,或者使用 JavaScript 也可以构造 POST 请求。
使用 Fiddler 观察 POST 方法:
POST 请求的特点
经典面试题:请谈谈 GET方法 和 POST 方法的区别。
遇到这题首先要答:GET方法 和 POST 方法 本质上没有区别。
为什么没有本质区别呢?
原因是 使用 GET 的场景替换成 POST 一般也可以;使用 POST 的场景替换成 GET 一般也可以。
但是使用习惯不同
补充说明:
- 关于幂等性: 标准建议 GET 实现为幂等的. 实际开发中 GET 也不必完全遵守这个规则(主流网站都有 "猜你喜欢" 功能, 会根据用户的历史行为实时更新现有的结果.
- 关于安全性: 有些资料上说 "POST 比 GET 请安全". 这样的说法是不科学的. 是否安全取决于前端在传输密码等敏感信息时是否进行加密, 和 GET POST 无关.
- 关于传输数据量: 有的资料上说 "GET 传输的数据量小, POST 传输数据量大". 这个也是不科学的, 标准没有规定 GET 的 URL 的长度, 也没有规定 POST 的 body 的长度. 传输数据量多少, 完全取决于不同浏览器和不同服务器之间的实现区别.
- 关于传输数据类型: 有的资料上说 "GET 只能传输文本数据, POST 可以传输二进制数据". 这个也是不科学的. GET 的 query string 虽然无法直接传输二进制数据, 但是可以针对二进制数据进行 url encode.
这些方法的 HTTP 请求可以使用 ajax 来构造。(或者第三方工具)
任何一个能进行网络编程的语言都可以构造 HTTP 请求。本质上就是通过 TCP socket 写入一个符合 HTTP 协议规则的字符串。
一个 HTTP 请求(request)报头(Header):
Host 表示服务器主机的端口和地址。
大多数情况下 Host 的值 和 url 的值是一致的,但是如果使用一些“代理应用”(比如某些加速器之类的),此时 Host(表示最终目标) 和 url(表示当前目标) 就会不同。
描述了 body 的长度(单位:字节)
欸?那为什么上方图片上没有 Content-Length 呢?
原因是在 Get 方法中通常是没有 body 的,那么既然没有 body 了,Content-Length 自然就可以省略了~~
描述了 body 的数据格式。
常见选项:
关于 Content-Type 的详细情况:MIME types (IANA media types) - HTTP | MDN (mozilla.org)
同理,上方图片上没有 Content-Type 的原因也是因为 Get 方法中通常是没有 body 的~~
如果方法是 POST (有 body 的情况下),那么 就会有 Content-Type 了:
表示浏览器/操作系统的属性。
User-Agent 的一个重要作用就是区分用户是 PC/平板/手机~~
表示这个页面是从哪个页面跳转过来的。形如:
这个就是我在 百度搜索 上点进 搜狗搜索 得来的。
但是如果我直接在浏览器上输入网址(url):
或者在收藏栏里点击:
就不会有 Referer
Cookie 直接翻译称为:曲奇饼。但是在网络上可与这种 小甜饼干 没有半毛钱关系~~
Cookie 中存储了一个字符串,这个数据可能是客户端(网页)自行通过 JS 写入的,也可能来自于服务器( 服务器在 HTTP 响应的 header 中通过 Set-Cookie 字段给浏览器返回数据 )
Cookie 的值也是由键值对组成的:
键与值之间用“=”分隔;键值对之间用“;”分隔。
这里的键值对是由程序员规定的,不同的网站有不同的 键值对,也就有不同的含义和用途。
Cookie 的本质:
是浏览器在本地存储 用户自定义数据 的一种关键机制。
就拿最典型的 登录操作 举例:
假设我们要登陆 B站,我们输入 账号 和 密码 之后点击登录
登陆成功:
当我们关掉 这个 B站 的页面之后
再次 打开我们心爱的 B站
我们发现:并不需要重新登录,我们的浏览器已经帮我们“登录”好了。
实现这种效果离不开我们的 Cookie~~
从上述流程我们不难了解:
Cookie 从哪来?
Cookie 从服务器来。当我们的浏览器访问服务器的时候,服务器就会在 HTTP 响应中,通过 Set-Cookie 字段,把 Cookie 的键值对返回给浏览器。
Cookie 到哪去?
浏览器会在下一次请求的时候,把 Cookie 带给服务器,Cookie 在浏览器这边,只能算是 “暂存” ,真正要让这个数据发挥作用,还得是由服务器来使用。
Cookie 有什么用?
Cookie 是浏览器本地存储数据的机制。存的不一定是账户信息,想存任何东西都可以(前提是得是字符串)。由于 Cookie 的存储空间有限,一般不会用 Cookie 存储太大的数据~~
上面我们提到 Cookie 是浏览器本地存储数据的机制。既然涉及到存储,那么具体怎么个存法呢?
是不是直接存储到硬盘文件上就行了呢?
万万使不得!!
这个操作无异于允许网页直接操作你电脑的文件系统,那么如果你一旦不小心点到了一个奇奇怪怪的网站,那么你的电脑可能就会被这些恶意网站的开发者给 “夺舍了”。
因此,为了保证用户上网能够比较安全,浏览器会作出限制,禁止网页能够直接访问硬盘。
虽然浏览器禁止了直接访问硬盘,但是允许网页往浏览器这里存储一些 Cookie ,这些数据通过浏览器提供的 api,写入特定的文件中。
由于网页由很多很多个,因此每个网站都是存自己的 Cookie (按照域名为维度来进行存储)
比如同一个网站(B站的舞蹈区、影视区、动画区等)共享一份 Cookie 。而不同的网站(百度、搜狗、B站等)是各有各的 Cookie 。
除了 浏览器禁止网页能够直接访问硬盘 之外,还有一种机制能够防止 Cookie 信息泄漏,那就是
Session (会话) 。这个会在将来的文章为大家详细讲解~~
正文中的内容格式和 header 中的 Content-Type 密切相关,有比较常见的三种情况:
大家可以试着抓一下包,观察一下~~
这是一个 HTTP 响应:
状态码存在于 首行 中。
以下为常见的状态码(大家应该清楚它们的含义):
这是一个最常见的状态码,表示访问成功
没有找到资源
浏览器输入一个 URL,目的就是为了访问对方服务器上的一个资源。如果这个 URL 标识的资源不存在,那么就会出现 404。
表示访问被拒绝
有的页面通常需要用户具有一定的权限才能访问(登陆后才能访问).如果用户没有登陆直接访问,就容易见到 403。
方法不被允许使用
前面我们已经学习了 HTTP 中所支持的方法,有 GET、POST、PUT、DELETE 等。但是对方的服务器不一定都支持所有的方法(或者不允许用户使用一些其他的方法)。
服务器出现内部错误
一般是服务器的代码执行过程中遇到了一些特殊情况(服务器异常崩溃)会产生这个状态码。
超时
当服务器负载比较大的时候,服务器处理单条请求的时候消耗的时间就会很长,就可能会导致出现超时的情况。
临时重定向
理解重定向:
就相当于手机号码中的 "呼叫转移" 功能。
比如我本来的手机号是 186-1234-5678,后来换了个新号码 135-1234-5678,那么不需要让我的朋友知道新号码,只要我去办理一个呼叫转移业务,其他人拨打 186-1234-5678,就会自动转移到 135-1234-5678 上。
在登陆页面中经常会见到 302,用于实现登陆成功后自动跳转到主页。
响应报文的 header 部分会包含一个 Location 字段,表示要跳转到哪个页面。
永久重定向
当浏览器收到这种响应时,后续的请求都会被自动改成新的地址。301 也是通过 Location 字段来表示要重定向到的新地址。
响应报头的基本格式和请求报头的格式基本一致,类似于 Content-Type、Content-Length 等属性的含义也和请求中的含义一致。
响应中的 Content-Type 常见取值有以下几种:
- text/html : body 数据格式是 HTML
- text/css : body 数据格式是 CSS
- application/javascript : body 数据格式是 JavaScript
- application/json : body 数据格式是 JSON
正文的具体格式取决于 Content-Type。
大家感兴趣可以去试着抓一下包。
以这个 text/html 为例:
它的 body 为:
太长了,没截全,大家可以试着抓一下~~
好啦,HTTP 协议初识就到这了,由于篇幅问题,还有一些内容会在后面的文章发布~~