HTTP 学习笔记:简记 URI、URL、HTTP Message、MIME、HTTPS

256 阅读8分钟

HTTP, Hyper Text Transport Protocol

HTTP 基于 TCP 实现了可靠网络通信,屏蔽了【确保消息的完整性和顺序性等】具体通信细节,为开发者和用户都提供了很大的方便

既然是进行通信,那就意味着信息和资源的传递——【资源】一词意味着相当多种类的内容,从静态的文档、图片、视频,到动态的网络服务——比如我们常用的各种 app ,它们给我们展示的图片和视频是静态资源,根据我们的身份提供专门为我们准备的内容是动态资源

URI, Uniform Resource Identifier

全世界每个被服务器提供的资源都有一个名字,这个名字就是 URI,客户端通过 URI 来定位资源并进行传输。

比如给定这样一个URI: http://www.gov.cn/govweb/xhtml/2016gov/images/public/logo_wz1.jpg

浏览器就能取回下面这个图片资源:

URI 有两种具体的实现方式,分别是 URL 和 URN。但后者目前基本没有应用实例,所以在很多语境下 URI 等同于 URL (比如上面例子中的链接就是一个 URL )

URL, Uniform Resource Locator

URL 告诉我们该通过什么方式、到哪里获取到我们想要的资源。比如上面的图片的链接http://www.gov.cn/govweb/xhtml/2016gov/images/public/logo_wz1.jpg 。一般来说, URL 都可以分为三个部分来看:

  • 第一段是协议名(正式的名字叫 scheme ),就是例子中的 http:// 。说明,如果想要这个资源,要使用 http 协议进行连接(当然还有不少其他类型的协议,比如 HTTPS、 FTP 等)
  • 第二段是 IP 地址,这里是 www.gov.cn 。说明这个资源在域名为 www.gov.cn 的这台服务器(域名通过 DNS 转换为 IP 地址,所以访问网站本质上还是通过 IP 地址进行的)
  • 第三段是资源名,如 /govweb/xhtml/2016gov/images/public/logo_wz1.jpg 说明了这个图片资源在这台服务器上的什么地方、叫什么名字

绝大多数的 URL 基本都符合下面的格式:

<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>

比如用 bing 搜一个”abc“,那 url 大概就是这样的:https://cn.bing.com/search?q=abc,内容都可以和上面的格式对上(省略了相当多的字段)。问号? 后面的叫做【Query Strings】,实际上多数的网站都用这个来传递送给服务器的参数供服务器解析,就比如刚刚那个例子。如果有多个参数要传递,则可以用& 连接多个参数。

又比如,请求一个 ftp 也许是这样的:ftp://anonymous:mypwd@ftp.prep.ai.mit.edu/pub/gnu,内容也都可以和上面的格式对上(同样省略了一些字段)

最后那个 frag 其实是 fragment 的意思,在实际应用上基本都是用来给 html 里面的锚点进行定位的

URN, Uniform Resource Name

URN 就是给特定资源的独一无二的名称,就像一个 ISBN 号标记唯一一本书一样。

博主个人见过的唯一一个实例,是 IPFS 项目——在其系统内部,使用资源的 hash 值作为资源的唯一标记进行访问。由于其采用的 SHA 的空间足够大,所以理论上不存在碰撞问题

这里就不多讨论了

HTTP Message(HTTP 消息)

HTTP 的通信交互都是一问一答的,这 ”问“ 和 ”答“ 就叫做 【HTTP 消息】

HTTP 消息分为 Request 和 Respond,两者均由头部(Headers)和消息正文(Body)组成,如下图所示

请求 Request

格式: 下图是访问百度的一个请求头实例,可以和上面对应着看,应该很容易看懂

  • 请求行(Start-line)
    • 请求方法(Method,此处仅说一下 GET 和 POST):
      • GET:一般不用报文中的请求数据传值,而是直接将参数和 URL 拼在一起,明文写在地址栏中。地址栏中填入的 ? 隔开 URL 和请求参数,多个参数用 & 隔开。浏览器支持的总长一般不超过 8182 个字符(IE:2083)。对于非 ASCII 字符,经 BASE64 编码发送,值中的 %XX 表示 XX 是 ASCII 的 hex 表示
      • POST:一般将参数和数据放在报文的【请求数据】中,以 <名称, 值> 对的形式保存,可传大量数据(理论上无限制)
  • 头部(HTTP Headers):关键字: 值 对组成,每行一对。请求头部通知服务器有关于客户端请求的信息,下面举几个例子
    • Authorization:授权信息,常出现在对服务器发送的 WWW-Authenticate 头的应答中
    • Content-Length:请求消息正文的长度
    • Cookie:可以用来在用户处缓存一些数据(比如用于存储一些状态、进行身份验证等。各浏览器一般限制每个域名存 50 个 cookie,总大小不超过 4MB )
    • Content-Type:定义文件类型、网页编码,决定浏览器如何读取该数据。比如某些链接点击后展开空的新页面随即开始下载文件。此处详细内容见下面的 MIME
    • Referer:表明该请求来自哪个 URL (比如从一个站点)
  • 空行(Empty line):标明 header 的边界
  • 请求数据(Body)
    • POST 例:对于 user:admin, password:123 ,数据为 user=admin&password=123

