HTTP 协议又称为超文本传输协议,它是一种通信协议,允许将超文本标记语言(HTML)文档从 Web 服务器传送到客户端的浏览器。

# HTTP 协议特点

HTTP 协议的主要特点可概括如下:

  • 遵循经典的“客户端-服务端”模型
    • 客户端打开一个连接并发出请求,然后等待直到收到服务器端响应或超时
  • 简单
    • HTTP 被设计得简单、易读、可测,对新人友好
    • HTTP 报文(在 HTTP/2 之前)是语义可读的
  • 可拓展
    • HTTP 允许传输任意类型的数据对象
  • HTTP 连接
    • HTTP/1.0:默认为每一对 HTTP 请求/响应都打开一个单独的 TCP 连接
    • HTTP/1.1:引入了持久连接的概念,通过设置 Connection 头部为keep-alive,网络连接可持久、不会关闭,使得对同一个服务器的请求可以继续在该连接上完成,当出现对服务器的后续请求时,该功能避免了建立或者重新建立连接
    • HTTP/2:通过在一个连接中复用消息的方式来让这个连接始终保持
  • 无状态
    • 在同一个连接中,两个执行成功的请求之间是没有关系的
    • HTTP 本质是无状态的,使用 Cookies 可以创建有状态的会话

# URL 详解

URL(Uniform Resource Locator) 地址用于描述一个网络上的资源, 基本格式如下:

schema://host[:port#]/path/.../[?query-string][#anchor]

其中包括:

  • scheme: 指定低层使用的协议(例如:http/https/ftp)
  • host: HTTP 服务器的 IP 地址或者域名
  • port#: HTTP 服务器的默认端口是 80,这种情况下端口号可以省略。如果使用了别的端口,必须指明,例如 http://www.cnblogs.com:8080/
  • path: 访问资源的路径
  • query-string: 发送给 HTTP 服务器的数据
  • anchor: 锚

# HTTP 报文

HTTP 报文有两种类型:Request 请求与 Response 响应,每种都有其特定的格式。

(1) Request 请求。

------------------
Request line
(包括:请求方法、请求的资源、HTTP协议的版本号)
------------------
Request header
(包括:Cache头域、Client头域、Cookie/Login头域、Entity头域、Miscellaneous头域、Transport头域等)
------------------
空行
------------------
Request body
------------------

(2) Response 响应。

------------------
Response line
(包括:HTTP协议的版本号、状态码、消息)
------------------
Response header
(包括:Cache头域、Cookie/Login头域、Entity头域、Miscellaneous头域、Transport头域、Location头域等)
------------------
空行
------------------
Response body
-----

对于无论是 Request 还是 Response 的 header,每个字段都需要去理解的,大家平时可多留意一下浏览器的请求。

# HTTP 状态码

HTTP/1.1 中定义了 5 类状态码, 状态码由三位数字组成,第一个数字定义了响应的类别。

状态码 类别 表达内容
1XX 提示信息 表示请求已被成功接收,继续处理
2XX 成功 表示请求已被成功接收,理解,接受
3XX 重定向 要完成请求必须进行更进一步的处理
4XX 客户端错误 请求有语法错误或请求无法实现
5XX 服务器端错误 服务器未能实现合法的请求

一些常见的状态码也是需要掌握的:

  • 200: OK
  • 302: Found 重定向
  • 304: Not Modified 缓存
  • 400: Bad Request 客户端请求与语法错误
  • 403: Forbidden 服务器拒绝提供服务
  • 404: Not Found 请求资源不存在
  • 500: Internal Server Error 服务器发生了不可预期的错误
  • 503: Server Unavailable 服务器当前不能处理客户端的请求,一段时间后可能恢复正常

# HTTP 请求方法

HTTP 常见的请求方法包括:

  • GET:通常用于获取资源
  • POST:通常用于提交资源,可能会导致状态更改或对服务器产生副作用
  • PUT:通常用于修改资源
  • DELETE:通常用于删除指定的资源
  • OPTION: 描述目标资源的通信选项,比如用于切换到 Websocket 通道

除了以上列出的,HTTP 方法还包括 HEAD/CONNECT/TRACE/PATCH,用来定义客户端的动作行为。一般来说,我们还需要理解 GET 和 POST 的区别,主要包括是否有 body、长度限制、是否可缓存等等。

# HTTP Headers

HTTP 消息头允许客户端和服务器通过 request 和 response 传递附加信息,根据上下文可主要分为:

  • General headers:
    • 可以应用于请求和响应中,但是不能应用于消息内容自身
    • 常见包括:Date、Cache-Control、Connection
  • Request headers
    • 可在 HTTP 请求中使用,并且和请求主体无关
    • Accept、Accept-*、If-*允许执行条件请求
    • Cookie、User-Agent、Referer 描述了请求本身,以确保服务端能正确响应
  • Response headers:
    • 包含有关响应的补充信息
    • Age、Location、Server 被用于描述其位置或服务器本身(名称和版本等)
  • Entity headers:
    • 包含有关实体主体的更多信息
    • 常见包括:Content-Length,Content-Language,Content-Encoding

关于 HTTP 消息头相关内容,需要我们在开发和调试过程中根据实际场景才能了解得更加深入。其中,HTTP Cookie 和浏览器缓存也算是一个较常见的场景。

# 常见的 HTTP 协议场景

下面我们来介绍一下常见的一些 HTTP 协议场景。

HTTP Cookie

前面提到,HTTP 协议是无状态的,这带来了一个问题:用户没有办法在同一个网站中进行连续的交互,比如用户在某个电商网站上将两个商品分别加入了购物车,服务器无法知道这两个操作都来自同一个用户。

HTTP Cookie 可以解决这个问题,它可告知服务端两个请求是否来自同一浏览器,因此可保持用户的登录状态。

Cookie 主要用于以下三个方面:

  • 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
  • 个性化设置(如用户自定义设置、主题等)
  • 浏览器行为跟踪(如跟踪分析用户行为等)

根据生命周期区分,Cookie 可包括两种:

(1) 最简单的 Cookie:浏览器关闭之后它会被自动删除。

(2) 持久性的 Cookie:通过指定过期时间(Expires)或者有效期(Max-Age),指定 Cookie 的一段有效时间。

Session

我们在实际开发中,谈到用户登录态,除了 Cookie 还常常会提到 Session。

Session 是从服务器角度出发,当客户端访问服务器时,将用户会话信息(Session)保存在服务器上,同时将标示 Session 的 SessionId 返回给客户端浏览器,浏览器将这个 SessionId 保存在内存中(比如 Cookie),下次请求可直接带给服务器。服务器会根据这个 SessionId,就能取得客户端的数据信息。

Token

既然谈到 Cookie 和 Session,Token 也可以一并了解下。

以前 Token 更多是在用户授权中使用,例如移动 App 通常采用 Token 进行验证。Token 和 Session 有第一定的类似,但是服务器不保存用户会话信息,而是生成一个 Token 保存在客户端,这个 Token 是加密并确保完整性和不变性的,修改后无效,可保存在客户端,下次请求带给服务器。服务器进行解密后,就能取得客户端的数据信息。

除此之外,Token 还支持跨域访问、无状态等,也能解决 Cookie 劫持(CSRF)的安全问题。