飞翔飞翔
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL教程
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON教程
  • 工具

    • Markdown指南
  • Git

    • GitFlow
  • Quartz

    • Quartz教程
  • Java

    • Java设计模式
  • 缓存

    • Redis教程
联系
阿里云
  • 学习路径
  • HTTP 基础

    • 认识HTTP协议与应用层定位
    • HTTP消息格式与报文结构
    • HTTP请求方法与幂等性
    • HTTP状态码详解
  • 连接与缓存

    • HTTP持久连接与版本演进
    • HTTP缓存机制
  • 状态与协商

    • Cookie与Session状态管理
    • HTTP重定向与内容协商
    • HTTP条件请求与范围请求
  • 安全与加密

    • HTTP认证机制
    • HTTPS与TLS握手
  • 协议演进

    • HTTP2核心特性
    • HTTP3与QUIC
  • 架构与实战

    • HTTP代理服务器与Web缓存
    • HTTP常见攻击与防御
    • HTTP实践工具与抓包分析

HTTP消息格式与报文结构

概念引入

想象你给朋友写一封正式信函:开头写称呼和事由("尊敬的翼王:关于本月服务器维护计划……"),中间分段写正文,结尾署名。HTTP 报文也有类似的"三段式"结构,而且格式更加严格——它就像飞翔公司内部的标准化申请表,每个区域该写什么、写在哪里,都有明确规定。

HTTP 报文(Message) 是客户端与服务器之间传递数据的"信封+信纸",分为请求报文和响应报文两种。理解报文结构,是读懂 HTTP 的第一步。


核心内容

HTTP 报文的三部分结构

无论是请求还是响应,HTTP 报文都由三个部分组成:

┌─────────────────────────────────────┐
│  起始行(Start Line)                 │  ← 第一行,说明"要做什么"或"结果如何"
├─────────────────────────────────────┤
│  首部行(Header Fields)             │  ← 多行键值对,说明附加信息
│  Host: www.feixiang.net             │
│  Content-Type: text/html            │
├─────────────────────────────────────┤
│  (空行,CRLF 分隔)                 │  ← 一个空行,标记首部结束
├─────────────────────────────────────┤
│  实体主体(Entity Body)              │  ← 实际传输的数据(可选)
│  <html>...</html>                   │
└─────────────────────────────────────┘

生活比喻:这就像快递包裹——起始行是快递单上的"收发件信息",首部行是包裹上的"易碎品""轻拿轻放"等标签,实体主体则是包裹里的实际物品。

请求报文结构详解

请求行(Request Line) = 方法 + URL + HTTP 版本

GET /api/employees/hangzai HTTP/1.1
Host: www.feixiang.net
User-Agent: Mozilla/5.0
Accept: application/json

组成部分示例说明
方法(Method)GET要对资源执行的操作,如获取、提交、删除
URL/api/employees/hangzai请求的资源路径
HTTP 版本HTTP/1.1使用的协议版本

飞翔公司场景:空少在前端页面点击"查看航仔资料",浏览器发送上述请求到内部 API 服务器,请求路径中的 hangzai 就是航仔的工号标识。

响应报文结构详解

状态行(Status Line) = HTTP 版本 + 状态码 + 原因短语

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 256
Date: Mon, 09 Jun 2026 04:00:00 GMT

{
  "name": "航仔",
  "dept": "技术部",
  "role": "后端开发",
  "hobby": "钓鱼、看科幻小说"
}
组成部分示例说明
HTTP 版本HTTP/1.1服务器使用的协议版本
状态码(Status Code)200三位数字,表示请求处理结果
原因短语(Reason Phrase)OK状态码的文字描述,便于人类阅读

首部字段分类

HTTP 首部(Header)是报文的"元数据",按用途分为四类:

类别作用常见示例
通用首部请求和响应都可能出现Date、Connection、Cache-Control
请求首部仅出现在请求中Host、User-Agent、Accept、Authorization
响应首部仅出现在响应中Server、Location、Set-Cookie
实体首部描述实体主体属性Content-Type、Content-Length、Last-Modified

