事和组长的一番对话引起了笔者对 git 的思考
先介绍一下我司小工坊式的 git 提交流程,本地打包,删除 dist 文件,重建 dist 文件,git add .,git commit -m 'XX',git push origin 分支名
和传统公司的 git 提交不同,我司打包是本地打包,而且是把 dist 文件直接上传到仓库
同事把代码推上去后,浏览器访问的还是原来的 js 和 css。
同事说:组长,需要你把 dist 删掉,重新再从仓库里拉一下最新的
组长:git 提交后不就把原来的 dist 替换了吗,你让我删 dist 有什么意义
扯皮了一会儿,组长还是删了然后重新拉,没想到好了
组长说:你的 dist 现在是最新的,所以现在就好了
同事具体说了什么笔者忘记了,大致上在辩护 git 提交不会把原来的 dist 文件删除问题,不过他没说服组长,组长也没说服他,反正已经安全上线而不了了之。
我正好在旁边听到了,要是两年前我也许会一直提出问题参与辩论,申援同事。但笔者没动,不是怕 PUA,而是表达能力太差,即使是对的,也说不好。其根本原因是笔者对这块知识了解的不深刻,所以不敢说大话
按照理论知识,你 push 整个 dist 文件,即使远程仓库中有 dist,也不会把整个 dist 文件夹替换,只会替换其中相同的数据,而因为打了 hash 值,所以 css 和 js 都是不同的,所以一直这样做,dist 中的文件会越来越多,而因为 index.html 文件只有一个,所以不会出现替换了还引用之前文件的问题,如果出现,清除下浏览器的缓存就能解决
因为生产环境和测试环境发布代码流程不同,所以先要把环境配置成一致先
需要做的事情很简单,把 nginx 中指向仓库地址,到时候从远端拉下代码即可
先修改 nginx 中的配置
server {
listen 7000;
# root /usr/share/nginx/html/dist
root /home/jingqb-web/dist
...
}
再检查一下 nginx 配置是否 ok
nginx -t
接着重启 nginx
nginx -s reload
接着把代码提交到远端仓库,再上服务器进入 /home/jingqb-web 目录下,git pull origin XX ,进入 dist 文件,查看打包后的 js
原js的hash值
我们修改在项目中打印一些日志,表示文件改动,这样 build 之后会打出不同 hash 的 js
git push origin XX
再次登录服务器,进入 /home/jingqb-web 目录,再拉代码git pull origin xx
再次提交后的代码
发现,umi.b0f5511b.js 被删掉了,新生成的 umi.f8280c0e.js 在其中,dist 中是干净的源文件,这是为什么呢?
你 build 之后,是先删掉 dist 文件,生成的是一个干净的 dist,然后我的操作是:
我的操作中没有 pull 代码,而是直接 push 代码,这就意味着 dist 就是我本地的 dist,而非合并之后的
想想这种做法的缺点是多人开发时,pull 别人的代码后,merge 之后还要重新 build,才能再次提交
好险,还好没有逞英雄
谨言慎行是一辈子的学问
这触发了笔者对 git 的新认知,结合平时经验,笔者觉得三个问题能测试别人对 git 的理解程度
面几篇文章我们讲到了跨站脚本(XSS)漏洞的几种类型和验证方法以及防御措施,有兴趣的朋友可以到我的主页翻看文章《十大常见web漏洞——跨站脚本漏洞》和《实操web漏洞验证——跨站脚本漏洞》,今天我们继续由易到难实战演示一下跨站脚本漏洞的形成,以便更好地了解漏洞的产生原理,进一步做好防御。
上一篇文章我们已经闯过了5关,今天我们继续。
html事件是在满足一定条件的用户行为发生时,所触发的的事件,例如当单击鼠标时的“onclick”以及当浏览器加载图像时的“onload”,我们可以将这些特定的html事件发生时,将JavaScript语句作为属性传递给特定的标签,从而构成一个或多个JavaScript命令或函数。
下图我们从网上搜索了一些html事件属性,有兴趣的可以自己搜索学习。
html事件属性
在这一关中,我们可以构造语句:
111" onmouseover="alert(document.domain);"
前边的“111"”是为了闭合标签,后边的“onmouseover”属性表示当鼠标移动到输入框时执行后边的语句,点击“search”按钮,将鼠标移动到输入框时,页面在弹出内容为当前页面域名的弹窗后,提示“恭喜!”,就可以顺利进入下一关了,如下图所示:
恭喜通关
这一关我们先来探测一下注入点的情况,我们和之前一样先闭合标签,输入“123456"”来闭合标签,找到对应的代码,发现我们输入的内容被另一对引号括住了,如下图所示:
页面代码
这表明我们输入的内容直接被实体化了,那我们不使用引号闭合,直接输入“123456 onmouseover=“alert(document.domain)””,发现只要是等号后边的参数都被引号括了起来,如下图所示:
页面代码
因此我们都不加引号,构造:
123456 onmouseover=alert(document.domain)
注意中间有个空格,点击“search”按钮时,页面在弹出内容为当前页面域名的弹窗后,提示“恭喜!”,就可以顺利进入下一关了,如下图所示:
恭喜通关
有时候我们需要将JavaScript代码添加到客户端中,这时就需要JavaScript伪协议来帮助,它的格式为JavaScript:url,例如:JavaScript:alert("hello word!"),就是一个简单的通过JavaScript伪协议来执行alert("hello word!")语句,它表示在页面显示“hello word!”。
因此我们可以构造语句
JavaScript:alert(document.domain);
点击“Make a Link”按钮时,可见输入框下边出现一个URL超链接,我们点击这个链接,如下图所示:
URL超链接
页面在弹出内容为当前页面域名的弹窗后,提示“恭喜!”,就可以顺利进入下一关了,如下图所示:
恭喜通关
这个比较简单,因为UTF-7绝大多数浏览器都已经不用了,我们很少会遇到,因此我们直接构造语句:
onclick=alert(document.domain);
我们按F12键,根据下图提示找到第三步位置,将以上语句写入到对应位置,再点击第二步的位置,如下图所示:
修改页面代码
页面在弹出内容为当前页面域名的弹窗后,提示“恭喜!”,就可以顺利进入下一关了,如下图所示:
恭喜通关
首先我们还是老办法构造闭合语句,如下所示:
"><script>alert(document.domain);</script>
点击“search”,按F12,找到如下图红框中的位置,发现我们上边构造的语句中“domain”被删除了,如下图所示:
页面代码
既然被删除了,这时我们可以通过双写来绕过domain被删除这种情况,我们可以构造:
"><script>alert(document.dodomainmain);</script>
注意我们在单词domain中间又加了一个单词domain,这时系统在删除一个单词domain后,还会留下一个domain,这样我们就成功执行了语句了。
点击“search”按钮时,页面在弹出内容为当前页面域名的弹窗后,提示“恭喜!”,就可以顺利进入下一关了,如下图所示:
恭喜通关
当然我们也可以通过编码的方法来绕过,我们可以构造:
"><script>eval(atob('YWxlcnQoZG9jdW1lbnQuZG9kb21haW5tYWluKTs='));</script>
其中“eval”是用来执行字符串,其后边的内容会当成JavaScript语句执行,“atob”表示将加密的base64密文,转换成原文,而里边的一串乱码就是通过base64加密过的的“alert(document.domain)”语句,关于加密,有兴趣的可以阅读我的文章《Web渗透测试——密码学基础》,其实和上边的语句一样,这样就可以避免domain被删除了。
以上就是跨站脚本(XSS)漏洞实战演示——由易到难第二部分的全部内容,希望对你了解XSS漏洞有所帮助,欢迎关注@科技兴了解更多科技尤其是网络安全方面的资讯和知识。
正式学习网络爬虫之前,我们需要详细了解 HTTP 的基本原理,了解在浏览器中敲入 URL 到获取网页内容之间发生了什么。了解这些内容,有助于我们进一步了解爬虫的基本原理。
在本节中,我们会详细了解 HTTP 的基本原理,了解在浏览器中敲入 URL 到获取网页内容之间发生了什么。了解这些内容,有助于我们进一步了解爬虫的基本原理。
这里我们先了解一下 URI 和 URL。URI 的全称为 Uniform Resource Identifier,即统一资源标志符;而 URL 的全称为 Universal Resource Locator,即统一资源定位符。举例来说,github.com/favicon.ico 是一个 URL,也是一个 URI。即有这样一个图标资源,我们用 URL/URI 来唯一指定了它的访问方式,这其中包括了访问协议 https、访问路径(即根目录)和资源名称 favicon.ico。通过这样一个链接,我们便可以从互联网上找到这个资源,这就是 URL/URI。
URL 是 URI 的子集,也就是说每个 URL 都是 URI,但不是每个 URI 都是 URL。那么,怎样的 URI 不是 URL 呢?URI 还包括一个子类,叫作 URN,它的全称为 Universal Resource Name,即统一资源名称。URN 只命名资源而不指定如何定位资源,比如 urn:isbn:0451450523 指定了一本书的 ISBN,可以唯一标识这本书,但是没有指定到哪里定位这本书,这就是 URN。URL、URN 和 URI 的关系可以用图 1-1 表示。
但是在目前的互联网,URN 使用得非常少,几乎所有的 URI 都是 URL,所以对于一般的网页链接,我们既可以称之为 URL,也可以称之为 URI,我个人习惯称之为 URL。
但 URL 也不是随便写的,它也是需要遵循一定的格式规范的,基本的组成格式如下:
scheme://[username:password@]hostname[:port][/path][;parameters][?query][#fragment]
复制代码
其中这些括号包括的内容代表非必要部分,比如 www.baidu.com 这个 URL,这里就只包含了 scheme 和 host 两部分,其他的 port、path、parameters、query、fragment 都没有。
这里我们分别介绍下几部分代表的含义和作用:
以上我们就简单了解了 URL 的基本概念和构成,后文我们会结合多个实战案例练习来帮助加深其理解。
刚才我们了解了 URL 的基本构成,其支持的协议有很多,比如 http、https、ftp、sftp、smb 等等。
在爬虫中,我们抓取的页面通常基于 http 或 https 协议,这里首先我们先来了解一下这两个协议的含义。
HTTP 的全称是 Hyper Text Transfer Protocol,中文名叫作超文本传输协议。HTTP 协议是用于从网络传输超文本数据到本地浏览器的传送协议,它能保证高效而准确地传送超文本文档。HTTP 由万维网协会(World Wide Web Consortium)和 Internet 工作小组 IETF(Internet Engineering Task Force)共同合作制定的规范,目前广泛使用的是 HTTP 1.1 版本,当然 HTTP 2.0 现在不少网站也增加了支持。
其发展历史见下表:
版本 | 产生时间 | 主要特点 | 发展现状 |
HTTP/0.9 | 1991 年 | 不涉及数据包传输,规定客户端和服务器之间通信格式,只能 GET 请求 | 没有作为正式的标准 |
HTTP/1.0 | 1996 年 | 传输内容格式不限制,增加 PUT、PATCH、HEAD、 OPTIONS、DELETE 命令 | 正式作为标准 |
HTTP/1.1 | 1997 年 | 持久连接(长连接)、节约带宽、HOST 域、管道机制、分块传输编码 | 正式作为标准并广泛使用 |
HTTP/2.0 | 2015 年 | 多路复用、服务器推送、头信息压缩、二进制协议等 | 逐渐覆盖市场 |
HTTPS 的全称是 Hyper Text Transfer Protocol over Secure Socket Layer,是以安全为目标的 HTTP 通道,简单讲是 HTTP 的安全版,即在 HTTP 下加入 SSL 层,简称为 HTTPS。
HTTPS 的安全基础是 SSL,因此通过它传输的内容都是经过 SSL 加密的,它的主要作用分为以下两种。
现在越来越多的网站和 App 都已经向 HTTPS 方向发展,举例如下。
因此,HTTPS 已经是大势所趋。
注:HTTP 和 HTTPS 协议都属于计算机网络中的应用层协议,其下层是基于 TCP 协议实现的,TCP 协议属于计算机网络中的传输层协议,包括建立连接时的三次握手和断开时的四次挥手等过程。但本书主要讲的是网络爬虫相关,主要爬取的是 HTTP/HTTPS 协议相关的内容,所以这里就不再展开深入讲解 TCP、IP 等相关知识了,感兴趣的读者可以搜索相关资料了解下,如《计算机网络》、《图解 HTTP》等书籍。
我们在浏览器中输入一个 URL,回车之后便会在浏览器中观察到页面内容。
实际上,这个过程是浏览器向网站所在的服务器发送了一个请求,网站服务器接收到这个请求后进行处理和解析,然后返回对应的响应,接着传回给浏览器。
由于响应里包含页面的源代码等内容,浏览器再对其进行解析,便将网页呈现了出来,流程如图 1-3 所示。
此处客户端即代表我们自己的 PC 或手机浏览器,服务器即要访问的网站所在的服务器。
为了更直观地说明这个过程,这里用 Chrome 浏览器开发者模式下的 Network 监听组件来做下演示,它可以显示访问当前请求网页时发生的所有网络请求和响应。
打开 Chrome 浏览器,访问百度 www.baidu.com/,这时候鼠标右键并选择“检查”菜单(或直接按快捷键 F12),即可打开浏览器的开发者工具,如下图所示:
我们切换到 Network 面板,然后重新刷新网页,这时候就可以看到在 Network 面板下方出现了很多个条目,其中一个条目就代表一次发送请求和接收响应的过程,如图所示:
我们先观察第一个网络请求,即 www.baidu.com,其中各列的含义如下。
我们点击这个条目,即可看到其更详细的信息,如图所示。
首先是 General 部分,其中 Request URL 为请求的 URL,Request Method 为请求的方法,Status Code 为响应状态码,Remote Address 为远程服务器的地址和端口,Referrer Policy 为 Referrer 判别策略。
再继续往下可以看到,有 Response Headers 和 Request Headers,它们分别代表响应头和请求头。请求头里带有许多请求信息,例如浏览器标识、Cookie、Host 等信息,这是请求的一部分,服务器会根据请求头内的信息判断请求是否合法,进而作出对应的响应。图 1-5 中看到的 Response Headers 就是响应的一部分,其中包含了服务器的类型、文档类型、日期等信息,浏览器接收到响应后,会解析响应内容,进而呈现网页内容。
下面我们分别来介绍一下请求和响应都包含哪些内容。
请求,英文为 Request,由客户端向服务器发出,可以分为 4 部分内容:请求方法(Request Method)、请求的网址(Request URL)、请求头(Request Headers)、请求体(Request Body)。
下面我们分别予以介绍。
请求方法,英文为 Request Method,用于标识请求客户端请求服务端的方式,常见的请求方法有两种:GET 和 POST。
在浏览器中直接输入 URL 并回车,这便发起了一个 GET 请求,请求的参数会直接包含到 URL 里。例如,在百度中搜索 Python,这就是一个 GET 请求,链接为 www.baidu.com/s?wd=Python,其中 URL 中包含了请求的 query 信息,这里的参数 wd 表示要搜寻的关键字。POST 请求大多在表单提交时发起。比如,对于一个登录表单,输入用户名和密码后,点击 “登录” 按钮,这通常会发起一个 POST 请求,其数据通常以表单的形式传输,而不会体现在 URL 中。
GET 和 POST 请求方法有如下区别:
一般来说,登录时,需要提交用户名和密码,其中包含了敏感信息,使用 GET 方式请求的话,密码就会暴露在 URL 里面,造成密码泄露,所以这里最好以 POST 方式发送。上传文件时,由于文件内容比较大,也会选用 POST 方式。
我们平常遇到的绝大部分请求都是 GET 或 POST 请求。另外,还有一些请求方法,如 GET、HEAD、POST、PUT、DELETE、CONNECT、OPTIONS、TRACE 等,我们简单将其总结为下表。
方 法 | 描 述 |
GET | 请求页面,并返回页面内容 |
HEAD | 类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头 |
POST | 大多用于提交表单或上传文件,数据包含在请求体中 |
PUT | 从客户端向服务器传送的数据取代指定文档中的内容 |
DELETE | 请求服务器删除指定的页面 |
CONNECT | 把服务器当作跳板,让服务器代替客户端访问其他网页 |
OPTIONS | 允许客户端查看服务器的性能 |
TRACE | 回显服务器收到的请求,主要用于测试或诊断 |
本表参考:www.runoob.com/http/http-m…。
请求的网址,英文为 Reqeust URL,它可以唯一确定我们想请求的资源。关于 URL 的构成和各个部分的功能我们在前文已经提及到了,这里就不再赘述。
请求头,英文为 Request Headers,用来说明服务器要使用的附加信息,比较重要的信息有 Cookie、Referer、User-Agent 等。
下面简要说明一些常用的头信息:
因此,请求头是请求的重要组成部分,在写爬虫时,大部分情况下都需要设定请求头。
请求体,即 Request Body 一般承载的内容是 POST 请求中的表单数据,而对于 GET 请求,请求体则为空。
例如,这里我登录 GitHub 时捕获到的请求和响应如图 1-6 所示。
登录之前,我们填写了用户名和密码信息,提交时这些内容就会以表单数据的形式提交给服务器,此时需要注意 Request Headers 中指定 Content-Type 为 application/x-www-form-urlencoded。只有设置 Content-Type 为 application/x-www-form-urlencoded,才会以表单数据的形式提交。另外,我们也可以将 Content-Type 设置为 application/json 来提交 JSON 数据,或者设置为 multipart/form-data 来上传文件。
如下表是 Content-Type 和 POST 提交数据方式的关系
Content-Type | 提交数据的方式 |
application/x-www-form-urlencoded | 表单数据 |
multipart/form-data | 表单文件上传 |
application/json | 序列化 JSON 数据 |
text/xml | XML 数据 |
在爬虫中,如果要构造 POST 请求,需要使用正确的 Content-Type,并了解各种请求库的各个参数设置时使用的是哪种 Content-Type,不然可能会导致 POST 提交后无法正常响应。
响应,即 Response,由服务器返回给客户端,可以分为三部分:响应状态码(Response Status Code)、响应头(Response Headers)和响应体(Response Body)。
响应状态码,即 Response Status Code,表示服务器的响应状态,如 200 代表服务器正常响应,404 代表页面未找到,500 代表服务器内部发生错误。在爬虫中,我们可以根据状态码来判断服务器响应状态,如状态码为 200,则证明成功返回数据,再进行进一步的处理,否则直接忽略。下表列出了常见的错误代码及错误原因。
常见的错误代码及错误原因
状态码 | 说 明 | 详 情 |
100 | 继续 | 请求者应当继续提出请求。服务器已收到请求的一部分,正在等待其余部分 |
101 | 切换协议 | 请求者已要求服务器切换协议,服务器已确认并准备切换 |
200 | 成功 | 服务器已成功处理了请求 |
201 | 已创建 | 请求成功并且服务器创建了新的资源 |
202 | 已接受 | 服务器已接受请求,但尚未处理 |
203 | 非授权信息 | 服务器已成功处理了请求,但返回的信息可能来自另一个源 |
204 | 无内容 | 服务器成功处理了请求,但没有返回任何内容 |
205 | 重置内容 | 服务器成功处理了请求,内容被重置 |
206 | 部分内容 | 服务器成功处理了部分请求 |
300 | 多种选择 | 针对请求,服务器可执行多种操作 |
301 | 永久移动 | 请求的网页已永久移动到新位置,即永久重定向 |
302 | 临时移动 | 请求的网页暂时跳转到其他页面,即暂时重定向 |
303 | 查看其他位置 | 如果原来的请求是 POST,重定向目标文档应该通过 GET 提取 |
304 | 未修改 | 此次请求返回的网页未修改,继续使用上次的资源 |
305 | 使用代理 | 请求者应该使用代理访问该网页 |
307 | 临时重定向 | 请求的资源临时从其他位置响应 |
400 | 错误请求 | 服务器无法解析该请求 |
401 | 未授权 | 请求没有进行身份验证或验证未通过 |
403 | 禁止访问 | 服务器拒绝此请求 |
404 | 未找到 | 服务器找不到请求的网页 |
405 | 方法禁用 | 服务器禁用了请求中指定的方法 |
406 | 不接受 | 无法使用请求的内容响应请求的网页 |
407 | 需要代理授权 | 请求者需要使用代理授权 |
408 | 请求超时 | 服务器请求超时 |
409 | 冲突 | 服务器在完成请求时发生冲突 |
410 | 已删除 | 请求的资源已永久删除 |
411 | 需要有效长度 | 服务器不接受不含有效内容长度标头字段的请求 |
412 | 未满足前提条件 | 服务器未满足请求者在请求中设置的其中一个前提条件 |
413 | 请求实体过大 | 请求实体过大,超出服务器的处理能力 |
414 | 请求 URI 过长 | 请求网址过长,服务器无法处理 |
415 | 不支持类型 | 请求格式不被请求页面支持 |
416 | 请求范围不符 | 页面无法提供请求的范围 |
417 | 未满足期望值 | 服务器未满足期望请求标头字段的要求 |
500 | 服务器内部错误 | 服务器遇到错误,无法完成请求 |
501 | 未实现 | 服务器不具备完成请求的功能 |
502 | 错误网关 | 服务器作为网关或代理,从上游服务器收到无效响应 |
503 | 服务不可用 | 服务器目前无法使用 |
504 | 网关超时 | 服务器作为网关或代理,但是没有及时从上游服务器收到请求 |
505 | HTTP 版本不支持 | 服务器不支持请求中所用的 HTTP 协议版本 |
响应头,即 Response Headers,包含了服务器对请求的应答信息,如 Content-Type、Server、Set-Cookie 等。下面简要说明一些常用的头信息。
响应体,即 Response Body,这可以说是最关键的部分了,响应的正文数据都在响应体中,比如请求网页时,它的响应体就是网页的 HTML 代码;请求一张图片时,它的响应体就是图片的二进制数据。我们做爬虫请求网页后,要解析的内容就是响应体,如图 1-7 所示。
在浏览器开发者工具中点击 Preview,就可以看到网页的源代码,也就是响应体的内容,它是解析的目标。
在做爬虫时,我们主要通过响应体得到网页的源代码、JSON 数据等,然后从中做相应内容的提取。
本节中,我们了解了 HTTP 的基本原理,大概了解了访问网页时背后的请求和响应过程。本节涉及的知识点需要好好掌握,后面分析网页请求时会经常用到。
前面我们也提到了 HTTP 协议从 2015 年起发布了 2.0 版本,相比 HTTP/1.1 来说,HTTP/2.0 变得更快、更简单、更稳定,HTTP/2.0 在传输层做了很多优化,HTTP/2.0 的主要目标是通过支持完整的请求与响应复用来减少延迟,并通过有效压缩 HTTP 请求头字段将协议开销降至最低,同时增加对请求优先级和服务器推送的支持,这些优化一笔勾销了 HTTP/1.1 为做传输优化想出的一系列“歪招”。
有读者这时候可能会问,为什么不叫 HTTP/1.2 而叫 HTTP/2.0 呢?因为 HTTP/2.0 在内部实现上新的二进制分帧层,这是没法与之前的 HTTP/1.x 的服务器和客户端实现向后兼容的,所以直接修改了主版本号为 2.0。
下面我们就来了解下 HTTP/2.0 相比 HTTP/1.1 来说做了哪些优化吧。
HTTP/2.0 所有性能增强的核心就在于这个新的二进制分帧层。在 HTTP/1.x 中,不管是请求(Request)还是响应(Response),它们都是用文本格式传输的,其头部(Headers)、实体(Body)之间也是用文本换行符分隔开的。HTTP/2.0 对其做了优化,将文本格式修改为了二进制格式,使得解析起来更加高效。同时将请求和响应数据分割为更小的帧,并采用二进制编码。
所以这里就引入了几个新的概念:
在 HTTP/2.0 中,同域名下的所有通信都可以在单个连接上完成,该连接可以承载任意数量的双向数据流,数据流是用于承载双向消息的,每条消息都是一条逻辑 HTTP 消息(例如请求或响应),它可以包含一个或多个帧。
简而言之,HTTP/2.0 将 HTTP 协议通信分解为二进制编码帧的交换,这些帧对应着特定数据流中的消息,所有这些都在一个 TCP 连接内复用,这是 HTTP/2.0 协议所有其他功能和性能优化的基础。
在 HTTP/1.x 中,如果客户端要想发起多个并行请求以提升性能,则必须使用多个 TCP 连接,而且浏览器位了控制资源,还会对单个域名有 6-8 个 TCP 连接请求的限制。但在 HTTP/2.0 中,由于又了二进制分帧技术的加持,HTTP/2.0 不用再以来 TCP 连接去实现多路并行了,客户端和服务器可以将 HTTP 消息分解为互不依赖的帧,然后交错发送,最后再在另一端把它们重新组装起来,让我们可以:
这样以来,整个数据传输使性能就有了极大提升:
流控制是一种阻止发送方向接收方发送大量数据的机制,以免超出后者的需求或处理能力。可以理解为,接收方已经太繁忙了,来不及处理收到的消息了,但是发送方还在一直大量发送消息,这样就会出现一些问题。
比如说,客户端可能请求了一个具有较高优先级的大型视频流,但是用户已经暂停视频,客户端现在希望暂停或限制从服务器的传输,以免提取和缓冲不必要的数据。 再比如,一个代理服务器可能具有较快的下游连接和较慢的上游连接,并且也希望调节下游连接传输数据的速度以匹配上游连接的速度来控制其资源利用率等等。
由于 HTTP 是基于 TCP 实现的,虽然 TCP 原生有流量控制机制,但是由于 HTTP/2.0 数据流在一个 TCP 连接内复用,TCP 流控制既不够精细,也无法提供必要的应用级 API 来调节各个数据流的传输。
为了解决这一问题,HTTP/2.0 提供了一组简单的构建块,这些构建块允许客户端和服务器实现其自己的数据流和连接级流控制:
由此可见,HTTP/2.0 提供了简单的构建块实现了自定义策略来调节资源使用和分配,以及实现新传输能力,同时提升了网页应用的实际性能和感知性能。
HTTP/2.0 新增的另一个强大的新功能是,服务器可以对一个客户端请求发送多个响应。 换句话说,除了对最初请求的响应外,服务器还可以向客户端推送额外资源,而无需客户端明确地请求。
如果某些资源客户端是一定会请求的,这时就可以采取服务端推送的技术,在客户端发起一次请求后,额外提前给客户端推送必要的资源,这样就可以相对减少一点延迟时间。例如,服务端可以主动把 JS 和 CSS 文件推送给客户端,而不需要客户端解析 HTML 时再发送这些请求。
服务端可以主动推送,当然客户端也有权利选择是否接收。如果服务端推送的资源已经被浏览器缓存过,浏览器可以通过发送 RST_STREAM 帧来拒收。
另外主动推送也遵守同源策略,即服务器不能随便将第三方资源推送给客户端,而必须是经过双方确认才行,这样也能保证一定的安全性。
HTTP/2.0 的普及是一件任重而道远的事情,一些主流的网站现在已经支持了 HTTP/2.0,主流浏览器现在都已经实现了 HTTP/2.0 的支持,但总的来看,目前大部分网站依然还是以 HTTP/1.1 为主。
另外一些编程语言的库还没有完全支持 HTTP/2.0,比如对于 Python 来说,hyper、httpx 等库已经支持了 HTTP/2.0,但广泛使用的 requests 库依然还是只支持 HTTP/1.1。
本节介绍了关于 HTTP 的一些基础知识,内容不少,需要好好掌握,这些知识对于后面我们编写和理解网络爬虫具有非常大的帮助。
由于本节的内容多数为概念介绍,内容参考了很多书籍、文档、博客,来源如下:
更多精彩内容,请关注我的公众号「进击的 Coder」和「崔庆才丨静觅」。
作者:崔庆才丨静觅
链接:https://juejin.cn/post/7081288652034146312
*请认真填写需求信息,我们会在24小时内与您取得联系。