)
第 3 章HTTP 协议详解 本章摘要HTTP 是 Web 开发的基石本章从 HTTP 请求与响应的结构讲起带你认识请求行、请求头、请求体与状态码随后对比 GET 与 POST 的差异、详解 Content-Type 的常见格式并介绍 Cookie 与 Session 如何解决 HTTP 的无状态问题最后用 Python 的 requests 库动手模拟真实请求帮你直观理解一次完整的请求-响应过程。3.1 HTTP 是什么HTTPHyperText 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} ← 请求体请求行包含三个信息方法GET、POST、PUT、DELETE等路径/api/users协议版本HTTP/1.1常见请求方法方法用途示例GET获取资源打开网页、查询数据POST创建资源提交表单、新建用户PUT更新资源整体替换修改用户信息DELETE删除资源删除文章PATCH部分更新只修改用户名常见请求头请求头含义示例Host服务器地址localhost:5000Content-Type请求体数据格式application/jsonAuthorization认证信息Bearer tokenUser-Agent客户端信息Mozilla/5.0...Cookie会话信息session_idabc123Accept期望的响应格式application/json3.3 HTTP 响应结构服务器返回的响应也有固定结构HTTP/1.1 200 OK ← 状态行 Content-Type: application/json ← 响应头 Content-Length: 32 ← 空行 {message: success, id: 1} ← 响应体状态码分类范围含义常见状态码1xx信息100 Continue2xx成功200 OK、201 Created3xx重定向301 永久重定向、302 临时重定向4xx客户端错误400 Bad Request、401 Unauthorized、404 Not Found5xx服务端错误500 Internal Server Error、503 Service Unavailable常见响应头响应头含义示例值Content-Type响应体格式application/jsonContent-Length响应体长度字节32Set-Cookie设置 Cookiesession_idabc123Location重定向地址/loginCache-Control缓存策略no-cache你一定要记住的状态码200# OK —— 请求成功201# Created —— 资源创建成功POST 创建新资源时返回400# Bad Request —— 请求参数有误401# Unauthorized —— 未登录/未认证403# Forbidden —— 已登录但无权限404# Not Found —— 资源不存在405# Method Not Allowed —— 请求方法不允许如对 GET 接口发 POST500# 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?id1### 3.5 GET 与 POST 的区别的区别这是初学者最常混淆的概念对比项GETPOST用途获取数据提交数据参数位置URL 中?name小明请求体中长度限制有URL 长度限制约 2KB无理论上无限制可见性参数显示在地址栏参数不在地址栏显示缓存可被浏览器缓存不缓存安全性较低参数暴露在 URL较高参数在体中GET 请求示例GET /search?qpythonpage1 HTTP/1.1 Host: localhost:5000POST 请求示例POST /login HTTP/1.1 Host: localhost:5000 Content-Type: application/x-www-form-urlencoded usernameadminpassword1### 3.6 Content-Type 详解详解解 Content-Type 告诉服务器/浏览器数据的格式是什么。Web 开发中最常用的几种 | Content-Type | 格式 | 示例 | | --- | --- | --- | | text/html | HTML 页面 | html.../html | | application/json | JSON 数据 | {name: 小明} | | application/x-www-form-urlencoded | 表单数据 | name小明age18 | | multipart/form-data | 文件上传 | 二进制数据 | | text/plain | 纯文本 | Hello### 3.7 Cookie 与 SessiononnHTTP 是无状态协议——每次请求都是独立的服务器不会自动记住你是谁。但很多时候我们需要记住用户的状态比如登录状态这就需要 Cookie 和 Session。Cookie存储在浏览器端的小段数据每次请求自动带上大小限制约 4KB可设置过期时间Session存储在服务器端的数据通过 Cookie 中的session_id关联更安全数据不暴露给用户登录流程用户提交用户名密码服务器验证成功后创建 Session存储用户信息服务器返回响应Set-Cookie: session_idabc123浏览器保存 Cookie后续请求自动带上 Cookie: session_idabc123服务器根据 session_id 找到 Session识别用户身份下面是完整的登录交互时序图服务器浏览器用户服务器浏览器用户输入用户名密码并提交POST /login携带用户名密码验证成功创建 Session 并存储用户信息返回响应Set-Cookie: session_idabc123保存 Cookie后续请求自动带上 Cookie: session_idabc123根据 session_id 找到 Session识别用户身份返回在学习写 Web 服务器之前先用 Python 当客户端发送 HTTP 请求直观感受 HTTP 协议。# 先安装 requests 库pipinstallrequestsimportrequests# GET 请求responserequests.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 数据responserequests.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}# 处理不同的响应responserequests.get(https://httpbin.org/status/404)print(f状态码{response.status_code})# 404responserequests.get(https://httpbin.org/status/500)print(f状态码{response.status_code})# 500# 获取响应文本responserequests.get(https://httpbin.org/html)print(response.text)# 返回 HTML 内容**模拟带 Cookie 的登录流程**pythonimportrequests# 1. 创建 Session 对象自动保存并携带 Cookiesessionrequests.Session()# 2. 登录POST /login 获取 session_idlogin_urlhttps://httpbin.org/postlogin_data{username:admin,password:123456}login_respsession.post(login_url,jsonlogin_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_respsession.get(https://httpbin.org/cookies)print(f访问个人资料状态码{profile_resp.status_code})print(f服务器识别到的 Cookie{profile_resp.json()[cookies]})# 5. 对比不使用 Session 时Cookie 不会自动携带no_session_resprequests.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 urlhttps://httpbin.org/getparams{course:python,chapter:3}headers{User-Agent:MyPythonBot/1.0}responserequests.get(url,paramsparams,headersheaders)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)dataresponse.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 应用最常用的手段建议熟练掌握。Q3Cookie 和 Session 哪个更安全Session 更安全。Session 数据存储在服务器端客户端只能拿到一个随机的session_id无法直接看到或篡改服务器上的用户数据。而 Cookie 存储在浏览器端用户可以直接查看甚至修改内容因此不要把密码等敏感信息直接放进 Cookie。实际开发中通常两者配合使用Session 保存核心数据Cookie 只保存关联用的session_id。Q4Content-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 请求。。