2024年掌握HTTP协议,你务必了解的点_http头字段与值之间有空格吗,2024年最新2024年字节跳动、阿里等大厂C C++面试题

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 右侧上方显示了 HTTP 请求的报文内容. (切换到 Raw 标签页可以看到详细的数据格式)
  • 右侧下方显示了 HTTP 响应的报文内容. (切换到 Raw 标签页可以看到详细的数据格式)
  • 请求和响应的详细数据, 可以通过右下角的 View in Notepad 通过记事本打开
  • 可以使用 ctrl + a 全选左侧的抓包结果, delete 键清除所有被选中的结果

3.抓包结果

(1)HTTP请求

查看格式:
在这里插入图片描述
原始模样如下图:
在这里插入图片描述上面的请求分为四个部分:

  1. 请求行(首行),包含三个部分.
    a)HTTP的方法。方法大概描述了这个请求想干啥,GET意思就是想从服务器获取到某个东西。
    b)URL。描述了要访问的网络上的资源具体是在哪。
    c)版本号。HTTP/1.1表示当前使用的HTTP 的版本是1.1。1.1是当下最主流的版本,此外还可能是1.0/2/ 3。
  2. 请求头(header)包含了很多行,每一行都是一个键值对。键和值之间使用:空格来分割。这里的键值对个数是不固定的,有可能多,也有可能少。不同的键和值,表示的含义也不同。
  3. 空行相当于请求头的结束标记,类似于链表的null
  4. 请求正文(body)可选的.不一定有。

在这里插入图片描述


(2)HTTP响应

针对响应,也有很多的选项. 此处要选择Raw,才能看到本体。

在这里插入图片描述

上面看到的本体好像是乱码?乱码其实是压缩之后的结果。一个服务器,最贵的硬件资源,其实是网络带宽。像这些HTTP响应,经常会很大,就比较占用带宽为了能够提高效率,经常服务器会返回"压缩之后”的数据,由浏览器收到之后再来解压缩。这里同样也点击右下角的按钮,就可以看到原始模样了。

在这里插入图片描述
上面也是包含了四个部分的:

  1. 首行:包含了3个部分
    a)版本号~HTTP/1.1
    b) 200状态码,描述了这个响应,是一个表示"成功的”还是"失败的",以及不同的状态码,描述了失败的原因。
    c)OK状态码的描述.通过一个/一组简单的单词,来描述当前的状态码的含义。
  2. 响应头(header)
    也是键值对结构。每个键值对占一行,每个键和值之间使用:空格来分割。响应头中的键值对个数,也是不确定的。不同的键值对表示不同的含义。
  3. 空行:表示响应头的结束标记。
  4. 响应正文(body):服务器返回给客户端的具体数据.


4.注意事项

(1)Fiddler刚安装好的时候,默认没有启用HTTPS.如果你抓到了HTTPS的包,就会出现下面的情况。因为当下网络上的大部分的网站都是HTTPS,如果不开启HTTPS,其实就基本没啥可抓的了。

在这里插入图片描述

开启步骤:

在这里插入图片描述

(2)Fiddler 作为一个代理,是和其他的代理程序冲突的。
如果你的电脑上也安装了其他代理程序/插件,就可能导致 Fiddler 失效,啥也抓不着。

比如你电脑上的xxx加速器,xxx vpn, xxx fq工具…都是可能和fiddler冲突的.保证你使用fiddler的时候,要先退出相关的程序。

关于Fiddler这个抓包工具就介绍到这里。下面回到我们的HTTP协议格式。


5.协议格式总结

在这里插入图片描述在这里插入图片描述

思考:为什么 HTTP 报文中要存在 “空行”?

答:因为 HTTP 协议并没有规定报头部分的键值对有多少个。空行就相当于是 “报头的结束标记”, 或者是 “报头和正文之间的分隔符”。HTTP 在传输层依赖 TCP 协议,TCP 是面向字节流的. 如果没有这个空行, 就会出现 “粘包问题”。


