Python web编程教程(五)
2026/9/4 2:01:08 网站建设 项目流程

第 3 章:HTTP 协议详解

📌 本章摘要:HTTP 是 Web 开发的基石,本章从 HTTP 请求与响应的结构讲起,带你认识请求行、请求头、请求体与状态码;随后对比 GET 与 POST 的差异、详解 Content-Type 的常见格式,并介绍 Cookie 与 Session 如何解决 HTTP 的无状态问题;最后用 Python 的 requests 库动手模拟真实请求,帮你直观理解一次完整的请求-响应过程。

3.1 HTTP 是什么?

HTTP(HyperText Transfer Protocol,超文本传输协议)是 Web 开发的基石。浏览器和服务器之间的每一次通信,都遵循 HTTP 协议。

理解 HTTP,就是理解 Web 开发的本质。Flask 和 Django 的所有功能,说到底都是在处理 HTTP 请求和生成 HTTP 响应。

3.2 HTTP 请求结构

一个 HTTP 请求由四部分组成:

POST /api/users HTTP/1.1 ← 请求行 Host: localhost:5000 ← 请求头 Content-Type: application/json Authorization: Bearer abc123 ← 空行(分隔头和体) {"name": "小明", "age": 18} ← 请求体

请求行包含三个信息:

  • 方法GETPOSTPUTDELETE
  • 路径/api/users
  • 协议版本HTTP/1.1

常见请求方法:

方法用途示例
GET获取资源打开网页、查询数据
POST创建资源提交表单、新建用户
PUT更新资源(整体替换)修改用户信息
DELETE删除资源删除文章
PATCH部分更新只修改用户名

常见请求头:

请求头含义示例
Host服务器地址localhost:5000
Content-Type请求体数据格式application/json
Authorization认证信息Bearer <token>
User-Agent客户端信息Mozilla/5.0...
Cookie会话信息session_id=abc123
Accept期望的响应格式application/json

3.3 HTTP 响应结构

服务器返回的响应也有固定结构:

HTTP/1.1 200 OK ← 状态行 Content-Type: application/json ← 响应头 Content-Length: 32 ← 空行 {"message": "success", "id": 1} ← 响应体

状态码分类:

范围含义常见状态码
1xx信息100 Continue
2xx成功200 OK、201 Created
3xx重定向301 永久重定向、302 临时重定向
4xx客户端错误400 Bad Request、401 Unauthorized、404 Not Found
5xx服务端错误500 Internal Server Error、503 Service Unavailable
常见响应头:
响应头含义示例值
Content-Type响应体格式application/json
Content-Length响应体长度(字节)32
Set-Cookie设置 Cookiesession_id=abc123
Location重定向地址/login
Cache-Control缓存策略no-cache

你一定要记住的状态码:

200# OK —— 请求成功201# Created —— 资源创建成功(POST 创建新资源时返回)400# Bad Request —— 请求参数有误401# Unauthorized —— 未登录/未认证403# Forbidden —— 已登录但无权限404# Not Found —— 资源不存在405# Method Not Allowed —— 请求方法不允许(如对 GET 接口发 POST)500# Internal Server Error —— 服务器内部错误

