You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
请求行大概长这样 GET /images/logo.gif HTTP/1.1,基本由请求方法、URL、协议版本组成。
请求方法
GET:向指定的资源发出“显示”请求。该方法应该只用在读取数据,而不应当被用于产生"副作用”的操作中,例如在网络应用程序中。其中一个原因是 GET 可能会被网络爬虫等随意访问。GET 上要在 url 之外带一些参数就只能依靠 url 上附带 querystring。
HEAD:与 GET 方法一样,都是向服务器发出指定资源的请求。只不过服务器将不传回资源的本文部分。它的好处在于,使用这个方法可以在不必传输全部内容的情况下,就可以获取其中“关于该资源的信息”(元信息或称元数据)。
PUT:向指定资源位置上传其最新内容。PUT 方法是幂等的方法,一般用于整体资源的更新。
PATCH:与 PUT 请求类似,同样用于资源的更新。PATCH 一般用于资源的部分更新。当资源不存在时,PATCH 会创建一个新的资源,而 PUT 只会对已经存在的资源更新。
POST:向指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件)。数据被包含在请求本文中。这个请求可能会创建新的资源或修改现有资源,或二者皆有。每次提交,表单的数据被浏览器用编码到 HTTP 请求的 body 里。浏览器发出的 POST 请求的 body 主要有有两种格式,一种是 application/x-www-form-urlencoded 用来传输简单的数据,大概就是key1=value1&key2=value2这样的格式。另外一种是传文件,会采用 multipart/form-data 格式。采用后者是因为前者对于文件这种二进制的数据非常低效。
HTTP
超文本传输协议(英语:HyperText Transfer Protocol,缩写:HTTP)是一种用于分布式、协作式和超媒体信息系统的应用层协议。HTTP 是万维网的数据通信的基础。
HTTP 是一个客户端(用户)和服务端(网站)之间请求和应答的标准,通常使用 TCP 协议。通过使用网页浏览器、网络爬虫或者其它的工具,客户端发起一个 HTTP 请求到服务器上指定端口(默认端口为 80)。我们称这个客户端为用户代理程序。应答的服务器上存储着一些资源,比如 HTML 文件和图像。我们称这个应答服务器为源服务器。(在用户代理和源服务器中间可能存在多个“中间层”,比如代理服务器、网关或者隧道)
协议:规定了客户端与服务器双方必须遵守约定好的数据传输格式
一个完成的 HTTP 请求
TCP 三次握手
传输控制协议(英语:Transmission Control Protocol,缩写:TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
TCP 用三次握手过程创建一个连接。在连接创建过程中,很多参数要被初始化,例如序号被初始化以保证按序传输和连接的强壮性。
TCP 连接的正常创建
一对终端同时初始化一个它们之间的连接是可能的。但通常是由一端打开一个套接字(socket)然后监听来自另一方的连接,这就是通常所指的被动打开(passive open)。服务器端被被动打开以后,用户端就能开始创建主动打开(active open)。
协议内容
请求(Request)
客户端发送一个 HTTP 请求到服务端的格式:
请求行大概长这样
GET /images/logo.gif HTTP/1.1
,基本由请求方法、URL、协议版本组成。请求方法
application/x-www-form-urlencoded
用来传输简单的数据,大概就是key1=value1&key2=value2
这样的格式。另外一种是传文件,会采用multipart/form-data
格式。采用后者是因为前者对于文件这种二进制的数据非常低效。Post 和 Get 的区别?
常见状态码
状态代码的第一个数字代表当前响应的类型:
通用首部
常见请求头
keep-alive
当一个网页打开完成后,客户端和服务器之间用于传输 HTTP 数据的 TCP 连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。close
代表一个 Request 完成后,客户端和服务器之间用于传输 HTTP 数据的 TCP 连接会关闭, 当客户端再次发送 Request,需要重新建立 TCP 连接。常见响应头
HTTP2
HTTP/2 相比于 HTTP/1,可以说是大幅度提高了网页的性能。
HTTPS
HTTPS 的主要作用是在不安全的网络上创建一个安全信道,并可在使用适当的加密包和服务器证书可被验证且可被信任时,对窃听和中间人攻击提供合理的防护。
HTTP 不是安全的,所有传输的内容都是明文,而且攻击者可以通过监听和中间人攻击等手段,获取网站帐户和敏感信息等。HTTPS 的设计可以防止前述攻击,在正确配置时是安全的。
HTTPS 是有两部分组成:HTTP + SSL/TLS,也就是在 HTTP 上又加了一层处理加密信息的协议。服务端和客户端的信息传输都会通过 TLS(传输层安全性协议) 进行加密,所以传输的数据都是加密后的数据。默认端口为 443。
HTTPS 和 HTTP 协议相比提供了:
浏览器缓存
web 缓存
在 Web 应用领域,Web 缓存大致可以分为以下几种类型:
浏览器缓存
当一个客户端请求 web 服务器, 请求的内容可以从以下几个地方获取:服务器、浏览器缓存中或缓存服务器中。这取决于服务器端输出的页面信息。
可以缓存的文件类型
页面文件有三种缓存状态
浏览器缓存机制
很多时候,大家倾向于将浏览器缓存简单地理解为“HTTP 缓存”。但事实上,浏览器缓存机制有四个方面,它们按照获取资源时请求的优先级依次排列如下:
大家对 HTTP Cache(即 Cache-Control、expires 等字段控制的缓存)应该比较熟悉,如果对其它几种缓存可能还没什么概念,我们可以先来看一张线上网站的 Network 面板截图:
大家注意一下非数字——即形如“(from xxx)”这样的描述——对应的资源,这些资源就是我们通过缓存获取到的。其中,“from memory cache”对标到 Memory Cache 类型,“from ServiceWorker”对标到 Service Worker Cache 类型。至于 Push Cache,这个比较特殊,是 HTTP2 的新特性。HTTP 缓存是最主要、最具有代表性的缓存策略。
无法被浏览器缓存的请求
HTTP 缓存机制
HTTP 缓存是我们日常开发中最为熟悉的一种缓存机制。它又分为强缓存和协商缓存。优先级较高的是强缓存,在命中强缓存失败的情况下,才会走协商缓存。
强缓存
强缓存是利用 http 头中的 Expires 和 Cache-Control 两个字段来控制的。强缓存中,当请求再次发出时,浏览器会根据其中的 expires 和 cache-control 判断目标资源是否“命中”强缓存,若命中则直接从缓存中获取资源,不会再与服务端发生通信。
其中 Expires 是一个时间戳,当服务器返回响应时,在 Response Headers 中将过期时间写入 expires 字段。
接下来如果我们试图再次向服务器请求资源,浏览器就会先对比本地时间和 expires 的时间戳,如果本地时间小于 expires 设定的过期时间,那么就直接去缓存中取这个资源。
由于客户端时间与服务器端可能存在的时间差异,HTTP1.1 新增了 Cache-Control 字段来完成 expires 的任务。使用相对时间的方式进行标记。
在 Cache-Control 中,我们通过 max-age 来控制资源的有效期,max-age 是 31536000 秒,它意味着该资源在 31536000 秒以内都是有效的。
协商缓存
协商缓存是浏览器与服务器合作之下的缓存策略,是否命中缓存依赖于浏览器与服务器的通信结果。
协商缓存机制下,浏览器需要向服务器去询问缓存的相关信息,进而判断是重新发起请求、下载完整的响应,还是从本地获取缓存的资源。
如果服务端提示缓存资源未改动(Not Modified),资源会被重定向到浏览器缓存,这种情况下网络请求对应的状态码是 304(如下图)。
协商缓存的实现:从 Last-Modified 到 Etag
Last-Modified 是一个时间戳,如果我们启用了协商缓存,它会在首次请求时随着 Response Headers 返回:
随后我们每次请求时,会带上一个叫 If-Modified-Since 的时间戳字段,它的值正是上一次 response 返回给它的 last-modified 值:
服务器接收到这个时间戳后,会比对该时间戳和资源在服务器上的最后修改时间是否一致,从而判断资源是否发生了变化。如果发生了变化,就会返回一个完整的响应内容,并在 Response Headers 中添加新的 Last-Modified 值;否则,返回如上图的 304 响应,Response Headers 不会再添加 Last-Modified 字段。
使用 Last-Modified 存在一些弊端,这其中最常见的就是这样两个场景:
我们编辑了文件,但文件的内容没有改变。服务端并不清楚我们是否真正改变了文件,它仍然通过最后编辑时间进行判断。因此这个资源在再次被请求时,会被当做新资源,进而引发一次完整的响应——不该重新请求的时候,也会重新请求。
当我们修改文件的速度过快时(比如花了 100ms 完成了改动),由于 If-Modified-Since 只能检查到以秒为最小计量单位的时间差,所以它是感知不到这个改动的——该重新请求的时候,反而没有重新请求了。
这两个场景其实指向了同一个 bug——服务器并没有正确感知文件的变化。为了解决这样的问题,Etag 作为 Last-Modified 的补充出现了。
Etag 是由服务器为每个资源生成的唯一的标识字符串,这个标识字符串是基于文件内容编码的,只要文件内容不同,它们对应的 Etag 就是不同的,反之亦然。因此 Etag 能够精准地感知文件的变化。
Etag 和 Last-Modified 类似,当首次请求时,我们会在响应头里获取到一个最初的标识符字符串,举个,它可以是这样的:
那么下一次请求时,请求头里就会带上一个值相同的、名为 if-None-Match 的字符串供服务端比对了:
Etag 的生成过程需要服务器额外付出开销,会影响服务端的性能,这是它的弊端。因此启用 Etag 需要我们审时度势。正如我们刚刚所提到的——Etag 并不能替代 Last-Modified,它只能作为 Last-Modified 的补充和强化存在。 Etag 在感知文件变化上比 Last-Modified 更加准确,优先级也更高。当 Etag 和 Last-Modified 同时存在时,以 Etag 为准。
HTTP 缓存流程图
首次请求:
再次请求:
浏览器的同源策略
参考资料
The text was updated successfully, but these errors were encountered: