HTTP 教程

HTTP(HyperText Transfer Protocol,超文本传输协议)是 Web 世界的基石协议。浏览器与服务器之间的一切通信,都建立在 HTTP 之上。

什么是 HTTP

HTTP 是一种请求-响应模式的文本协议:客户端(通常是浏览器)发出请求,服务器返回响应。整个过程简单直接,是理解 Web 工作原理的关键。

一次 HTTP 通信的流程

  1. 浏览器输入网址,解析出域名和端口
  2. DNS 解析域名得到服务器 IP
  3. 浏览器与服务器建立 TCP 连接
  4. 浏览器发送 HTTP 请求(请求行 + 请求头 + 请求体)
  5. 服务器处理请求,返回 HTTP 响应(状态行 + 响应头 + 响应体)
  6. 浏览器渲染页面,连接可复用或关闭

HTTP 的特点

特点说明
简单文本协议,头信息可读性强
无状态每个请求独立,服务器不记忆之前请求(用 Cookie/Session 补充)
可扩展通过自定义头信息扩展能力
基于 TCP默认 80 端口,可靠传输

HTTP 版本演进

版本年份主要改进
HTTP/1.01996首个被广泛使用的版本
HTTP/1.11997持久连接、虚拟主机(Host 头)、管线化
HTTP/22015多路复用、头部压缩、服务器推送
HTTP/32022基于 QUIC/UDP,降低延迟

查看 HTTP 通信

浏览器按 F12 打开开发者工具 → Network(网络)面板,即可看到每个请求的方法、状态码、耗时、请求头与响应头——这是调试 Web 应用最重要的工具。

💡 提示

地址栏输入 http:// 开头即用 HTTP 明文传输;https:// 则是在 HTTP 外加了一层 TLS 加密(见后续章节)。

HTTP/HTTPS 简介

本节讲清 HTTP 与 HTTPS 的区别,以及为什么现代网站必须使用 HTTPS。

HTTP 的先天不足

HTTP 使用明文传输,数据在网络上裸奔,存在三大风险:

  • 窃听:数据包可被中间人截获读取(密码、银行卡号泄露)
  • 篡改:内容可被中间人修改(注入广告、恶意脚本)
  • 冒充:无法确认服务器真实身份(钓鱼风险)

HTTPS = HTTP + TLS

HTTPS(HyperText Transfer Protocol Secure)在 HTTP 和 TCP 之间加入一层 TLS(传输层安全协议)加密:

HTTP  : 应用层(HTTP)   → TCP → IP
HTTPS : 应用层(HTTP)   → TLS(加密) → TCP → IP

HTTPS 提供三重保障

保障机制解决
加密传输对称 + 非对称混合加密防窃听
完整性消息认证码 / 哈希校验防篡改
身份认证数字证书(CA 签发)防冒充

TLS 握手过程(简化)

  1. 客户端发起连接,声明支持的加密算法
  2. 服务器返回数字证书(含公钥)
  3. 客户端验证证书合法性(是否受信任 CA 签发、域名是否匹配、是否过期)
  4. 双方协商出对称密钥(用公钥加密传输)
  5. 之后所有数据用对称密钥加密通信(高效)

如何获得 HTTPS

  • 免费证书:Let's Encrypt(自动续期,宝塔面板一键申请)
  • 云厂商证书:阿里云、腾讯云免费/付费证书
  • 自签名证书:仅用于内网测试,浏览器会报警
⚠️ 注意

2023 年起,Chrome/Firefox 已把纯 HTTP 页面标记为"不安全"。涉及登录、支付、个人信息的网站必须启用 HTTPS。

HTTP 消息结构

HTTP 消息分为两类:客户端发送的请求消息和服务器返回的响应消息。两者结构类似,都由"起始行 + 头字段 + 空行 + 消息体"组成。

请求消息结构

GET /index.html HTTP/1.1          ← 请求行:方法 + 路径 + 版本
Host: www.example.com             ← 请求头(多个)
User-Agent: Mozilla/5.0
Accept: text/html
                                  ← 空行(必须)
(请求体,GET 通常为空)             ← 消息体

响应消息结构

HTTP/1.1 200 OK                   ← 状态行:版本 + 状态码 + 原因短语
Content-Type: text/html           ← 响应头(多个)
Content-Length: 1024
Set-Cookie: session=abc123
                                  ← 空行
<html>...</html>                  ← 响应体(HTML 等)

起始行详解

消息起始行示例
请求请求行POST /api/login HTTP/1.1
响应状态行HTTP/1.1 201 Created

常用请求头

