# 第5-2课:URL与HTTP请求 ## 一、本课目标 完成本课后,你能够: 1. 拆解统一资源定位符(Uniform Resource Locator,URL); 2. 解释HTTP请求行、请求头和请求体; 3. 理解路径参数与查询参数的用途差异; 4. 为常见操作选择GET、POST、PUT、PATCH或DELETE; 5. 使用Python标准库安全编码查询参数。 ## 二、前置知识 - 已理解客户端与服务器; - Python字典、函数和字符串; - 不要求记忆HTTP报文的所有字段。 ## 三、URL的组成 示例: ```text https://api.example.com:443/books/10?detail=true#summary ``` | 部分 | 示例 | 作用 | |---|---|---| | 协议 | `https` | 约定通信方式 | | 主机 | `api.example.com` | 定位服务器 | | 端口 | `443` | 定位服务器中的服务 | | 路径 | `/books/10` | 定位资源 | | 查询字符串 | `detail=true` | 提供筛选或选项 | | 片段 | `summary` | 通常只供客户端定位页面位置,不发送给服务器 | HTTPS是经过传输层安全协议(Transport Layer Security,TLS)保护的HTTP。它保护传输过程,但不能自动修复错误的业务权限。 浏览器真正访问时还会涉及以下概念: - 域名(Domain Name):便于人记忆的服务器名称,例如`api.example.com`; - IP地址(Internet Protocol Address):网络用于定位设备或服务入口的地址; - 域名系统(Domain Name System,DNS):把域名查询为可用于连接的IP地址; - 端口(Port):同一台计算机上用于区分不同网络服务的编号。 可以把IP地址理解成办公楼地址,把端口理解成楼内具体窗口。这个类比不代表端口是物理接口,它只是操作系统管理网络连接时使用的数字。 HTTP默认端口通常是80,HTTPS默认端口通常是443。使用默认端口时,URL可以省略端口;使用开发服务器的8000等端口时通常需要明确写出。 ## 四、浏览器如何根据URL定位请求目标 以`https://api.example.com:443/books/10?detail=true`为例: 1. 浏览器看到`https`,知道要使用受TLS保护的HTTP; 2. 通过DNS查询`api.example.com`对应的IP地址; 3. 向该地址的443端口建立连接; 4. 把`/books/10?detail=true`作为请求目标; 5. 在连接中发送HTTP请求; 6. 等待服务器返回HTTP响应。 实际网络还涉及缓存、代理、网关和连接复用。本阶段只建立主干认识,不展开网络工程细节。 ## 五、HTTP请求结构 ```http POST /books HTTP/1.1 Host: localhost:8000 Content-Type: application/json {"title": "Python入门"} ``` - 请求行:请求方法、请求目标和HTTP版本; - 请求头:描述内容类型、认证信息和客户端能力; - 空行:分隔头部与请求体; - 请求体:提交给服务器的数据,GET通常不依赖请求体。 逐行阅读这份请求: 1. `POST /books HTTP/1.1`表示使用POST方法访问`/books`; 2. `Host`说明目标主机和端口; 3. `Content-Type`说明请求体是JSON; 4. 空行表示请求头结束; 5. 最后一行JSON是提交给服务器的数据。 HTTP报文在网络中最终按字节传输。这里用文本形式展示,是为了让结构更容易阅读。 ## 六、常用请求方法 | 方法 | 常见含义 | 图书示例 | |---|---|---| | GET | 查询 | 查询图书 | | POST | 创建或触发处理 | 新增图书 | | PUT | 整体替换 | 替换图书全部可修改信息 | | PATCH | 局部修改 | 只修改价格 | | DELETE | 删除 | 删除图书 | 方法表达意图,最终行为仍由服务器代码决定。GET应当是安全方法,即正常调用不应修改业务数据;重复执行PUT或DELETE通常应具有幂等性,即最终效果与执行一次相同。 安全和幂等是HTTP语义,不等同于权限安全: - “GET是安全方法”表示它不应改变业务状态; - “DELETE通常幂等”表示重复删除后最终仍是资源不存在; - 它们都不表示接口无需登录或权限控制。 ## 七、路径参数与查询参数 - `/books/10`中的`10`通常是路径参数,用于标识某一本书; - `/books?keyword=Python&page=2`中的值是查询参数,用于筛选、排序或分页。 请求体通常承载新增或修改时的结构化数据,例如书名、价格和作者。不要把大量结构化内容全部塞进URL。 ## 八、URL编码 URL中的空格、中文、`&`和`=`可能与URL结构规则冲突,因此需要百分号编码(Percent-encoding)或表单风格编码。 ```python urlencode({"keyword": "Python Web", "page": 1}) ``` 结果中的空格可能显示为`+`: ```text keyword=Python+Web&page=1 ``` 客户端负责编码,服务器负责解码。不要先手工替换一次,再交给工具重复编码。 ## 九、完整示例 `url_request_example.py`使用`urlsplit()`拆分URL,使用`parse_qs()`读取查询参数,使用`urlencode()`处理空格等特殊字符。 ## 十、运行方法 ```powershell cd D:\Code\Python\05_web基础\5_2_URL与HTTP请求 python url_request_example.py ``` 关键输出包括协议、主机、端口、路径、查询参数,以及编码后的GET请求行。 ## 十一、代码执行顺序 1. `main()`准备一条完整URL; 2. `parse_url()`使用`urlsplit()`拆分结构; 3. `parse_qs()`把查询字符串转换为字典; 4. 程序分别输出协议、主机、端口、路径和查询参数; 5. `build_request_target()`使用`urlencode()`编码参数; 6. 程序输出一条简化请求行和请求头。 `api.example.com`是教学示例域名,程序只解析字符串,不会访问该网站。 ## 十二、常见错误 ### 12.1 手工拼接查询字符串 空格、中文、`&`和`=`具有特殊含义,应交给`urlencode()`等工具编码。 ### 12.2 用POST处理所有操作 程序可能运行,但接口意图模糊,缓存、重试、权限和文档也更难设计。 ### 12.3 在URL中传密码 URL容易进入浏览历史和日志。密码及令牌不应放入查询字符串。 ### 12.4 混淆域名、IP和端口 域名需要经过DNS解析,IP用于网络定位,端口用于区分服务。它们有关联,但不是同一个值。 ### 12.5 认为HTTPS代表接口一定可信 HTTPS主要保护传输过程。客户端仍要确认访问的域名,服务器仍要进行身份认证、权限和输入校验。 ## 十三、课堂练习 打开`practice.py`,完成URL解析和请求方法选择练习。 ## 十四、本课小结 URL回答“向哪里请求”,HTTP方法回答“想做什么”,请求头描述消息,请求体携带提交的数据。 ## 十五、验收标准 - 能拆解完整URL; - 能解释域名、DNS、IP和端口的基本关系; - 能解释HTTP请求的主要部分; - 能区分路径参数和查询参数; - 能为常见增删改查选择请求方法; - 示例运行结果符合预期。