HTTP(Hypertext Transfer Protocol)是互联网中最常用的协议之一,它定义了客户端(如浏览器)与服务器之间的通信方式。每次客户端请求一个网页、图片或其他资源时,都会发起一个 HTTP 请求。


一、HTTP 请求消息的组成

HTTP 请求消息包含三部分:

  1. 请求行(Request Line):指示请求的方式(如 GET、POST)、请求的目标资源以及使用的协议版本。
  2. 请求头部(Request Headers):提供请求的元数据,包括客户端的配置信息、期望的响应格式等。
  3. 消息体(Message Body):可选部分,主要在 POST、PUT 等请求中使用,用于传输数据(如表单、文件等)。

示例 HTTP 请求

我们先看一个典型的 HTTP 请求的例子:

1
2
3
4
5
6
7
GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

该请求是客户端请求服务器上的 /index.html 页面,接下来我们会逐步解析这条 HTTP 请求消息的每个部分。


二、请求行(Request Line)

请求行是 HTTP 请求的第一行,包含以下三个部分:

  • 请求方法(HTTP Method)
  • 请求目标(Request Target,通常是 URL 的路径部分)
  • HTTP 版本(HTTP Version)

2.1 请求方法

HTTP 协议支持多种请求方法,最常见的包括:

  • GET:请求服务器返回指定资源的内容,一般用于获取数据,不包含请求体。
  • POST:向服务器提交数据(如表单数据),数据包含在请求体中。
  • PUT:向服务器发送数据并更新指定资源。
  • DELETE:请求服务器删除指定的资源。
  • HEAD:类似 GET,但只请求头部信息,不返回实际的资源数据。
  • OPTIONS:用于查询服务器支持的请求方法。
  • PATCH:部分更新资源。

2.2 请求目标

请求目标通常是相对于服务器根路径的资源路径。例如:

1
GET /index.html HTTP/1.1

这里的 /index.html 就是请求目标,表示客户端希望获取服务器上的 index.html 文件。这个路径是相对于服务器的主机名的(如 www.example.com)。

2.3 HTTP 版本

HTTP 请求行的最后一个部分是 HTTP 版本号。常见的版本有:

  • HTTP/1.0:最早的 HTTP 版本,每次请求结束后关闭连接。
  • HTTP/1.1:支持持久连接和流水线处理(即同一个连接上可以发出多个请求)。
  • HTTP/2:优化了性能,支持多路复用,减少了请求之间的等待时间。

在请求行中,客户端指明使用的 HTTP 版本,服务器会根据此版本来回应请求。


三、请求头部(Request Headers)

请求头部由一系列的键值对组成,提供了有关客户端环境、请求上下文和客户端希望如何处理响应的附加信息。

常见的请求头部

  1. Host

    Host: www.example.com

    指定请求目标的主机名和端口。对于 HTTP/1.1 请求,Host 头是必须的,因为服务器可能托管多个域名。

  2. User-Agent

    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)

    描述了发出请求的客户端软件。通常是浏览器、操作系统及其版本号等信息。服务器可以根据 User-Agent 提供差异化响应(例如移动端和桌面端网页可能不同)。

  3. Accept

    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp

    告知服务器客户端可以接受的响应数据类型(MIME 类型)。例如,text/html 表示客户端期望返回 HTML 网页,image/webp 表示可以接受 WebP 格式的图片。

  4. Accept-Language

    Accept-Language: en-US,en;q=0.5

    表示客户端首选的语言环境。服务器可以根据此信息返回不同的语言版本。

  5. Accept-Encoding

    Accept-Encoding: gzip, deflate, br

    客户端支持的压缩算法,服务器可以根据此信息选择以何种压缩格式传输响应数据。常见的压缩方式包括 gzipdeflatebr(Brotli)。

  6. Connection

    Connection: keep-alive

    表示是否保持 TCP 连接打开。keep-alive 表示浏览器希望与服务器保持连接,避免为每个请求重新建立 TCP 连接。

自定义请求头部

开发者可以自定义请求头部,例如在 REST API 中可能会用到 Authorization 头部,用于提供访问令牌:

1
Authorization: Bearer <token>

四、消息体(Message Body)

GET 请求 vs POST 请求

  • GET 请求 通常不带消息体,请求的数据通过 URL 的查询参数传递。例如:

    1
    
    GET /search?q=linux HTTP/1.1
    
  • POST 请求 可以携带消息体,用于传输表单数据或文件。例如,一个典型的 POST 请求体可能是:

    1
    2
    3
    4
    5
    
    POST /login HTTP/1.1
    Host: www.example.com
    Content-Type: application/x-www-form-urlencoded
    
    username=admin&password=123456
    

Content-Type

当请求包含消息体时,客户端需要通过 Content-Type 头部指定消息体的数据格式。常见的格式包括:

  • application/x-www-form-urlencoded:用于传输表单数据。
  • multipart/form-data:用于上传文件。
  • application/json:用于传输 JSON 数据。

五、HTTPS 请求与加密

如果使用 HTTPS 进行请求,整个 HTTP 请求消息都会通过 TLS(传输层安全) 加密。HTTPS 的工作流程如下:

  1. TLS 握手:客户端和服务器通过 TLS 协议建立安全的加密连接。
  2. 加密通信:HTTP 请求头部和消息体被加密,并通过安全通道传输。
  3. 解密与处理:服务器收到加密的请求后,进行解密并处理请求。

通过 HTTPS,加密了客户端与服务器之间的所有通信,保护用户隐私。


六、常见工具和调试方式

在开发过程中,我们经常需要调试 HTTP 请求。常用的工具包括:

  • curl:命令行工具,用于发送 HTTP 请求并查看服务器的响应。
  • 浏览器开发者工具:现代浏览器(如 Chrome、Firefox)内置的开发者工具,可以在 “Network” 标签下查看详细的 HTTP 请求和响应。
  • Postman:用于构建、测试和调试 API 请求的强大 GUI 工具。

示例:使用 curl 发送 GET 请求

1
curl -v https://www.example.com/index.html

该命令会显示详细的 HTTP 请求和响应,包括请求行、头部和响应的状态码。