请求头作用
Host目标主机(HTTP/1.1 必填)
User-Agent客户端标识(浏览器/爬虫)
Accept可接受的响应类型
Accept-Language偏好语言(zh-CN 等)
Content-Type请求体类型(如 JSON)
Content-Length请求体字节数
Authorization认证凭据(Bearer Token 等)
Cookie携带的会话 Cookie
Referer来源页面地址

常用响应头

响应头作用
Content-Type响应体类型(text/html、application/json)
Content-Length响应体字节数
Set-Cookie让浏览器种下 Cookie
Location重定向地址(配合 3xx 状态码)
Cache-Control缓存策略
Access-Control-Allow-OriginCORS 跨域许可
💡 提示

空行是头与体的分隔符,不可缺少;头字段名不区分大小写,但习惯用首字母大写。

HTTP 请求方法

HTTP 定义了多种请求方法,每种方法表达一种操作语义。了解它们,是设计 API 和理解 Web 的基础。

最常用的四种方法

方法含义常见场景
GET获取资源打开网页、查询列表
POST创建/提交资源提交表单、登录注册
PUT整体更新资源修改用户完整信息
DELETE删除资源删除文章、注销账号

其他方法

方法含义说明
HEAD只获取响应头探测资源是否存在、检查时效
PATCH部分更新资源只修改某个字段
OPTIONS查询支持的方法CORS 预检请求
CONNECT建立隧道HTTPS 代理
TRACE回显请求诊断用,常被禁用

GET 与 POST 的关键区别

  • GET:参数在 URL 中,可被收藏/分享/缓存,浏览器回退安全;不应产生副作用(只读)
  • POST:参数在请求体中,更安全、容量更大;会产生副作用(写操作)
// GET:参数在 URL
GET /search?q=python&page=1 HTTP/1.1

// POST:参数在请求体
POST /api/login HTTP/1.1
Content-Type: application/x-www-form-urlencoded

username=admin&password=123456

幂等性概念

幂等:同一个请求执行多次,结果与执行一次相同。GET、PUT、DELETE 都是幂等的(删除不存在的资源也返回成功);POST 不幂等(重复提交会创建多条数据)——这也是为什么表单重复提交会产生重复订单。

在开发中实践

// 浏览器侧
fetch("/api/users/1", { method: "DELETE" });           // 删除
fetch("/api/users/1", { method: "PUT", body: JSON.stringify(user) });  // 整体更新
fetch("/api/users/1", { method: "PATCH", body: JSON.stringify({ age: 26 }) });  // 部分更新
⚠️ 注意

GET 请求不应携带敏感数据(会出现在 URL、浏览器历史、服务器日志中);写操作务必使用 POST/PUT/DELETE。

HTTP 响应头信息

服务器返回的响应头携带了大量关于响应的元信息,理解它们有助于调试和优化 Web 应用。

常见的响应头字段

响应头示例值说明
Content-Typeapplication/json; charset=utf-8响应体媒体类型与编码
Content-Length2048响应体字节数
DateMon, 11 Aug 2026 10:00:00 GMT响应时间
Servernginx服务器软件
Set-Cookiesession=abc; Path=/; HttpOnly写入 Cookie
Location/new-page重定向目标
Cache-Controlmax-age=3600缓存策略
Last-ModifiedWed, 01 Aug 2026 08:00:00 GMT资源最后修改时间
ETag"33a64df5"资源校验标记

与缓存相关的响应头

Cache-Control: max-age=86400              // 缓存 1 天
Cache-Control: no-cache                   // 使用前必须校验
Cache-Control: no-store                   // 禁止缓存(敏感数据)

配合 ETag 或 Last-Modified,浏览器可以发起条件请求:带 If-None-Match 或 If-Modified-Since 头,若资源未变,服务器返回 304 Not Modified,节省带宽。

与安全相关的响应头

Strict-Transport-Security: max-age=31536000   // 强制 HTTPS
Content-Security-Policy: default-src 'self'   // 内容安全策略,防 XSS
X-Frame-Options: DENY                         // 防点击劫持(禁止被 iframe 嵌入)
X-Content-Type-Options: nosniff               // 禁止 MIME 嗅探
Referrer-Policy: no-referrer                  // 控制 Referer 泄露

查看响应头

  1. 开发者工具 → Network → 点击某个请求
  2. 在 Headers(响应头)面板查看全部字段
  3. 或命令行:curl -I https://www.example.com 只看响应头
curl -I https://www.laowang.click
# HTTP/2 200
# content-type: text/html; charset=utf-8
# server: nginx
# ...
💡 提示

排查"页面突然空白 / 加载慢"时,先看响应头:Content-Type 对不对、Cache-Control 是否合理、有无 304 等。

HTTP 状态码