四、HTTP 请求 (Request)

1.认识 URL

1.1.URL 基本格式

URL含义表示是“网络上唯一资源的地址符"。

平时我们俗称的 “网址” 其实就是说的 URL (Uniform Resource Locator 统一资源定位符)。互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。

URL 的详细规则由 因特网标准RFC1738 进行了约定。点击这里
在这里插入图片描述
我们来分析下面这个具体的URL:

https://v.bitedu.vip/personInf/student?userId=10000&classId=100

可以看到, 在这个 URL 中有些信息被省略了。

  • https : 协议方案名. 常见的有 http 和 https, 也有其他的类型. (例如访问 mysql 时用的jdbc:mysql;http://给HTTP用的https://给HTTPS用的 )
  • user:pass : 登陆信息. 现在的网站进行身份认证一般不再通过 URL 进行了. 一般都会省略
  • v.bitedu.vip : 服务器地址。表示当前访问的主机是啥,此处是一个 “域名”, 域名会通过 DNS 系统解析成一个具体的 IP 地址。(通过 ping 命令可以看到, v.bitedu.vip 的真实 IP 地址为 118.24.113.28 )
  • 端口号: 上面的 URL 中端口号被省略了。当端口号省略的时候, 浏览器会根据协议类型自动决定使用哪个端口。 例如 http 协议默认使用 80 端口, https 协议默认使用 443 端口。
  • /personInf/student : 带层次的文件路径,表示当前要访问的的服务器的资源是什么。虽然请求的URL中,写的是一个文件路径,但是服务器上不一定就真存在一个对应的文件。这个文件可能是一个真实的,在磁盘上存在的文件,也可能是虚拟的,由服务器代码,构造出的一个动态数据。
  • userId=10000&classId=100 : 查询字符串(query string). 本质是一个键值对结构。键值对之间使用 & 分隔。键和值之间使用 = 分隔。query string 中的内容是键值对结构。 其中的 key 和 value 的取值和个数,完全都是程序猿自己约定的。我们可以通过这样的方式来自定制传输我们需要的信息给服务器。
    在这里插入图片描述
  • 片段标识:此 URL 中省略了片段标识。片段标识主要用于页面内跳转。

URL 中的可省略部分:

  • 协议名: 可以省略, 省略后默认为 http://
  • ip 地址 / 域名: 在 HTML 中可以省略(比如 img, link, script, a 标签的 src 或者 href 属性)。 省略后表示服务器的 ip / 域名与当前 HTML 所属的 ip / 域名一致。
  • 端口号: 可以省略. 省略后如果是 http 协议, 端口号自动设为 80; 如果是 https 协议,,端口号自动设为 443。
  • 带层次的文件路径: 可以省略。 省略后相当于 / 。有些服务器会在发现 / 路径的时候自动访问/index.html。
  • 查询字符串: 可以省略。
  • 片段标识: 可以省略。

URL小结:
对于URL来说,里面的结构看起来比较复杂,其实最重要的,和开发最关系紧密的,主要就是四个部分:
(1) ip 地址/域名
(2)端口号(经常是小透明)
(3)带层次结构的路径
(4) query string查询字符串


2.URL encode 与 URL decode

当query string 中如果包含了特殊字符,就需要对特殊字符进行转义。这个转义的过程,就叫做url encode。反之,把转义后的内容还原回来,就叫做url decode。

问:为什么需要这个转义过程呢?

答:因为url里面是有很多特殊含义的符号的,例如 /∶? &= …这些符号都是在URL中具有特定含义的。万一, query string里也包含这类特殊符号,就可能导致URL被解析失败。

转义的规则:

将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式。

如下图这个:“+” 被转义成了 “%2B”。
在这里插入图片描述
在这里插入图片描述

而urldecode就是urlencode的逆过程。


3.一些方法

在这里插入图片描述
HTTP协议的方法有很多,但是最常用的是GET 和 POST两个方法。

3.1.GET 方法

GET 是最常用的 HTTP 方法。常用于获取服务器上的某个资源。在浏览器中直接输入 URL, 此时浏览器就会发送出一个 GET 请求。另外, HTML 中的 link, img, script 等标签, 也会触发 GET 请求。

GET 请求的特点

  • 首行的第一部分为 GET
  • URL 的 query string 可以为空, 也可以不为空.
  • header 部分有若干个键值对结构.
  • body 部分为空.

我们可以使用Fiddler 观察 GET 请求。

(1)打开 Fiddler, 访问 百度主页, 观察抓包结果。

在这里插入图片描述

在上面的结果中可以看到,下图是通过浏览器地址栏发送的 GET 请求。
在这里插入图片描述
下面的和 百度域名相关的请求, 有些是通过 html 中的 link/script/img 标签产生的, 例如:
在这里插入图片描述

关于 GET 请求的 URL 长度问题:
  网上有些资料上描述: get请求长度最多1024kb 这样的说法是错误的。HTTP 协议由 RFC 2616 标准定义, 标准原文中明确说明: “Hypertext Transfer Protocol --HTTP/1.1,” does not specify any requirement for URL length。没有对 URL 的长度有任何的限制。实际 URL 的长度取决于浏览器的实现和 HTTP 服务器端的实现。 在浏览器端, 不同的浏览器最大长度是不同的, 但是现代浏览器支持的长度一般都很长; 在服务器端, 一般这个长度是可以配置的。


3.2.POST 方法

POST 方法也是一种常见的方法。多用于提交用户输入的数据给服务器(例如登陆页面)。通过 HTML 中的 form 标签可以构造 POST 请求, 或者使用 JavaScript 的 ajax 也可以构造 POST 请求。

POST 请求的特点

  • 首行的第一部分为 POST。
  • URL 的 query string 一般为空 (也可以不为空)。
  • header 部分有若干个键值对结构。
  • body 部分一般不为空.。body 内的数据格式通过 header 中的 Content-Type 指定。 body 的长度由header 中的 Content-Length 指定。

3.3.GET与POST区别

设计HTTP的大佬希望程序猿能够按照HTTP语义来使用这里的各种方法。但是随着时间的推移,使用就走形了。现在大家写代码,基本都是GET/POST一把梭,基本没咋考虑语义的事情。正因为如此,也就导致了多种HTTP方法之间的界限,就变的模糊了

  • GET也可以给服务器送个东西
  • POST也可以从服务器拿个东西

面试题:谈谈 GET 和 POST 的区别

GET和POST没有本质区别。

具体来说,相当于是GET能使用的场景,也能替换成POST使用的场景,也能替换成GET。但是细节上,还是有一些区别的。体现如下:

  1. 语义不同: GET 一般用于获取数据, POST 一般用于提交数据。但当下使用的现状是:GET用经常用来提交数据,POST也常用来获取数据。
  2. GET 的 body 一般为空(没有body), 需要传递的数据通过 query string 传递,POST 的 query string 一般为空,但有body,需要传递的数据通过 body 传递。如果我就想让GET有body,于是自己构造一个带 body的GET请求,或者就想让POST带有query string,这是完全可以!
  3. GET 请求一般是幂等的, POST 请求一般是不幂等的. (如果多次请求得到的结果一样, 就视为请求是幂等的)。
    数学上的术语:
    幂等:每次你相同的输入,得到的输出结果是确定的;
    不幂等每次你相同的输入,得到的结果不确定
  4. GET 可以被缓存, POST 不能被缓存. (这一点也是承接幂等性)。
    这里缓存的意思是提前把结果记住,如果是幂等的,记住结果的话就可以节省下次访问的开销。否则,则记住无用。

能不能缓存和能不能幂等是有关联的.如果请求本身都不是幂等,就不能缓存。


4.请求 “报头” (header)

header 的整体的格式也是 “键值对” 结构。每个键值对占一行,键和值之间使用分号分割。

下面介绍一些常用的报头。

4.1.Host

表示服务器主机的地址和端口

比如下面这里抓的是百度的页面:在这里插入图片描述上面的域名可以通过DNS转换成IP地址。


4.2.Content-Length

表示body中的数据长度

比如下面向百度网页发出请求的响应:
在这里插入图片描述

  HTTP也是基于TCP的协议,而TCP是一个面向字节流的的协议,那么这里就存在一个粘包问题——接收数据包的时候,会一个字节一个字节的挨在一起,那么读数据的时候就会分不清这个数据的头和尾在哪。

解决方案是合理设计应用层协议,明确包和包之间的边界。一般有两种方法,一是使用分隔符,而是使用长度规定。如果当前我们有若干个GET请求,到了TCP接收缓冲区了,应用程序读取请求的时候,就以空行作为分隔符。如果当前有若干个POST请求,到了TCP接收缓冲区,这个时候空行后面还有body的话,当应用程序读到空行之后,就需要按照Content-length表明的长度,继续读若干长度的数据。因此,我们HTTP这里既借助了分隔符,也借助了长度来设计这个应用层协议。


4.3.Content-Type

表示请求的 body 中的数据格式

比如下面向百度网页发出请求的响应:
在这里插入图片描述
这个东西看起来很长,但是在实际开发中,会经常用到。这个东西表示的含义就是body中的数据表示格式,就和url中的query string 一样!

这些数据格式常见的有:

(1)application/x-www-form-urlencoded

最常见的 POST 提交数据方式。也是浏览器的原生form表单,如果不设置 Content-Type 属性,则默认以 application/x-www-form-urlencoded 方式传输数据。

此时 body 的格式形如:

POST http://www.example.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8

title=ahweg&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3

Content-Type 被指定为 application/x-www-form-urlencoded;其次,提交的数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL 转码。

(2)multipart/form-data

另一个常见的 POST 数据提交的方式。我们使用表单上传文件时,必须让表单的 Content-Type 等于 multipart/form-data。此外,还支持传输多种文件格式。

如:

POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA

------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="ahweg"

title
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="file"; filename="ahweg.png"
Content-Type: image/png

PNG ... content of ahweg.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--

首先生成了一个 boundary 用于分割不同的字段,为了避免与正文内容重复,boundary 很长很复杂。然后 Content-Type 里指明了数据是以 multipart/form-data 来编码,本次请求的 boundary 是什么内容。消息主体里按照字段个数又分为多个结构类似的部分,每部分都是以 --boundary 开始,紧接着是内容描述信息,然后是回车,最后是字段具体内容(文本或二进制)。如果传输的是文件,还要包含文件名和文件类型信息。消息主体最后以 --boundary-- 标示结束。

(3)application/json

现在用得比较多的一种方式JSON字符串,支持结构化的数据。用来告诉服务端消息主体是序列化后的 JSON 字符串。

如:

POST http://www.example.com HTTP/1.1 
Content-Type: application/json;charset=utf-8

{"title":"ahweg","sub":[1,2,3,4,5]}

这种方案,可以方便的提交复杂的结构化数据,特别适合 RESTful 的接口。各大抓包工具如 Chrome 自带的开发者工具、Firebug、Fiddler,都会以树形结构展示 JSON 数据,非常友好。

参考资料来源:HTTP POST body四种数据格式


4.4.User-Agent (简称 UA)

表示浏览器/操作系统的属性。

例如:

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/91.0.4472.77 Safari/537.36

  • Windows NT 10.0; Win64; x64 表示操作系统信息
  • AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36 表示浏览器信息。

User-Agent 的故事


4.5.Referer

表示这个页面是从哪个页面跳转过来的。如果直接在浏览器中输入URL, 或者直接通过收藏夹访问页面时是没有Referer 的。

在这里插入图片描述


4.6.Cookie

Cookie就是浏览器给页面提供的一种能够持久化存储数据的机制。持久化指的就是数据不会因为程序重启或者主机重启而丢失,因为数据被写到磁盘里。

浏览器为了安全在默认情况下是不能让页面的js访问到用户电脑上的文件系统的。假设某个网页上,包含恶意代码,如果不小心一点,就可能触发这个恶意代码,把你电脑上的"学习资料"全给删了。但是浏览器这样的安全限制,也会带来了一些麻烦。比如说有时候确实又需要让页面这里持久化存储一些数据,方便后续访问网站。例如最典型的去存储用户当前的身份信息。当用户在登录页面完成身份认证之后,此时服务器就会给浏览器返回一个用户的身份信息,浏览器就会把这个信息就保存到了一个特定的位置上。后续再访问同一个网站的其他页面的时候,浏览器再自动的带上这个身份信息,这样服务器就能识别了。

虽然不能让页面的js访问你的整个磁盘数据,但是可以单独给浏览器分配一个小黑屋, js代码就可以在这个小黑屋里随便折腾。这里的折腾,就不会影响到你磁盘上的其他的学习资料。

这里的小黑屋,有多种不同的形式.其中Cookie是一个比较古老,也比较经典的形式。现代浏览器也支持一些其他的本地存储的方案。

Cookie具体的组织形式:
(1)先按照域名来组织,针对每个域名,分别分配一个小房间。比如说,我访问B站,B站就会给B站的域名记录一组Cookie。

在这里插入图片描述

(2)一个小房间里面,又会按照键值对的方式来组织数据。

在这里插入图片描述
下面举一个例子:抓包观察页面登陆的过程——以登录B站为例。

(1)清除之前的 cookie。
为了方便观察, 先清除掉之前登陆的 cookie,在gitee页面上点击 url 左侧的图标, 选择 Cookie。点击移除,将记录全部去掉。

(2)登陆请求

在这里插入图片描述

(3)登陆响应

在这里插入图片描述

可以看到,,响应中包含了 4 个 Set-Cookie 属性。其中我们重点关注第四个。里面包含了一个 gitee-session-n 这样的属性, 属性值是一串很长的加密之后的信息, 这个信息就是用户当前登陆的身份标识,也称为 “令牌(token)”。上面的一组这样的header ,表示的就是服务器完成身份认证之后,给客户端返回了一些具体的信息,而这些信息就是就是通过Set-Cookie这样的响应报头来表示的。

我们登录的关键信息,存储在服务器上,我们管这个东西称为"session",中文意思是会话。服务器这里管理着很多很多的session ,每个session里面都存储了用户的关键信息,每个session也有一个sessionld(会话的标识)。

(4)访问其他页面

登陆成功之后, 此时可以看到后续访问码云的其他页面(比如个人主页), 请求中就都会带着刚才获取到的Cookie 信息。
  请求中的 Cookie 字段也包含了一个 gitee-session-n 属性, 里面的值和刚才服务器返回的值相同。 后续只要访问 gitee 这个网站, 就会一直带着这个令牌, 直到令牌过期/下次重新登陆。

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

,而这些信息就是就是通过Set-Cookie这样的响应报头来表示的。

我们登录的关键信息,存储在服务器上,我们管这个东西称为"session",中文意思是会话。服务器这里管理着很多很多的session ,每个session里面都存储了用户的关键信息,每个session也有一个sessionld(会话的标识)。

(4)访问其他页面

登陆成功之后, 此时可以看到后续访问码云的其他页面(比如个人主页), 请求中就都会带着刚才获取到的Cookie 信息。
  请求中的 Cookie 字段也包含了一个 gitee-session-n 属性, 里面的值和刚才服务器返回的值相同。 后续只要访问 gitee 这个网站, 就会一直带着这个令牌, 直到令牌过期/下次重新登陆。

[外链图片转存中…(img-93YxuQAm-1715595913453)]
[外链图片转存中…(img-dYVbaLAN-1715595913454)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值