零基础入门Python12HTTP请求响应用标准库写第一个Web服务本篇图解一次请求的完整链路读代码时可以沿着这条链路定位输入错误看校验权限错误看依赖数据错误看服务和数据库。一、上一篇课后练习讲解参考命令顺序gitswitch-c feature/priority git add task_manager/models.py task_manager/service.py git commit-mfeat: support task priority# 制造未提交修改后查看gitdiff# 确认不要该修改后恢复git restore main.py gitswitchmain git merge feature/priority git log--oneline--graph--all数据流是编辑器修改文件形成工作区变化git add把选定变化复制到暂存区git commit把暂存区形成不可变提交。restore根据选择恢复工作区或暂存区。可执行验收答案在任务管理器仓库根目录逐条执行确认每一步的状态gitswitch-c feature/priority git add task_manager/models.py task_manager/service.py git commit-mfeat: support task prioritygit status--short git log-1--oneline gitswitchmain git merge--ff-only feature/priority git log--oneline--graph--decorate-3git status --short为空表示工作区干净最后一条日志应包含新提交。若git merge --ff-only提示无法快进不要强行 reset先执行git log --graph --all看是否有分叉再用普通 merge 或 rebase并在提交信息中记录原因。git restore main.py只会丢弃未提交的工作区修改执行前先用git diff main.py确认内容确实不要。二、本篇成果运行一个真实HTTP服务用浏览器和Python客户端发出请求观察方法、路径、请求头、状态码、响应头和JSON正文。后面的所有框架都只是更方便地处理同一种HTTP交换。三、一次请求包含什么浏览器请求GET /api/health HTTP/1.1 Host: 127.0.0.1:8000 Accept: application/jsonGET是方法/api/health是路径HTTP/1.1是协议版本Host、Accept是请求头GET通常没有请求体。服务器响应HTTP/1.1 200 OK Content-Type: application/json; charsetutf-8 Content-Length: 40 {status:ok,message:服务正常}200是状态码响应头描述正文空行之后是响应体。四、常用方法和状态码GET读取资源不应改变服务器数据POST创建资源PUT整体替换PATCH部分修改DELETE删除。常见状态码200查询或修改成功201创建成功204删除成功且无正文400请求格式或业务参数错误401尚未认证403已认证但无权操作404资源不存在409与当前数据冲突500服务器未处理的错误。五、完整HTTP服务保存为server.pyfromhttp.serverimportBaseHTTPRequestHandler,HTTPServerimportjsonclassHandler(BaseHTTPRequestHandler):defsend_json(self,status_code,data):bodyjson.dumps(data,ensure_asciiFalse).encode(utf-8)self.send_response(status_code)self.send_header(Content-Type,application/json; charsetutf-8)self.send_header(Content-Length,str(len(body)))self.end_headers()self.wfile.write(body)defdo_GET(self):ifself.path/api/health:self.send_json(200,{status:ok,message:服务正常},)returnifself.path/api/tasks:self.send_json(200,{items:[{id:1,title:学习HTTP,done:False},],},)returnself.send_json(404,{code:NOT_FOUND,message:接口不存在},)serverHTTPServer((127.0.0.1,8000),Handler)print(服务已启动http://127.0.0.1:8000)server.serve_forever()启动python server.py访问http://127.0.0.1:8000/api/health http://127.0.0.1:8000/api/tasks http://127.0.0.1:8000/not-found六、用Python客户端发请求另开一个终端保存client.pyfromurllib.errorimportHTTPErrorfromurllib.requestimporturlopen urls[http://127.0.0.1:8000/api/health,http://127.0.0.1:8000/api/tasks,http://127.0.0.1:8000/not-found,]forurlinurls:try:withurlopen(url)asresponse:bodyresponse.read().decode(utf-8)print(response.status,response.headers[Content-Type],body)exceptHTTPErroraserror:bodyerror.read().decode(utf-8)print(error.code,body)客户端同时检查状态码、Content-Type和正文。404并不代表网络失败而是服务器明确回复“资源不存在”。七、URL、查询参数和JSONURL可以包含查询参数/api/tasks?page1size10donefalse问号后是查询字符串————于分页、筛选和排序。创建任务通常使用POST和JSON请求体{title:学习HTTP,priority:high}标准库手写POST解析很繁琐这正是Web框架提供路由、校验和JSON处理的原因。八、本篇验收服务能在127.0.0.1:8000启动health返回200和JSONtasks返回列表未知路径返回404而不是200Content-Type声明JSON和UTF-8客户端能区分成功与HTTPError能指出请求和响应各部分。九、课后练习为标准库服务增加GET /api/tasks/1返回单个任务GET /api/tasks/999返回404。再记录浏览器请求中User-Agent请求头并在服务端打印出来。下一篇会把这些路径整理成完整REST接口契约。实战补充HTTP 调试脚本把手工 curl 固化成脚本状态码不符合预期时立即退出避免测试人员只看到了响应正文。importrequestsdefexpect(method,url,status,**kwargs):responserequests.request(method,url,timeout3,**kwargs)print(method,url,response.status_code)assertresponse.status_codestatus,response.textreturnresponse expect(GET,http://127.0.0.1:8000/health,200)课后练习补充 422、404 和 500 场景保存响应体中的 request_id下一篇把这些请求映射到 REST 资源。本篇结束完整模块文件本节不是代码片段而是本篇结束时该模块的完整版本。请先备份旧文件再整体替换替换后重新运行本篇命令和测试。阅读时重点看本篇新增的函数、事务边界和错误处理未涉及的代码先不要自行删减。本篇完整示例GET /api/books?page1 HTTP/1.1 Host: example.com Accept: application/json HTTP/1.1 200 OK Content-Type: application/json