飞翔公司场景:风速写了一个算法接口,图妹用 Postman 测试时发现返回乱码。检查发现请求缺少 Accept: application/json 首部,服务器默认返回了 XML。这就是请求首部的重要性。

空行(CRLF)分隔的重要性

HTTP 报文使用 CRLF(Carriage Return + Line Feed,即 \r\n) 作为每行的结束符。首部行和实体主体之间必须有一个完全空白的行(只有一个 CRLF)。

这个空行是"分水岭"——服务器读到连续两个 CRLF,就知道"首部结束了,后面是正文"。如果漏了这个空行,服务器会把正文误当成首部解析,导致错误。

实体主体的可选性

并非所有 HTTP 报文都有实体主体:

场景是否有实体主体示例
GET 请求通常没有查询员工信息,参数在 URL 中
POST 请求有提交请假申请,表单数据在主体中
200 OK 响应有返回航仔的 JSON 资料
204 No Content没有删除草稿成功,无需返回内容
304 Not Modified没有缓存有效,告诉浏览器用本地副本

完整示例:飞翔公司内部员工查询

请求报文(空少查询航仔信息):

GET /api/v1/employees/hangzai HTTP/1.1
Host: hr.feixiang.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

响应报文(服务器返回航仔资料):

HTTP/1.1 200 OK
Date: Mon, 09 Jun 2026 04:00:00 GMT
Server: nginx/1.24.0
Content-Type: application/json; charset=utf-8
Content-Length: 312

{
  "id": "10001",
  "name": "航仔",
  "department": "技术部",
  "position": "后端开发",
  "personality": "沉稳靠谱,话不多但代码干净",
  "hobbies": ["钓鱼", "看科幻小说", "深夜撸串"],
  "joinYear": 2018
}

注意:HTTP 报文每行以 \r\n(CRLF)结束,首部和主体之间有一个空行(即连续的 \r\n\r\n)。上面的示例为可读性去掉了 \r,只保留 \n 换行。实际抓包中 \r\n 是不可见的控制字符。


本篇小结

  • HTTP 报文由三部分组成:起始行、首部行、实体主体
  • 请求报文的起始行叫请求行(方法 + URL + 版本)
  • 响应报文的起始行叫状态行(版本 + 状态码 + 原因短语)
  • 首部字段分四类:通用首部、请求首部、响应首部、实体首部
  • 空行(CRLF) 是首部和实体主体的分界线,不可或缺
  • 实体主体是可选的,GET 请求和 204/304 响应通常没有主体
  • 报文是纯文本格式,便于人类阅读和调试

动手实践

温馨提示: 以下实践示例中涉及的域名(如 www.feixiang.net)、公司场景和接口均为虚构数据,仅用于演示协议原理,实际执行时可能不会产生文档中描述的效果。建议将命令中的域名替换为你自己可访问的真实地址进行练习。

实践:用 curl 查看完整 HTTP 响应

# 显示完整的请求和响应报文(包括首部)
curl -v http://www.feixiang.net 2>&1 | grep -E "(> |< |HTTP)"

# 只显示响应首部
curl -I http://www.feixiang.net

观察响应中的 Server、Content-Type、Date 等首部字段。

实践:用 telnet 手动发送 HTTP 请求

# 连接到服务器(Windows 需先启用 Telnet 客户端)
telnet www.feixiang.net 80

# 然后手动输入以下三行(每行以回车结束),最后多按一次回车:
GET / HTTP/1.1
Host: www.feixiang.net

你会看到服务器返回的原始 HTTP 响应报文。体会"空行分隔"的实际作用。

实践:思考题

  1. 为什么 HTTP 报文要设计成"首部 + 空行 + 主体"的三段式?如果去掉空行直接拼接会有什么后果?
  2. 请求报文中的 Host 首部有什么作用?如果一台服务器托管了多个网站(虚拟主机),缺少 Host 会怎样?
  3. 假设波比要提交一个活动报名表单,应该使用 GET 还是 POST?请求报文和响应报文分别长什么样?

查看思考题答案

上一页
认识HTTP协议与应用层定位
下一页
HTTP请求方法与幂等性