💡 记忆技巧

  • 2xx = 成功(“好的”)
  • 4xx = 你的问题(客户端搞错了)
  • 5xx = 我的问题(服务器出### 3.4 RESTful API 设计规范规范

RESTful 是一种基于 HTTP 方法的接口设计风格,核心思想是把 URL 当作资源,用 HTTP 方法表达对资源的操作。同一个 URL 配合不同方法,就能完成增删改查。

方法与 URL 的对应关系:

HTTP 方法操作URL 示例说明
GET查询资源GET /users获取用户列表
GET查询单个资源GET /users/1获取 id 为 1 的用户
POST创建资源POST /users新建一个用户
PUT整体更新PUT /users/1整体替换 id 为 1 的用户
PATCH部分更新PATCH /users/1只修改 id 为 1 的用户的某个字段
DELETE删除资源DELETE /users/1删除 id 为 1 的用户

状态码使用规范:

状态码适用场景示例
200 OK查询成功GET /users返回用户列表
201 Created创建成功POST /users新建用户成功
204 No Content删除成功(无返回体)DELETE /users/1删除成功
400 Bad Request参数错误缺少必填字段、格式不对
404 Not Found资源不存在GET /users/999用户不存在

用户管理接口设计示例:

功能方法 + URL成功状态码失败状态码
获取用户列表GET /users200400
获取单个用户GET /users/1200404
新建用户POST /users201400
整体更新用户PUT /users/1200400、404
部分更新用户PATCH /users/1200400、404
删除用户DELETE /users/1204404

💡 提示:RESTful 的 URL 只描述资源(名词),操作交给 HTTP 方法表达。例如用POST /users而不是POST /createUser,用DELETE /users/1而不是 `GET /deleteUser?id=1### 3.5 GET 与 POST 的区别的区别

这是初学者最常混淆的概念:

对比项GETPOST
用途获取数据提交数据
参数位置URL 中(?name=小明请求体中
长度限制有(URL 长度限制,约 2KB)无(理论上无限制)
可见性参数显示在地址栏参数不在地址栏显示
缓存可被浏览器缓存不缓存
安全性较低(参数暴露在 URL)较高(参数在体中)

GET 请求示例:

GET /search?q=python&page=1 HTTP/1.1 Host: localhost:5000

POST 请求示例:

POST /login HTTP/1.1 Host: localhost:5000 Content-Type: application/x-www-form-urlencoded username=admin&password=1### 3.6 Content-Type 详解详解解 `Content-Type` 告诉服务器/浏览器数据的格式是什么。Web 开发中最常用的几种: | Content-Type | 格式 | 示例 | | --- | --- | --- | | `text/html` | HTML 页面 | `<html>...</html>` | | `application/json` | JSON 数据 | `{"name": "小明"}` | | `application/x-www-form-urlencoded` | 表单数据 | `name=小明&age=18` | | `multipart/form-data` | 文件上传 | 二进制数据 | | `text/plain` | 纯文本 | `Hello### 3.7 Cookie 与 Sessiononn

HTTP 是无状态协议——每次请求都是独立的,服务器不会自动"记住"你是谁。但很多时候我们需要记住用户的状态(比如登录状态),这就需要 Cookie 和 Session。

Cookie

  • 存储在浏览器端的小段数据
  • 每次请求自动带上
  • 大小限制约 4KB
  • 可设置过期时间

Session

  • 存储在服务器端的数据
  • 通过 Cookie 中的session_id关联
  • 更安全,数据不暴露给用户

登录流程:

  1. 用户提交用户名+密码
  2. 服务器验证成功后,创建 Session,存储用户信息
  3. 服务器返回响应,Set-Cookie: session_id=abc123
  4. 浏览器保存 Cookie
  5. 后续请求自动带上 Cookie: session_id=abc123
  6. 服务器根据 session_id 找到 Session,识别用户身份

下面是完整的登录交互时序图:

服务器浏览器用户服务器浏览器用户输入用户名+密码并提交POST /login(携带用户名+密码)验证成功,创建 Session 并存储用户信息返回响应,Set-Cookie: session_id=abc123保存 Cookie后续请求自动带上 Cookie: session_id=abc123根据 session_id 找到 Session,识别用户身份返回

在学习写 Web 服务器之前,先用 Python 当"客户端"发送 HTTP 请求,直观感受 HTTP 协议。

# 先安装 requests 库pipinstallrequests
importrequests# GET 请求response=requests.get("https://httpbin.org/get",params={"name":"小明","age":18})print(f"状态码:{response.status_code}")print(f"响应头:{response.headers['Content-Type']}")print(f"响应体:{response.json()}")

输出:

状态码:200 响应头:application/json 响应体:{'args': {'age': '18', 'name': '小明'}, 'headers': {...}, ...}
# POST 请求(提交 JSON 数据)response=requests.post("https://httpbin.org/post",json={"username":"admin","password":"123456"})print(f"状态码:{response.status_code}")print(f"服务器收到的数据:{response.json()['json']}")

输出:

状态码:200 服务器收到的数据:{'username': 'admin', 'password': '123456'}
# 处理不同的响应response=requests.get("https://httpbin.org/status/404")print(f"状态码:{response.status_code}")# 404response=requests.get("https://httpbin.org/status/500")print(f"状态码:{response.status_code}")# 500# 获取响应文本response=requests.get("https://httpbin.org/html")print(response.text)# 返回 HTML 内容``**模拟带 Cookie 的登录流程:**```pythonimportrequests# 1. 创建 Session 对象(自动保存并携带 Cookie)session=requests.Session()# 2. 登录:POST /login 获取 session_idlogin_url="https://httpbin.org/post"login_data={"username":"admin","password":"123456"}login_resp=session.post(login_url,json=login_data)print(f"登录状态码:{login_resp.status_code}")print(f"登录响应体:{login_resp.json()['json']}")# 3. 查看服务器通过 Set-Cookie 下发的 session_idprint(f"服务器下发的 Cookie:{session.cookies.get_dict()}")# 4. 携带 Cookie 访问需要认证的接口profile_resp=session.get("https://httpbin.org/cookies")print(f"访问个人资料状态码:{profile_resp.status_code}")print(f"服务器识别到的 Cookie:{profile_resp.json()['cookies']}")# 5. 对比:不使用 Session 时,Cookie 不会自动携带no_session_resp=requests.get("https://httpbin.org/cookies")print(f"不带 Cookie 的响应:{no_session_resp.json()['cookies']}")

输出:

登录状态码:200 登录响应体:{'username': 'admin', 'password': '123456'} 服务器下发的 Cookie:{} 访问个人资料状态码:200 服务器识别到的 Cookie:{} 不带 Cookie 的响应:{}

💡 说明httpbin.org是公开测试接口,不会真正下发session_id。实际开发中,服务器会在登录成功后通过Set-Cookie响应头下发session_id,而requests.Session()会自动保存该 Cookie,并在后续请求中自动携带——这正是浏览器处理 Cookie 的方式,也是 Session 与 Cookie 配合工作### 3.9 动手试一试一试一试

用 Python 写一个脚本,向测试 API 发送请求并打印完整信息:

importrequests url="https://httpbin.org/get"params={"course":"python","chapter":3}headers={"User-Agent":"MyPythonBot/1.0"}response=requests.get(url,params=params,headers=headers)print("="*50)print(f"请求 URL:{response.url}")print(f"状态码:{response.status_code}")print(f"响应时间:{response.elapsed.total_seconds()}秒")print("="*50)print("响应头:")forkey,valueinresponse.headers.items():print(f"{key}:{value}")print("="*50)print("响应体(JSON):")data=response.json()print(f" 服务器收到的参数:{data['args']}")print(f" 服务器收到的请求头:{data['headers']}")print(f" 你的 IP:{data['origin']}")

运行这个脚本,你会清晰地看到一次完整的 HTTP 请求-响应过程。这也是后面调试 Web API 时### 3.10 常见问题排查排查排查

Q1:为什么 POST 请求的参数不在 URL 中?

因为 POST 请求的参数放在请求体里,而不是 URL 中。URL 只包含请求行中的路径和查询字符串,而 POST 的数据通过请求体传输,这样既避免了 URL 长度限制,也不会把敏感信息暴露在地址栏。如果你用浏览器开发者工具查看,POST 请求的参数会显示在 Payload 或 Form Data 标签页中。

Q2:如何查看浏览器发送的 HTTP 请求?

F12打开开发者工具,切换到Network(网络)标签页,刷新页面或执行操作后,点击任意一条请求即可查看详细信息:

  • Headers:查看请求行、请求头和响应头
  • Payload / Request:查看 POST 请求体内容
  • Preview / Response:查看响应体内容

这是调试 Web 应用最常用的手段,建议熟练掌握。

Q3:Cookie 和 Session 哪个更安全?

Session 更安全。Session 数据存储在服务器端,客户端只能拿到一个随机的session_id,无法直接看到或篡改服务器上的用户数据。而 Cookie 存储在浏览器端,用户可以直接查看甚至修改内容,因此不要把密码等敏感信息直接放进 Cookie。实际开发中通常两者配合使用:Session 保存核心数据,Cookie 只保存关联用的session_id

Q4:Content-Type 设置错误会怎样?

服务器会按错误的格式解析请求体,导致数据接收失败。例如:前端用application/json发送 JSON,但后端按application/x-www-form-urlencoded解析,就会拿不到参数。解决方法是前后端约定一致:发送 JSON 时设置Content-Type: application/json,发送表单时设置application/x-www-form-urlencoded,并在后端用对应的解析方式处理。

Q5:请求返回 404 或 500 分别代表什么?

  • 404 Not Found:请求的 URL 路径不存在,通常是路由写错或资源已被删除。检查请求路径是否与后端路由一致。
  • 500 Internal Server Error:服务器内部出错,通常是后端代码抛异常。查看服务器日志定位具体错误行。

如果遇到 405,则说明请求方法不对,例如对只支持 GET 的接口发送了 POST 请求。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询