HTTP 状态码是服务器告诉客户端请求结果的三位数字。看懂状态码,就能快速定位问题。

状态码分类

分类范围含义
1xx100-199信息性响应(继续处理)
2xx200-299成功
3xx300-399重定向(需进一步操作)
4xx400-499客户端错误
5xx500-599服务器错误

2xx 成功

状态码说明
200 OK请求成功,最常见的状态码
201 Created创建成功(POST 建资源)
204 No Content成功但无内容返回

3xx 重定向

状态码说明
301 Moved Permanently永久重定向(SEO 会更新链接)
302 Found临时重定向(默认)
304 Not Modified资源未变,用缓存

4xx 客户端错误

状态码说明常见场景
400 Bad Request请求格式错误JSON 语法错误
401 Unauthorized未认证没登录或 Token 失效
403 Forbidden无权限登录了但禁止访问
404 Not Found资源不存在链接写错、文件缺失
405 Method Not Allowed方法不允许GET 接口被 POST 调用
409 Conflict冲突用户名已存在
429 Too Many Requests请求过多触发限流

5xx 服务器错误

状态码说明常见场景
500 Internal Server Error服务器内部错误代码异常、数据库挂了
502 Bad Gateway网关错误反代后上游服务未启动
503 Service Unavailable服务不可用过载、维护中
504 Gateway Timeout网关超时上游响应超时

状态码速查口诀

  • 2xx 成了,3xx 挪了,4xx 你错了,5xx 它挂了
  • 404 → 检查 URL/文件;403 → 检查权限;502/504 → 检查后端服务
💡 提示

调试时在浏览器开发者工具 Network 面板按状态码筛选(红色=4xx/5xx),能快速找出失败请求。

HTTP content-type

Content-Type(内容类型)头告诉接收方:这段数据的格式是什么。它决定了浏览器如何解析响应、服务器如何解析请求体。

Content-Type 的格式

Content-Type: 类型/子类型; 参数

示例:
Content-Type: text/html; charset=utf-8
Content-Type: application/json
Content-Type: image/png

常用 Content-Type

类型说明典型场景
text/htmlHTML 网页网页响应
text/plain纯文本普通文本文件
text/css样式表.css 文件
application/jsonJSON 数据API 响应/请求
application/javascriptJS 脚本.js 文件
application/xmlXML 数据SOAP、RSS
application/x-www-form-urlencoded表单编码传统表单提交
multipart/form-data多部分表单文件上传
image/png / jpeg / gif / webp图片图片资源
application/pdfPDF 文档下载
application/zip压缩包下载

请求中的 Content-Type

POST/PUT 请求发送数据时,必须声明正确的类型:

// 发送 JSON
fetch("/api/user", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ name: "张三" })
});

// 发送表单(自动处理)
const formData = new FormData(form);
fetch("/api/upload", { method: "POST", body: formData });
// 浏览器自动设置 multipart/form-data

响应中的 Content-Type

服务器返回 JSON 时必须设置 Content-Type: application/json,否则浏览器不知道如何解析:

# FastAPI 自动设置
from fastapi import FastAPI
app = FastAPI()

@app.get("/api/user")
def get_user():
    return {"name": "张三"}   # 自动响应 application/json

charset 与编码

charset=utf-8 声明字符编码。中文网站必须用 UTF-8,否则会出现乱码。如今 text/html 默认已是 UTF-8,但显式声明更稳妥。

⚠️ 注意

接口返回了 JSON 但 Content-Type 是 text/html,前端 res.json() 仍可能解析成功,但某些严格客户端会报错。保持类型一致是好习惯。

MIME 类型

MIME 类型(Multipurpose Internet Mail Extensions,多用途互联网邮件扩展)是 Content-Type 的基础——它用"类型/子类型"的形式描述文件内容格式,让浏览器知道如何打开各类资源。

MIME 类型的作用

服务器在响应中带 Content-Type(即 MIME 类型),浏览器据此决定处理方式:

  • text/html → 渲染为网页
  • image/png → 显示为图片
  • application/pdf → 打开 PDF 阅读器
  • application/octet-stream → 触发下载

常见文件扩展名与 MIME 对照

扩展名MIME 类型
.htmltext/html
.csstext/css
.jsapplication/javascript
.jsonapplication/json
.xmlapplication/xml
.txttext/plain
.pngimage/png
.jpg / .jpegimage/jpeg
.gifimage/gif
.webpimage/webp
.svgimage/svg+xml
.mp4video/mp4
.mp3audio/mpeg
.pdfapplication/pdf
.zipapplication/zip
.docapplication/msword
.xlsapplication/vnd.ms-excel
.woff2font/woff2