响应 Response

下图是访问百度的一个响应头实例 与请求类似,响应也可以分为四个部分

  • 响应头:描述服务器信息、数据信息等
  • 响应体:大致可分为三类,可以是已知长度的单个文件(其 body 可由 Content-Type 和 Content-Length 定义)、未知长度的单个文件(通过将 Transfer-Encoding 设置为 chunked 使用 chunks 编码)和由多个body分别存不同信息段的数据组成(少见)

实际上,Header 还可以分类为 Request headers、General headers、Entity headers,如下图所示:

请求报文:

响应报文: 如上图所示,头其实还可以分类为通用头和实体头:

  • 通用头:请求、响应均支持的头域
  • 实体头:包含实体信息的头。实体信息一般由实体头和实体组成

MIME: Multipurpose Internet Mail Extensions

MIME 类型,标记了【要被传输的数据的类型】,用来表示文档、文件或字节流的性质和格式——比如发送的数据是什么类型(比如文本、图片、音频、视频、代码等)、发送的数据有多大等。

对于什么数据该叫什么名字这件事,是由一个叫做 IANA 的大组织规定的,具体可见:www.iana.org/assignments… 截止本文写作时的2020年10月,大概有2000种不同的标记

Web 服务器和客户端都会对发送的 HTTP 对象附上一个 MIME 类型说明,这样两端在收到数据时,就都可以根据 MIME 类型来决定如何对待收到的数据(比如对纯粹的文本,浏览器就可以直接显示出来。如果是要被下载的文件,就会调起浏览器的文件下载器)

浏览器通常使用MIME类型(而不是文件扩展名)来确定如何处理URL,因此Web服务器在响应头中添加正确的MIME类型非常重要。如果配置不正确,浏览器可能会曲解文件内容,网站将无法正常工作,并且下载的文件也会被错误处理

类型举例:

text/plain
text/html
image/jpeg
video/mp4

【application 意味着是某种二进制数据】
application/json
application/javascript
application/octet-stream  一般的二进制流,如文件下载

【可被用来发包含多段内容的表单,表单里可以含文件,实现上传】
multipart/form-data

HTTP 下面的 Socket

HTTP 是基于 TCP 的,而 TCP 的具体数据传输则要通过 Socket 进行。

Socket ,是用标准 UNIX File Descriptions 与其他程序沟通的方式

首先,浏览器通过 DNS 获取到所请求域名的 IP 地址(若直接对 地址:端口 的端点(Endpoint)进行请求,则跳过此步),然后与端点进行三次握手,建立 TCP Socket:

  1. 发送端发送连接请求的报文
  2. 服务端收到请求连接的报文,向发送端返回报文
  3. 发送端确认收到了正确的服务端报文,再次发送确认报文

接下来进行 TCP 通信,直至需要关闭连接。通常服务器返回结果后就会关闭连接。但若请求中包含 Connection:keep-alive ,则会保持 TCP 连接(也就是【长连接】,HTTP1.1 默认都是长连接了)

HTTPS——“HTTP Over TLS”

HTTPS 就是 HTTP Over TLS,目前用的主要是 TLS1.1 和 TLS1.2

HTTPS 需要提供的特性:

  • 客户端和服务器的身份认证:双方都需要有办法验证对方的身份,比如用户不会希望访问一个假的银行网站,银行网站也不会希望允许一个冒牌的用户进行操作
  • 保证传输数据的完整性:客户端和服务器通信的内容不能被中间的坏人篡改
  • 加密通信:防止通信内容被窃取
  • 高效:不能让通信的性能下降太多

目前采用的 HTTPS 方案,直接在 HTTP 下面一层增加了 TLS 协议,安全性由 TLS 保障,而不需要在 HTTP 协议层做太多的修改

主要的修改内容,基本上就是将原本 TCP 上面的输入和输出换成 TLS 的输入和输出,并加入一些新的通信步骤来完成保证安全相关的操作。

后续会另写一篇文章来更详细讲讲 HTTPS 。