HTTP
HTTP 基础知识
HTTP(超文本传输协议)是
网络上的交流。
HTTP 的核心基于两个基本思想:
- 无状态模型
- 客户端-服务器模型
1.无状态模型
HTTP 遵循 无状态 通信模型。
无状态意味着服务器不记得
之前与客户的任何互动。
每个 HTTP 请求都被视为一个全新的请求。
无状态意味着什么?
- 每个请求都包含所有必需的信息
- 信息通过以下方式发送:
- 标题
- 网址
- 方法(GET、POST 等)
- 身体(如果需要)
- 一旦服务器发送响应,它就会丢弃该请求
- 下一个请求被认为是独立的
换句话说,HTTP 请求是独立的。
无状态模型的好处
1. 简单
无状态系统更容易设计和维护
因为服务器不需要存储客户端会话数据。
2. 可扩展性
由于服务器上没有存储会话状态,
请求可以分布在多个服务器上
使用负载平衡器。
3. 可靠性
如果一台服务器出现故障,另一台服务器可以处理请求
而不丢失会话数据。
4. 状态管理的灵活性
虽然HTTP本身是无状态的,
应用程序可以使用以下方式保持连续性:
- 饼干
- 会议
- 令牌(JWT、OAuth)
这些机制构建于HTTP之上,
不是 HTTP 本身的一部分。
2. 客户端-服务器模型
HTTP 遵循客户端-服务器架构。
在典型的 HTTP 交互中:
- 客户端发起通信
- 服务器响应请求
客户的责任
客户端(浏览器、移动应用程序或其他服务):
- 发起请求
- 发送所需数据,例如:
- 网址
- 标题
- HTTP方法
- 请求正文(如果适用)
服务器职责
服务器:
- 托管资源,例如:
- 网页
- API
- 文件
- 等待传入的请求
- 处理请求
- 发送适当的响应,例如:
- HTML 页面
- JSON数据
- 文件
- 状态代码
根据HTTP协议,
通信始终由客户端发起。
HTTP 与 HTTPS
HTTP 和 HTTPS 遵循相同的协议规则。
区别在于安全性。
- HTTP 以纯文本形式发送数据
- HTTPS 使用 TLS/SSL 加密数据
HTTPS 确保:
- 数据保密性
- 数据完整性
- 服务器真实性
在生产系统中,
HTTPS 是强制的。
传输层和连接
对于客户端发送请求或接收响应,
需要网络连接。
HTTP 在传输层使用 TCP 协议。
TCP(传输控制协议)
TCP 是一种传输协议,它提供:
- 可靠的数据传输
- 订购的数据包
- 错误检查和重传
由于这些保证,
TCP 被认为比其他传输协议更可靠。
TCP 与 UDP
有两种主要的传输协议:
- TCP(传输控制协议)
- UDP(用户数据报协议)
TCP 可靠但速度稍慢。
UDP 速度更快,但不能保证传送。
传统的 HTTP 使用 TCP。
(一些现代协议(例如 HTTP/3)使用 QUIC over UDP。)
OSI 模型概述
网络通信通俗解释
使用 OSI(开放系统互连)模型。
OSI模型由7层组成:
- 身体方面
- 数据链
- 网络
- 交通
- 会议
- 演示
七、申请
后端工程师的视角
作为后端工程师,我们主要从事:
- 第 7 层:应用层
这包括:
- 设计API
- 处理HTTP请求和响应
- 实现身份验证和授权
- 管理数据格式(JSON、XML)
- 返回适当的状态代码
然而,了解较低层
帮助调试性能、网络、
和生产问题。
HTTP 的演变
HTTP(超文本传输协议)随着时间的推移而发展
提高性能、可靠性和可扩展性
随着网络变得越来越复杂。
本文档解释了主要的 HTTP 版本
以及它们的优点和局限性。
HTTP/0.9 (1991)
HTTP 的第一个也是最简单的版本。
优点: 极其简单和轻量级,适合早期基于文本的网络通信。
缺点: 仅支持 GET 请求、纯文本响应,并且没有标头、状态代码或元数据。
HTTP/1.0 (1996)
引入了 HTTP 通信的结构和元数据。
优点: 添加了请求/响应标头、状态代码以及对不同内容类型的支持。
缺点: 为每个请求打开一个新的 TCP 连接,导致高延迟和性能差。
HTTP/1.1 (1997)
成为网络通信的长期标准。
优点: 引入了持久连接和请求管道,减少了连接开销。
缺点: 由于顺序请求处理,仍然遭受队头阻塞。
HTTP/2 (2015)
旨在显着提高性能和效率。
优点: 启用多路复用、二进制成帧和标头压缩,大大提高速度。
缺点: 基于 TCP 构建,因此数据包丢失可能会阻塞所有流(TCP 级队头阻塞)。
HTTP/3 (2022)
针对现代网络优化的最新版本。
优点: 在 UDP 上使用 QUIC,消除 TCP 队头阻塞并提高不可靠网络上的性能。
缺点: 实施起来更复杂,并且并非所有遗留系统都完全支持。
HTTP 消息
有两种类型的消息 - 请求消息和响应消息
(1)请求消息——这是客户端发送的消息
(2)响应消息——这是服务器发送给客户端的消息
1. HTTP 请求消息
客户端发送HTTP请求消息
(浏览器、移动应用程序或其他服务)
请求资源或在服务器上执行操作。
HTTP 请求的结构
每个 HTTP 请求消息包含:
- HTTP 方法
- 资源(URL/路径)
- HTTP 版本
- 标题
- 请求正文(可选)
完整的 HTTP 请求示例
POST /login HTTP/1.1 # 方法、资源、HTTP 版本
主机:example.com
用户代理:Mozilla/5.0
内容类型:application/json
授权:持有者
{
“用户名”:“john_doe”,
“密码”:“123456”
} # 请求正文
2. HTTP 响应消息
服务器发送 HTTP 响应消息
处理完客户的请求后。
HTTP 响应的结构
每个 HTTP 响应消息包含:
- HTTP 版本
- 状态代码
- 状态消息
- 标题
- 响应正文(可选)
完整的 HTTP 响应示例
HTTP/1.1 200 OK # HTTP 版本、状态代码、状态消息
内容类型:application/json
内容长度:128
日期:2026 年 1 月 16 日星期二 10:30:00 GMT
服务器:nginx # 标头
{
“成功”:真实,
“message”: “用户获取成功”,
“数据”:{
“id”:101,
“用户名”:“john_doe”,
“电子邮件”:“john@example.com”
}
} # 响应正文
重要提示
- 请求消息总是由客户端发起
- 响应消息始终由服务器发送
- 标头携带有关消息的元数据
- 正文包含实际数据(JSON、HTML、文本、文件)
- 正文是可选的,取决于 HTTP 方法和状态代码
为什么我们需要标题?
出现一个常见问题:
为什么我们有一个名为 标题 的单独部分?
为什么不发送 URL、path 或 body 中的所有内容?
简单说明
标头的存在是为了携带有关请求或响应的元数据。
它们描述了“如何”处理数据,
不是实际数据什么。
现实生活中的类比(快递示例)
将 HTTP 想象成发送快递包裹。
当发件人发送包裹时:
- 地址、发件人详细信息和处理说明
包装上写有 - 快递员没有打开包裹
查找此信息
如果所有细节都保留在包装内,
每次快递员都要打开它,
这是低效且不安全的。
这如何应用于 HTTP
在 HTTP 中同样如此:
- 标题就像写在包裹上的信息
- 正文就像包装内的内容
标头允许服务器、代理和浏览器:
- 识别发件人
- 了解内容类型
- 检查身份验证
- 应用缓存规则
- 执行安全政策
所有这一切都是在不读取请求正文的情况下发生的。
为什么不在正文或 URL 中放入标头?
将所有内容放入正文或 URL 中会导致问题:
- 服务器需要解析每个请求的正文
- 代理和缓存无法有效工作
- 安全检查将变得更加困难
- 大型物体会减慢处理速度
标头通过保留重要的控制信息来解决这个问题
独立且轻便。
不同类型的 HTTP 标头
HTTP 标头是与请求或响应一起发送的元数据。
它们就像一个遥控器,告诉服务器或客户端
如何处理消息。
标头分为四种主要类型:
- 请求头
- 通用标题
- 表示标头
- 安全标头
1. 请求头
请求标头帮助服务器了解客户端的环境、偏好和功能。
(1) 用户代理 - 标识发出请求的客户端软件(浏览器、应用程序或设备)。
(2)Authorization - 包含用于身份验证的凭据(令牌、API 密钥等)。
(3)Cookie - 将存储的cookie从客户端发送到服务器。
(4)Accept - 指定客户端可以处理的媒体类型(JSON、HTML、XML、e
2. 通用标题
通用标头可用于请求和响应中。
(1)日期 - 指定发送消息的日期和时间。
(2)Cache-Control - 指导缓存行为(例如,公共、私有、无缓存)。
(3)Connection - 控制连接在消息后是保持打开状态还是关闭。
3. 表示标头
表示标头描述消息正文的格式和编码。
标头
(1)Content-Type - 指定正文的 MIME 类型(例如 application/json)。
(2)Content-Length - 指示主体的大小(以字节为单位)。
(3)Content-Encoding - 指定在正文上使用的任何压缩(gzip、deflate)。
(4)ETag - 为特定版本的资源提供唯一标识符(用于缓存)。
4. 安全标头
安全标头增强了请求和响应的安全性。
标头
(1) 严格传输安全 (HSTS) - 强制客户端对未来的请求使用 HTTPS。
(2)Content-Security-Policy (CSP) - 定义允许加载哪些资源,防止XSS攻击。
(3)X-Frame-Options - 通过控制页面是否可以嵌入框架来防止点击劫持。
(4)X-Content-Type-Options - 阻止浏览器进行 MIME 类型嗅探以防止攻击。
(5)Set-Cookie - 将带有可选安全标志的 cookie 从服务器发送到客户端。
HTTP 方法
存在 Http 方法来表示客户端可以在服务器上请求的不同类型的操作。
HTTP 方法
(1) GET——用于服务器的响应
(2) POST - 用于将数据从客户端发送到服务器
(3) PUT——用于替换或更新完整数据
(4)PATCH——用于更新数据的特定部分
(5)DELETE——用于删除
HTTP 方法
HTTP 方法定义客户端希望服务器对资源执行的操作类型。
它们也称为动词,对于 RESTful API 设计至关重要。
常见的 HTTP 方法
| 方法 | 描述 |
|---|---|
| 获取 | 从服务器请求数据而不修改它。 |
| 发布 | 将数据从客户端发送到服务器以创建新资源。 |
| 放置 | 用新数据替换或更新完整资源。 |
| 补丁 | 更新资源的特定部分而不替换整个资源。 |
| 删除 | 删除服务器上的指定资源。 |
重要提示
- HTTP 方法是 幂等 如果重复它们具有相同的效果:
- 获取、放置、删除 → 幂等
- POST、PATCH → 通常不是幂等的
- 选择正确的方法对于 API 设计、缓存和安全性很重要。
- 方法区分大小写并且通常以大写编写。
用法示例
1 | # GET request |
OPTIONS 方法和 CORS 流程
OPTIONS HTTP 方法在 CORS(跨源资源共享) 流程中起着关键作用。
CORS 是一种浏览器安全机制,用于控制如何从不同来源(域、协议或端口)请求 Web 服务器上的资源。它使用 HTTP 标头显式允许或限制跨源请求,从而防止对敏感数据进行未经授权的访问。在生产环境中,正确的 CORS 配置对于平衡安全性和合法的跨域通信至关重要。
CORS 请求流的类型
有两种类型的 CORS 请求流:
- 简单的请求
- 预检请求
1. 简单的请求流程
假设:
- 前端(客户端)托管在
https://example.com上 - 后端(服务器)托管在
https://api.example.com上
客户端请求(简单 GET 请求)
1 | GET /api/products/123 HTTP/1.1 |
服务器行为
- 服务器检查是否允许
Origin。 - 如果允许,它会在响应中包含
Access-Control-Allow-Origin标头。
服务器响应
1 | HTTP/1.1 200 OK |
重要提示
- 浏览器允许访问响应仅当:
Access-Control-Allow-Origin与请求来源匹配,或者- 使用
Access-Control-Allow-Origin: *(不建议用于经过身份验证的数据或敏感数据)。
- 如果没有此标头,即使服务器返回数据,浏览器也会阻止响应。
2. 预检请求流程
当满足以下任何条件时,请求将成为“预检”:
- HTTP 方法不是
GET、POST或HEAD(例如,PUT、DELETE) - 请求包含非简单标头(例如,
Authorization、X-Custom-Header) Content-Type不是以下之一:application/x-www-form-urlencodedmultipart/form-datatext/plain
在这些情况下,浏览器在发出实际请求之前,会使用 OPTIONS 方法发送 预检请求。
预检请求(选项)
1 | OPTIONS /api/users HTTP/1.1 |
服务器对预检的响应
1 | HTTP/1.1 204 No Content |
接下来会发生什么
- 浏览器验证服务器的响应。
- 如果允许请求的方法和标头,则浏览器将继续执行实际请求。
- 如果不允许,浏览器会在请求到达应用程序逻辑之前阻止该请求。
总结
- OPTIONS 由浏览器用于 CORS 预检检查。
- 简单的请求不需要预检。
- 预检请求确保服务器明确允许潜在的不安全操作。
- 正确的 CORS 配置对于安全可靠的生产系统至关重要。
HTTP 响应状态代码
HTTP 响应状态代码用于以标准化方式传达客户端请求的结果。
它们通知客户端请求是否成功、失败或需要采取进一步操作。
状态代码是 3 位数字,按第一位数字分组。
状态代码类别
- 1xx → 信息性
- 2xx → 成功
- 3xx → 重定向
- 4xx → 客户端错误
- 5xx → 服务器错误
常见状态码及其用法
✅ 成功回复 (2xx)
200(好的)
表示请求成功,服务器返回了请求的数据(常用GET)。201(已创建)
表示请求成功,新资源已创建(常与POST一起使用)。204(无内容)
表示请求成功,但服务器没有内容可返回(常用于 CORS 预检OPTIONS响应或删除操作)。
🔁 重定向响应 (3xx)
301(永久移动)
表示请求的资源已永久移动到新的 URL,以后的请求应使用新的 URL。302(找到)
指示临时重定向,其中资源暂时可在不同的 URL 上使用,但应继续使用原始 URL。304(未修改)
表示资源的缓存版本仍然有效,因此服务器不会重新发送响应正文,从而提高性能。
❌ 客户端错误响应 (4xx)
400(错误请求)
表示由于客户端数据无效或格式错误,服务器无法处理请求。401(未经授权)
表示需要身份验证或提供的凭据丢失或无效。403(禁止)
表示客户端已通过身份验证,但无权访问所请求的资源。404(未找到)
表示请求成功,但请求的资源在服务器上不存在。405(不允许的方法)
指示所请求的资源不支持所使用的 HTTP 方法。409(冲突)
指示与资源当前状态的冲突(例如,创建具有重复唯一值的资源)。429(请求太多)
指示客户端在给定时间范围内发送了太多请求并且已达到速率限制。
⚠️ 服务器错误响应 (5xx)
500(内部服务器错误)
表示服务器发生意外错误。501(未实施)
表示服务器不支持请求的HTTP方法,但将来可能会实现。502(网关错误)
指示服务器从上游服务器收到无效响应。503(服务不可用)
表示服务器暂时不可用,通常是由于过载或维护。504(网关超时)
表示服务器没有收到上游服务器的及时响应。
总结
- 状态代码帮助客户了解请求发生了什么。
- 正确使用状态代码可以提高 API 清晰度、调试和客户端处理。
- 正确的状态代码对于 生产级 API 至关重要。
HTTP 缓存
http 缓存是一种用于存储响应副本以供重用的技术。
减少带宽,减少服务器负载并提高效率
有3个重要的标头用于缓存
(1)缓存控制
(2)ETag
(3)最后修改时间
电子标签: 资源的哈希值。如果 E-Tag 与服务器版本匹配,则返回 304 Not Modified 以节省带宽。
**Cache-Control:**定义资源可以在本地存储多长时间(max-age)。
内容协商和压缩
内容协商: 客户端和服务器就格式(JSON 与 XML)和语言达成一致。
压缩: 使用 gzip 或 deflate 来减小文件大小(例如,将 26MB JSON 缩小到 3.8MB)。