# 第5-3课:HTTP响应与状态码 ## 一、本课目标 完成本课后,你能够: 1. 解释HTTP响应状态行、响应头和响应体; 2. 理解2xx、3xx、4xx和5xx状态码分类; 3. 为常见业务结果选择合适状态码; 4. 区分401、403和404; 5. 使用Python的`HTTPStatus`避免魔法数字。 ## 二、前置知识 - 已理解HTTP请求; - Python字典、函数和异常; - 知道后端业务可能成功,也可能因输入或系统问题失败。 ## 三、HTTP响应结构 ```http HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 {"id": 1, "title": "Python入门"} ``` - 状态行:HTTP版本、状态码和原因短语; - 响应头:描述响应内容、缓存和认证等信息; - 响应体:页面、JSON、文件或错误详情。 逐行阅读: 1. `HTTP/1.1 200 OK`说明HTTP版本和处理结果; 2. `Content-Type`说明响应体是UTF-8编码的JSON; 3. 空行表示响应头结束; 4. 最后一行JSON是响应体; 5. 客户端先根据状态码判断结果类别,再按照`Content-Type`解析响应体。 状态码是给程序和人共同使用的标准信号,原因短语`OK`主要帮助阅读。客户端逻辑应依赖状态码,不应依赖英文短语。 ## 四、状态码分类 | 范围 | 含义 | 常见情况 | |---|---|---| | 1xx | 信息响应 | 处理中,入门阶段很少手工处理 | | 2xx | 成功 | 查询、创建、更新或删除成功 | | 3xx | 重定向 | 资源位置变化或缓存仍有效 | | 4xx | 客户端请求问题 | 参数、认证、权限或资源错误 | | 5xx | 服务器处理失败 | 未处理异常或上游服务失败 | ## 五、常用状态码 | 状态码 | 常见使用场景 | |---|---| | 200 OK | 成功并返回内容 | | 201 Created | 成功创建资源,通常附带`Location`头 | | 204 No Content | 成功但没有响应体 | | 400 Bad Request | 请求格式或通用参数错误 | | 401 Unauthorized | 尚未完成身份认证,名称虽是Unauthorized,实际常表示未认证 | | 403 Forbidden | 身份已知,但没有访问权限 | | 404 Not Found | 资源不存在 | | 409 Conflict | 当前状态冲突,例如编号重复 | | 422 Unprocessable Content | 格式可解析,但字段校验或语义不符合要求 | | 500 Internal Server Error | 服务器出现未预期错误 | 业务失败不一定是500。例如图书不存在是404,重复编号可以是409。不要把异常详情和堆栈直接返回给外部客户端。 ## 六、选择状态码的思考顺序 遇到业务结果时,可以依次提问: 1. 请求是否完成了预期操作?完成则从2xx中选择; 2. 是否需要把客户端引导到其他地址?是则考虑3xx; 3. 客户端修改请求、身份或操作时机后能否解决?能则通常是4xx; 4. 是否因为服务器出现未预期故障而无法完成?是则通常是5xx。 进一步判断: - 成功返回内容:通常200; - 成功创建新资源:201; - 成功且没有响应体:204; - JSON根本无法解析:400; - JSON可解析但字段不符合约束:常用422; - 当前资源状态与操作冲突:409; - 代码出现未处理异常:500。 状态码选择可能受团队规范影响,但同一项目应保持一致并写入接口文档。 ## 七、401、403、404详细对比 假设用户请求删除一本图书: - 没有登录凭证:401,客户端需要先认证; - 已登录但不是管理员:403,身份明确但操作被禁止; - 有权限但图书编号不存在:404; - 删除成功且不返回正文:204。 有些安全敏感接口会用404隐藏资源是否存在,这是安全策略,需要由项目统一决定,不能随意混用。 ## 八、完整示例 `response_status_example.py`使用标准库`HTTPStatus`表示状态码,分别生成图书存在和不存在的响应。 ## 九、运行方法 ```powershell cd D:\Code\Python\05_web基础\5_3_HTTP响应与状态码 python response_status_example.py ``` 关键输出: ```text HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 响应体:{'id': 1, 'title': 'Python入门'} --- HTTP/1.1 404 Not Found ``` ## 十、关键代码解析 `find_book()`根据业务结果选择状态码;`print_response()`读取枚举的数值和原因短语。实际框架会负责把Python对象转换成网络报文,但选择状态码仍是后端开发者的责任。 执行过程: 1. `BOOKS`保存两条内存图书数据; 2. 第一次调用`find_book(1)`,字典中存在编号1; 3. 函数返回`HTTPStatus.OK`和图书数据; 4. 第二次调用`find_book(99)`,没有找到图书; 5. 函数返回`HTTPStatus.NOT_FOUND`和错误消息; 6. `print_response()`把两种结果按响应结构输出。 `HTTPStatus`是Python标准库提供的枚举,`HTTPStatus.NOT_FOUND`比直接写`404`更容易读懂。它最终仍能通过`.value`取得数字404。 ## 十一、常见错误 ### 11.1 HTTP永远返回200 只在响应体里写“失败”会让客户端、监控和网关难以判断真实结果。 ### 11.2 把所有异常都返回500 输入错误、资源不存在和权限不足属于可预期结果,应明确使用4xx。 ### 11.3 给204响应添加响应体 204的含义就是没有响应内容,需要返回内容时选择200等状态码。 ### 11.4 只看响应消息,不看状态码 错误消息可能变化或被翻译,状态码才是客户端判断结果类别的标准信号。 ### 11.5 把程序异常详情返回客户端 堆栈、SQL和服务器路径可能泄露内部信息。外部响应应提供安全的错误说明,详细异常写入受控日志。 ## 十二、课堂练习 打开`practice.py`,完成状态码选择和创建资源响应练习。 ## 十三、本课小结 状态码是HTTP层的统一结果语言。响应体提供细节,不能代替准确的状态码;准确的状态码也不能代替清晰、安全的错误信息。 ## 十四、验收标准 - 能解释HTTP响应的主要部分; - 能区分2xx、4xx和5xx; - 能正确区分401、403和404; - 能为创建、删除和校验失败选择状态码; - 能按顺序判断一个结果属于2xx、4xx还是5xx; - 示例可独立运行。