浏览器如何识别类型

  1. 优先看响应头 Content-Type
  2. 若缺失,浏览器可能嗅探文件内容(MIME Sniffing)
  3. 安全头 X-Content-Type-Options: nosniff 可禁止嗅探(防攻击)

静态文件与 MIME

Nginx/Apache 等 Web 服务器内置了扩展名 → MIME 映射表,配置正确就能自动返回合适的类型。若服务器配置错误(如把 .js 当 text/plain 返回),脚本可能无法执行。

# nginx 示例:自定义 MIME
location ~ \.m3u8$ {
    add_header Content-Type application/vnd.apple.mpegurl;
}
💡 提示

排查"图片不显示 / 文件打不开"时,用开发者工具看响应的 Content-Type 是否正确。

HTTP2

HTTP/2(2015 年发布)是 HTTP/1.1 之后的大版本升级,重点解决现代网页大量并发请求下的性能瓶颈,如今已被绝大多数网站使用。

HTTP/1.1 的痛点

  • 队头阻塞:一个连接上只能串行处理请求,前一个慢了后面全等
  • 连接数限制:浏览器对单域名并发连接有限制(6 个左右),资源多时要排队
  • 头部冗余:每次请求都重复发送大段相同的头信息

HTTP/2 的核心特性

特性说明
多路复用一个连接上并发传输多个请求/响应,互不阻塞
头部压缩HPACK 算法压缩头信息,重复字段只发一次
二进制分帧数据改为二进制帧传输,解析更高效
服务器推送服务器可主动推送资源(如 CSS/JS,现已少用)
流量优先级可设置资源加载优先级

HTTP/1.1 vs HTTP/2

对比项HTTP/1.1HTTP/2
数据传输文本二进制分帧
连接复用串行(有队头阻塞)多路复用(无阻塞)
头部开销重复发送HPACK 压缩
并发能力靠多连接单连接高并发
TLS 要求可选实践中必须 HTTPS

如何启用 HTTP/2

HTTP/2 需要 HTTPS(主流浏览器仅对 TLS 启用 h2)。在宝塔面板/Nginx 中:

# nginx 配置
listen 443 ssl http2;
server_name www.example.com;
ssl_certificate /path/cert.pem;
ssl_certificate_key /path/key.pem;

宝塔面板中:网站 → SSL → 开启 HTTPS 后,通常自动启用 HTTP/2。

验证是否启用

curl -I --http2 https://www.example.com
# HTTP/2 200        ← 协议版本显示 HTTP/2 即生效
💡 提示

HTTP/3 基于 QUIC(UDP),进一步解决 TCP 层面的队头阻塞,Google、Facebook 等已大规模使用,未来会逐步普及。

SSL 免费证书

让网站启用 HTTPS 需要一张 SSL/TLS 证书。本节介绍证书的类型,以及如何免费获取——对个人站长来说,Let's Encrypt 是首选。

什么是 SSL 证书

SSL 证书是一份由证书颁发机构(CA)签发的数字文件,包含网站公钥、域名、颁发者、有效期等信息,用于证明"这个网站确实是它声称的那个网站"。

证书类型

类型验证级别适用场景
DV(域名验证)验证域名所有权个人网站、博客(免费)
OV(组织验证)验证企业身份企业官网
EV(扩展验证)严格企业审核金融、支付等高信任场景

免费证书方案

方案有效期特点
Let's Encrypt90 天免费、自动续期、社区标准
ZeroSSL90 天免费、支持多域名
腾讯云/阿里云免费证书90 天-1 年国内访问稳定,需手动申请

宝塔面板一键申请(推荐)

  1. 宝塔面板 → 网站 → 选择站点 → SSL
  2. 选择 Let's Encrypt,勾选域名
  3. 点击"申请",面板自动完成验证与部署
  4. 开启"自动续期",到期前自动更新

整个过程无需命令行,几分钟搞定。

手动方式(acme.sh)

# 安装 acme.sh(Let's Encrypt 客户端)
curl https://get.acme.sh | sh

# 签发证书(HTTP 验证)
acme.sh --issue -d www.example.com -w /www/wwwroot/example

# 安装证书到指定目录
acme.sh --install-cert -d www.example.com   --key-file /path/key.pem   --fullchain-file /path/cert.pem

证书验证与续期

# 查看证书到期时间
echo | openssl s_client -connect www.example.com:443 2>/dev/null | openssl x509 -noout -dates

# 手动续期(acme.sh 默认自动)
acme.sh --renew -d www.example.com
⚠️ 注意

免费证书通常每 90 天到期,务必开启自动续期,否则到期后网站会出现证书错误,访问被浏览器拦截。

第 1 / 10 节