目录
一、HTTP的含义
1.1 理解超文本
1.2 理解应用层协议
1.3 理解HTTP协议的工作过程
二、HTTP协议格式
2.1 抓包工具的使用
2.2 理解协议格式
2.2.1 请求协议格式
2.2.2. 响应格式请求
一、HTTP的含义
HTTP(全称为“超文本传输协议”),它是基于TCP协议的应用层传输协议,简单来说就是客户端和服务端进行数据传输的一种规则。
注意:客户端与服务器的角色不是固定的,一端充当客户端,也可能在某次请求中充当服务器。这取决与请求的发起端。HTTP协议属于应用层,建立在传输层协议TCP之上。客户端通过与服务器建立TCP连接,之后发送HTTP请求与接收HTTP响应都是通过访问Socket接口来调用TCP协议实现。
Ps:HTTP1.0, HTTP1.1, HTTP2.0 均为TCP, HTTP3 基于 UDP实现)
虽然当下最新的http版本已经到3.0,但是平时我们最常见的还是http 1.1,因此本章主要介绍1.1版本。
举例:我们平时打开一个网站,就是通过HTTP协议来传输数据的。
当我们在浏览器输入搜狗搜索 的网址(URL)的时候,浏览器就给搜狗的服务器发送一个HTTP请求,搜狗的服务器返回一个HTTP响应。
这个响应结果呗浏览器解析后,就展示铖我们看到的页面内容(这个过程中浏览器可能会被服务器发送多个HTTP请求,服务器会对应返回多个响应,这些响应里就包含了页面HTML,CSS,JavaScript,图片,字体等信息)。
1.1 理解超文本
所谓超文本的含义,就是传输的内容,不仅仅是文本(比如html,css这个就是文本),还可以是一些其他资源,比如图片,视频,音频等二进制的数据。
1.2 理解应用层协议
我们已经学过 TCP/IP , 已经知道目前数据能从客户端进程经过路径选择跨网络传送到服务器端进程[ IP+Port ].
可是,仅仅把数据从A点传送到B点就完了吗。
这就好比,在淘宝上买了一部手机,卖家[ 客户端 ]把手机通过顺丰[ 传送+路径选择 ] 送到买家 [
服务器 ] 手里就完了吗?
当然不是,买家还要使用这款产品,还要在使用之后,给卖家打分评论。
所以,我们把数据从A端传送到B端, TCP/IP 解决的是顺丰的功能,而两端还要对数据进行加工处理或者使用,所以我们还需要一层协议,不关心通信细节,关心应用细节!
这层协议叫做应用层协议。而应用是有不同的场景的,所以应用层协议是有不同种类的,其中经典协议之一的HTTP就是其中的佼佼者.
再回到我们刚刚说的买手机的例子,顺丰相当于 TCP/IP 的功能,那么买回来的手机都附带了说明书【产品介绍,使用介绍,注意事项等】,而该说明书指导用户该如何使用手机【虽然我们都不看,但是父母辈有部分是有看说明书的习惯的】,此时的说明书可以理解为用户层协议。
1.3 理解HTTP协议的工作过程
当我们在浏览器中输入一个网址,此时浏览器就会给对应的服务器发送一个 HTTP 请求. 对方服务器收到这个请求之后, 经过计算处理, 就会返回一个 HTTP 响应。
二、HTTP协议格式
HTTP是最典型的“一问一答”模型的协议,我们学习HTTP协议,主要就是学习其报文格式,
报文格式:描述了HTTP请求是啥样的,响应是啥样的。
2.1 抓包工具的使用
HTTP 是一个文本格式的协议. 可以通过 Chrome 开发者工具或者 Fiddler 抓包, 分析 HTTP 请求/响应的细节.这里我们主要以Fiddler来讲解:
- 左侧窗口显示了所有的 HTTP请求/响应, 可以选中某个请求查看详情.
- 右侧上方显示了 HTTP 请求的报文内容. (切换到 Raw 标签页可以看到详细的数据格式)
- 右侧下方显示了 HTTP 响应的报文内容. (切换到 Raw 标签页可以看到详细的数据格式)
- 请求和响应的详细数据, 可以通过右下角的 View in Notepad 通过记事本打开
进一步理解抓包
抓包(packet capture)就是将网络传输发送与接收的数据包进行截获、重发、编辑、转存等操作,也用来检查网络安全。抓包也经常被用来进行数据截取等。
而抓包工具,是一个特殊的软件,相当于是一个“代理程序”,浏览器给服务器发的请求,就会经过这个代理程序,进一步就能分析出请求和响应的结果,从而理解发送端和接受端的交互细节。
何为代理?
浏览器访问 sogou.com 时, 就会把 HTTP 请求先发给 Fiddler, Fiddler 再把请求转发给 sogou 的服务器.当 sogou 服务器返回数据时, Fiddler 拿到返回数据, 再把数据交给浏览器.
因此 Fiddler 对于浏览器和 sogou 服务器之间交互的数据细节, 都是非常清楚的。
2.2 理解协议格式
2.2.1 请求协议格式
请求协议格式主要包括:请求行+请求头部(header)+空行+请求体(body)。
一下为随机抓取的一个 访问搜狗搜索的 数据包。
因为是GET方法,所以没有请求体部分(body)。
//首行
GET https://www.sogou.com/ HTTP/1.1
//header
Host: www.sogou.com
Connection: keep-alive
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="8"
sec-ch-ua-mobile: ?0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 SLBrowser/8.0.1.1171 SLBChan/103
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
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
请求行
首行包含三个元素,之间使用空格来区分:[方法] + [url] + [版本]
- GET : HTTP的方法。
- URL(俗称网址):https://www.sogou.com/
- 版本号:HTTP/1.1
方法
以下为方法大全。实际开发中,这里的方法其实大多用不到,最常见的有两个:GET,POST。
GET方法
GET 是最常用的 HTTP 方法. 常用于获取服务器上的某个资源.在浏览器中直接输入 URL, 此时浏览器就会发送出一个 GET 请求.
另外, HTML 中的 link, img, script 等标签, 也会触发 GET 请求,另外,使用 JavaScript 中的 ajax 也能构造 GET 请求。
这是一条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 服务器端的实现. 在浏览器端, 不同的浏览器最大长
度是不同的, 但是现代浏览器支持的长度一般都很长; 在服务器端, 一般这个长度是可以配置的
POST方法
POST 方法也是一种常见的方法. 多用于提交用户输入的数据给服务器(例如登陆页面).
通过 HTML 中的 form 标签可以构造 POST 请求, 或者使用 JavaScript 的 ajax 也可以构造 POST 请求
这是一条POST请求:
POST 请求的特点
- 首行的第一部分为 POST
- URL 的 query string 一般为空 (也可以不为空)
- header 部分有若干个键值对结构.
- body 部分一般不为空. body 内的数据格式通过 header 中的 Content-Type 指定. body 的长度由 header 中的 Content-Length 指定.
POST与GET的区别(经典面试题)
其实GET和POST并没有本质上的区别(在大部分场景下,彼此之间都能相互替代),但是在使用习惯上是存在差异的:
- 语义不同: GET 一般用于从服务器获取数据, POST 一般用于提交数据.
- GET 的 body 一般为空, 需要传递的数据通过 query string 传递, POST 的 query string 一般为空, 需要传递的数据通过 body 传递
- GET 请求一般是幂等的, POST 请求一般是不幂等的. (如果多次请求得到的结果一样, 就视为请求是幂等的)
- GET可以被缓存,POST则一般不能被缓存(把请求的结果保存下来,下次请求时候就可以直接读取缓存的数据)。(Ps:能够被缓存的前提是幂等的。)
补充说明:
- 关于语义: GET 完全可以用于提交数据, POST 也完全可以用于获取数据.
- 关于幂等性: 标准建议 GET 实现为幂等的. 实际开发中 GET 也不必完全遵守这个规则(主流网站都有 "猜你喜欢" 功能, 会根据用户的历史行为实时更新现有的结果.
- 关于安全性: 有些资料上说 "POST 比 GET 请安全". 这样的说法是不科学的. 是否安全取决于前端在传输密码等敏感信息时是否进行加密, 和 GET POST 无关.
- 关于传输数据量: 有的资料上说 "GET 传输的数据量小, POST 传输数据量大". 这个也是不科学的, 标准没有规定 GET 的 URL 的长度, 也没有规定 POST 的 body 的长度. 传输数据量多少,完全取决于不同浏览器和不同服务器之间的实现区别.
- 关于传输数据类型: 有的资料上说 "GET 只能传输文本数据, POST 可以传输二进制数据". 这个也是不科学的. GET 的 query string 虽然无法直接传输二进制数据, 但是可以针对二进制数据进行 url encode
认识URL
平时我们俗称的 "网址" 其实就是说的 URL (Uniform Resource Locator 统一资源定位符).
互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。
Ps:需要注意的是,URL非HTTP协议专属,很多协议都在使用URL。
URL最关键的四个部分:
- 域名
- 端口号
- 带层次的路径
- 查询字符串
举例,搜狗搜索的网址:https://www.sogou.com/
这里就省略了端口号(省略的话,浏览器就会提供默认端口,对于http来说,默认端口号是80,对于https来说,默认端口号是443)。
需要注意的是这里com后面的/也是路径,这里没省略,只是有点短,代表的是HTTP服务器的根目录。
查询字符串(query string)
以?开头,以键值对的方式组织,其中的 key 和 value 的取值和个数, 完全都是程序猿自己约定的. 我们可以通过这样的方式来自定制传输我们需要的信息给服务器. 键值对之间使用&分割,键和值之间使用 = 分割。
URL encode
我们随机找一个带query string的url,会发现搜索如果是带有特殊符号的比如# ?: 等,会被转义为其他字符。
这时一位 这些符号本先被url当特殊意义理解了,所以当某个参数带有这些特殊字符的时候就必须先对这些特殊字符进行转义:
urldecode就是urlencode的逆过程;
URL和URI的区别
URI是唯一资源标识符,是一种身份标识——用来区分其他资源区,其可能不是固定的,比如找一本书,这本书放在建设路aa图书馆的bb层的cc书架上;
其中的aa图书馆相对于aa图书馆相对于建设路就是一个标识符,bb层相对于aa图书馆就是一个标识符。
唯一资源标识符不是固定的,而是相对的。主要作用就是用于与其他资源区别开来的一个标识符。
而URL是唯一资源定位符,标识互联网上唯一的资源位置。
实际开发中,经常会将两个词混用,不必做过多纠结。
header部分
header 的整体的格式也是 "键值对" 结构.
每个键值对占一行. 键和值之间使用:分割。
1.HOST
表示服务器主机的地址和端口,用来描述最终要访问的目标。这个内容大概率是和URL中一样,也有一定的情况是不同的。
2.Content-Length
表示body中的数据长度
3.Content-Type
表示请求的body中的数据格式
响应中的 Content-Type 常见取值有以下几种:
- text/html : body 数据格式是 HTML
- text/css : body 数据格式是 CSS
- application/javascript : body 数据格式是 JavaScript
- application/json : body 数据格式是 JSON
需要注意的是:如果是GET请求,没body,请求中没有上面这两个字段(Content-Type,Content-Length),如果是POST请求,有body,则必须有这两个字段(Content-Length,Content-Type)。
4.user-Agent(简称UA)
表示浏览器/操作系统的属性. 形如
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 SLBrowser/8.0.1.1171 SLBChan/103
其中 Windows NT 10.0; WOW64 代表操作系统信息,、
其中 AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 SLBrowser/8.0.1.1171 SLBChan/103 表示浏览器信息。
user-Agent 存在的原因很大部分是因为历史原因,因为早期的浏览器只支持文本,后来浏览器支持图片,视频,音频,js等。
互联网发展至今,User-Agent现在的用途主要是用来区分PC和移动端了。
5.Refer
表示这个页面是从哪个页面跳转过来的 形如:
另外:如果直接在浏览器中输入URL,或者直接通过收藏家访问页面是没有Referer的。
6.Cookie(重点)
HTTP cookie,简称cookie,是用户浏览网站时由网络创建并由用户的网页浏览器存放在用户计算机或其他设备上的小文本文件。
Cookie使Web服务器能够在用户的设备上存储状态信息(如添加到在线商店购物车中的商品)或跟踪用户的浏览活动(如点击特定按钮、登录或记录历史)
其作用就像是服务器在浏览器中设置了一个寄存器一样。
Cookie是从哪里来的?
Cookie中的数据来自于服务器,服务器会通过HTTP响应的报头Set-Cookie字段来决定浏览器的Cookie要存什么。
Cookie是在哪存的?
可以认为存于浏览器中,存在于硬盘的。
Cookie在存的时候是按照 浏览器+域名的形式来进行细分。不同的浏览器各自存各自的Cookie,同一个浏览器不同的域名,对应的不同的Cookie。
需要注意的是:Cookie里面不止存键值对,可能还存储着过期时间。
越敏感的网站,对Cookie的保存时间就越短。
Cookie要到哪里去?
回到服务器中,客户端在同一时刻是很多的,客户端这边会通过Cookie来保存当前用户使用的中间状态,当客户端访问浏览器的时候,就会自动的把Cookie的内容带入到请求中,服务器就能够知道现在的客户端是啥样了。
空行
表示header结束的标志。
2.2.2. 响应格式请求
认识 "状态码" (status code):状态码表示访问一个页面的结果. (是访问成功, 还是失败, 还是其他的一些情况...)
200 OK
这是一个最常见的状态码, 表示访问成功.
404 Not Found
没有找到资源
浏览器输入一个 URL, 目的就是为了访问对方服务器上的一个资源. 如果这个 URL 标识的资源不存
在, 那么就会出现 404
例如, 在浏览器中输入 https://cn.bing.com/sai.html , 此时就在尝试访问 sogou 上的
/sal.html 这个资源.如果输入正确, 则可以正确访问到. 但是如果输入错误, 比如 https://cn.bing.com/sai.html, 就会看到 404 这样的响应
403 Forbidden
表示访问被拒绝. 有的页面通常需要用户具有一定的权限才能访问(登陆后才能访问). 如果用户没有登陆直接访问, 就容易见到 403.
例如: 查看码云的私有仓库, 如果不登陆, 就会出现 403
405 Method Not Allowed
前面我们已经学习了 HTTP 中所支持的方法, 有 GET, POST, PUT, DELETE 等.
但是对方的服务器不一定都支持所有的方法(或者不允许用户使用一些其他的方法).
500 Internal Server Error
服务器出现内部错误. 一般是服务器的代码执行过程中遇到了一些特殊情况(服务器异常崩溃)会产生这个状态码.咱们平时常用的网站很少会出现 500 (但是偶尔也能看到)
504 Gateway Timeout
当服务器负载比较大的时候, 服务器处理单条请求的时候消耗的时间就会很长, 就可能会导致出现超时的情况.这种情况在双十一等 "秒杀" 场景中容易出现, 平时不太容易见到.
302 Move temporarily
临时重定向.
在登陆页面中经常会见到 302. 用于实现登陆成功后自动跳转到主页.
响应报文的 header 部分会包含一个 Location 字段, 表示要跳转到哪个页面
何为重定向?
可以理解为电话的呼叫转移业务,当呼叫一个办理转移业务的手机号时候,会自动将你的电话转移到另外一部电话上。
301 Moved Permanently
永久重定向. 当浏览器收到这种响应时, 后续的请求都会被自动改成新的地址.
301 也是通过 Location 字段来表示要重定向到的新地址
状态码小结
在响应协议的格式中,响应报头和正文与请求协议格式相同,这里就不作过多赘述。
以下为小结: