中文RFC文档open in new window

HTTP(Hyper Text Transfer Protocol)超文本传输协议。

请求模型

客户端发送请求,服务器接收响应。

request-model

浏览器行为与HTTP协议(简单版)

处理流程:

  1. 输入网址并回车,从局域网跳到互联网
  2. DNS服务解析域名,拿到IP地址
  3. TCP连接,三次握手
  4. 浏览器发送http请求
  5. 服务器处理请求
  6. 服务器返回HTML响应
  7. 浏览器解析渲染页面
  8. 断开连接,TCP四次挥手

从URL输入到页面展现到底发生什么?

什么是HTTP协议

  • HTTP是超文本传输协议,是从万维网服务器传输到本地浏览器的传输协议。HTTP是基于 TCP/IP 协议来传递数据,如网站的图片、CSS、JS、查询结果等。

  • HTTP协议是由从客户端到服务器的请求和从服务器到客户端的响应的一种约束和规范。

  • 发展历史:

    1. HTTP/0.9 1991
    2. HTTP/1.0 1996
    3. HTTP/1.1 1999
    4. HTTP/2.0 2015
  • HTTP默认端口为80,HTTPS默认端口为43

了解TCP/IP协议栈

为什么叫栈呢?

因为它是分层的,数据结构中的栈结构很相似,协议栈是数据通信一层一层往下传,每一层包相对应的协议,回来的时候一层一层的剥掉向上传。

protocol-stack

为什么有两个协议呢?

  • 最早的TCP/IP协议是逐步发展起来,并不完善;
  • 随着互联网逐步的发展,发现只有一个应层层不够,于是把应用层和网络接口层细化;
  1. 应用层

为用户提供所需要的各种服务(都是直接面向客户的) HTTP、FTP、DNS、SMTP(简单邮件传输协议)、POP3等

  1. 传输层 tcp
  • 为应用层实体提供端到端的通信功能,保证数据包的顺序传送及数据的完整性
  • 主要是TCP(传输控制协议)和UDP(用户数据报协议)
  1. 网络层
  • 也叫ip层,主要解决主机到主机的通信问题
  • IP协议是网际互联层最重要的协议
  1. 链路层
  • 保证物理线路上进行可靠的数据传递
  • 网卡,Mac地址
  1. 物理层
  • 负责比特流在节点之间的传输,俗来说就是把计算机连接起来的物理手段。
  • 硬件,网线、电缆

HTTP在TCP/IP协议栈中的位置

目前普遍应用版本HTTP 1.1,正在逐步向HTTP 2迁移,HTTP默认端口号为80,HTTPS默认端口号为443。 如下图:

http 位置

HTTP的工作工程

一次HTTP操作成为一个事务,过程分为以下四步:

  1. 客户端与服务器需要建立连接。
  2. 建立连接后,客户端发送请求给服务器。
  3. 服务器接收请求后,给予响应的响应信息。
  4. 客户端接收到服务器所返回的信息通过浏览器显示在用户的显示屏上,然后断开与服务器的连接。

如果上述过程中的某一步出现错误了,那么产生错误的信息将返回到客户端上。

📢

事务:当一次工作时,并不能一次性完成,需要分成若干步骤,每个步骤以来上一次,当然也可以不依赖。但当在执行中,若有一个步骤失败了,整个流程都算失败。事务就需要回滚,所有操作都恢复程原始状态,如果有操作数据的话,也需要恢复到原始状态。

请求与响应

请求组成: 请求行、消息报头、空行、请求正文

响应组成: 状态行、消息报头、空行、响应报头

请求行组成:以一个方法符号开头(GET、POST),后面跟着请求的URL和协议版本

状态行组成:服务器HTTP协议版本,状态码和状态文本描述

空行组成: 回车符 + 换行符

为什么有回车跟换行这两个符号?

因为历史遗留的问题,根据最古老打字机的时候回车是复位,换行才是下一行。 ASCII码中,回车符是\r, 换行符\n。

请求方法(http 1.1)

  • GET: 请求指定的页面信息,并返回实体主体

  • POST: 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。

  • HEAD:请求获取响应消息报头

  • PUT: 从客户端向服务器传送的数据取代指定的文档的内容

  • DELETE: 请求服务器删除指定的页面

  • TRACE:请求服务器回送收到的请求信息,主要用于测试或诊断

  • CONNECT: HTTP/1.1协议中预留给能够将连接改为管道⽅式的代理服务器

  • OPTIONS:用于获取目的资源所支持的通信选项,允许客户端查看服务器的性能

OPTIONS

用 options 请求去嗅探某个请求在对应的服务器中都支持哪种请求方法。

什么时候会用到?

  1. 在跨域的情况下,用于确认目标资源是否支持跨域。
  2. 发起“复杂请求”时主动发起的。(复杂请求:除了GET、POST、HEAD以外的请求)

扩展知识点: CRUD

  • create -> post
  • read -> get
  • update -> put
  • delete -> delete

HTTP状态码

状态码由三位数组组成,第一个数字定义了响应类别:

  1. 1xx: 指示信息,表示请求已接收,继续处理

  2. 2xx: 成功,表示请求已被成功接收,理解、接受

  3. 3xx: 重定向,要完成请求必须进行更进一步的操作

  4. 4xx: 客户端错误,请求有语法错误或请求无法实现

  5. 5xx: 服务端错误,服务器未能实现合法的请求

http-code
状态码描述
301永久重定向
302临时重定向
303POST重定向为GET
304资源未改变,直接读取客户端缓存
305被请求的资源必须经过制定的代理才能被访问。(不支持使用)
307与302类似,只不过是针对POST方法的请求不允许更改方法
4001. 语义有误,请求无法被客户端理解;2. 请求参数有误;
402被保留使用的非标准客户端错误状态响应码,创建最初目的是用于数字现金或微型支付系统。
403服务器拒绝授权访问
404资源丢失,不知道是临时还是永久丢失
406服务器无法提供与`Accept-Charset
408响应空闲码,服务器想要将没有在使用的连接关闭
409请求与服务器目标资源的状态相冲突
410资源永久丢失,并且响应状态默认会被缓存
413请求主体大小超出了服务器处理限度
417服务器无法满足Expect请求消息投中的期望条件
418黑客文化,表示服务器拒绝冲泡咖啡,因为它是个茶壶
420Twitter Search与Trends API在客户端被限速的情况下返回(非官方状态码)
422服务器无法处理请求包含的指令
500服务器内部错误

常用请求报头

key/value描述
Accept用于指定客户端接受哪些类型的信息;一般用于指定可接受的内容编码格式;
Accept: image/gif图片的格式类型
Accept: text/htmlAccept-Charset接受的字符集
Accept: gzip服务器规定数据是否压缩,浏览器会解压,不需要手动解压
Accept: application/json传输JSON格式文件
Accept: Language告诉服务器客户端语言类型,一般用于多语言包的自动推送
Connection: keep-alive保持长连接,http 1.1开始,默认保持长连接
Cookie把本地cookie拿出来,通过键值对key=value的形式拼接起来
Host主要用于指定被请求资源的网络主机地址和端口号,它一般是从HTTP URL地址中提取出来的,发送请求时,这个报头是必须的
Referer来源,访问当前页面的上一页是谁,一般可以防止盗链,做一些简单的爬虫
User-Agent浏览器、系统信息

常用的响应报头

key/value描述
Allow服务器支持哪些请求方法
Location用于重定向到新的资源地址。Location响应报头域通常用在重定向的时候。
Server包含服务器用来处理请求的软件嘻嘻。与User-Agent请求报头所对应
Cache-control缓存相关
Content-Encoding压缩格式。与Accept: gzip 请求报头所对应
Date服务器当前的GMT时间
Expires资源什么时候过期
Last-Modified文档最后修改时间
Etag指纹,当内容改变了,指纹也会跟着变
Server服务器名称
Set-Cookie设置cookie
  1. Cookie 由服务器生成,或者通过api在浏览器产生(很少,不常用),保存在客户端。随客户端每一个请求发送该url下的所有cookie到服务器端。
  2. Session 由服务器生成,保存在服务器。通过唯一的值sessionID来区别每一个用户。SessionId随每个请求发送到服务器,服务器根据SessionId来识别客户端,再通过session的key获取值。有的时候它被放到缓存里边做共享。
  • 与Cookie相关的HTTP扩展头
    1. Cookie: 客户端将服务器设置的Cookie返回给服务器;
    2. Set-Cookie: 服务器向客户端设置Cookie;(在浏览器目录底下,有专门保存cookie的,保存在硬盘上)
  • 服务器在响应消息用Set-Cookie 头将Cookie 的内容回送给客户端,客户端在新的请求中将相同的内容携带在Cookie投中发送给服务器,从而实现会话的保持。

Session 使用

  • 使用Cookie来实现
  • 使用URL回显来实现
request-cookie

图解:

  1. 当客户端第一次访问服务器时,服务器会检查是否有携带cookie;

  2. 如果有携带cookie,服务器则会验证cookie,是否有效;如果不带,则说明客户端是第一次请求或者没有登录,这时候服务器就会下发凭据,生成一个新的session,在session里面生成唯一的id,通过set-cookie设置到客户端内;

  3. 客户端会保存cookie,每次请求都会带上cookie作为凭据;

HTTP缓存机制

缓存有浏览器缓存也有服务器缓存; 缓存一般存放经常要访问的数据;

缓存会根据请求保存输出内容的副本,例如html页面,图片,文件,当 下一个请求来到的时候:如果是相同的URL,缓存直接使用副本响应访 问请求,而不是向源服务器再次发送请求。

cache

缓存优点

  1. 减少相应延迟

  2. 减少网络带宽消耗

两种缓存策略

  • 强制缓存

  • 协商缓存

HTTP 1.0: 基于Pragma & Expires的缓存实现

  • Pragma
  • Expire

HTTP 1.1 Cache-Control: 相对过期时间

这三者的优先级顺序为: Pragma > Cache-Control > Expires

强缓存

利用http头中的Expires和Cache-Control两个字段来控制的,用来表示资源的缓存时间

普通刷新会忽略它,但不会清除它,需要强制刷新。浏览器强制刷新,请求会带上 Cache-Control:no-cache 和 Pragma:no-cache

  • Expires (http 1.0)

  • Cache-Control

协商缓存

协商缓存就是由服务器来确定缓存资源是否可用,所以客户端与服务器端要通过某种标识来进行通信,从而让服务器判断请求资源是否可以缓存访问。

  • Etag / If-None-Match,相当于指纹。只要内容变了,就会重新请求。

  • Last-Modified / If-Modified-Since,最后修改时间。 但是Last-Modified 有个问题,时间戳变了可能资源没变,这样就会造成服务器资源浪费,所以优先走 Etag 策略(Etag 哈希变了资源内容必定会变)

缓存优先级

Cache-Control > Expires > Etag > Last-modify

Request/Response Headers

Web页面设计中,介绍HTTP请求可以提高页面响应速度。浏览器在第一次访问页面时下载的资源会缓存起来,第二次访问时会判断在缓存中是否已有该资源并且有没有更新过,如果已有该资源且没有更新过,则去缓存去取,这样减少了下载资源的时间。原理上是通过HTTP Rquest Header中的 if-modified-since 和Response Headers中的last-modified来实现(还有一对组合If-None-Match和Etag,类似),HTTP请求把if-modified-sincede 时间传给服务端,服务端把last-modified时间与之对比,如果相同,则意味着文件没有改动,则返回304,浏览器则从缓存中获取资源,无需下载。

协商缓存 last-modified / if-modified-since

Response Headers

last-modified: Wed, 16 May 2020 12:57:16 GMT

Request Headers

if-modified-since: Wed, 16 May 2020 12:55:38 GMT

原理: 服务器端返回资源时,如果头部带上了 last-modified,那么资源下次请求时就会把值加⼊到请求头 if-modified-since中,服务器可以对⽐这个值,确定资源是否发⽣变化,如果没有发⽣变化,则返回 304


协商缓存 etag / if-none-match

Response Headers

etag: "D5FC8B85A045FF720547BC36FC872550"

Request Headers

if-none-match: "D5FC8B85A045FF720547BC36FC872550"

原理: 服务器端返回资源时,如果头部带上了 etag,那么资源下次请求时就会把值加⼊到请求头 if-none-match 中,服务器可以对⽐这个值,确定资源是否发⽣变化,如果没有发⽣变化,则返回 304


强缓存 Expires

Request Headers

expires: Thu, 16 May 2020 03:05:59 GMT

原理: 在 http 头中设置⼀个过期时间,在这个过期时间之前,浏览器的请求都不会发出,⽽是⾃动从缓存中读取⽂件,除⾮缓存被清空,或者强制刷新。缺陷在于,服务器时间和⽤户端时间可能存在不⼀致,所以 HTTP/1.1 加⼊了 cache-control 头来改进这个问题


强缓存 cache-control

Request Headers

原理: 设置过期的时间⻓度(秒),在这个时间范围内,浏览器请求都会直接读缓存。当 expires 和 cache-control 都存在时,cache-control 的优先级更⾼

小结

expires也是需要在服务端配置(具体配置也根据服务器而定),expires添加的是该资源过期的日期,浏览器会根据该过期日期与客户端时间对比,如果过期时间还没到,则会去缓存中读取该资源,如果已经到期了,则浏览器判断为该资源已经不新鲜要重新从服务端获取。通过这种方式,可以实现直接从浏览器缓存中读取,而不需要去服务端判断是否已经缓存,避免了这次http请求。值得注意的是expires时间可能存在客户端时间跟服务端时间不一致的问题。所以,建议expires结合Cache-Control一起使用,大型网站中一起使用的情况比较多见

参考链接

HTTP强缓存和协商缓存open in new window

彻底弄懂HTTP缓存机制及原理open in new window

Last Updated:
Contributors: kk