# Python Requests 代理接入示例

使用 requests 读取环境变量、设置 HTTP 代理、超时并进行有限错误处理。

示例使用调用方项目自行管理的 `requests` 依赖。`PROXY_URL` 通过部署系统注入，格式为 `http://<proxy-username>:<proxy-password>@<gateway-host>:<gateway-port>`。

## Python requests

```python
import os
import requests

proxy_url = os.environ["PROXY_URL"]
proxies = {"http": proxy_url, "https": proxy_url}

response = requests.get(
    "https://<public-test-host>/ip",
    proxies=proxies,
    timeout=(10, 30),
)
response.raise_for_status()
print(response.json())
```

## 依赖与配置

- 在项目虚拟环境中安装并锁定依赖。
- 代理值不进入源代码或镜像层。

## 请求

- HTTP 与 HTTPS 目标均使用同一个 HTTP 代理 URL。
- 分别设置连接和读取超时。

## 错误处理

- 区分代理错误、连接超时和目标状态。
- 只对幂等请求执行有限重试。

## 验证步骤

1. 在虚拟环境中锁定 `requests` 版本，并通过部署系统注入 `PROXY_URL`。
2. 先运行一次无代理请求记录本地出口，再运行示例并打印状态码和响应中的出口字段。
3. 分别模拟错误网关端口、错误密码和过短超时，确认异常类型能被区分且日志不含代理字典。

## 预期结果

- `raise_for_status()` 不抛异常，代理请求返回的出口与本地公网 IP 不同。
- 错误密码进入 `requests.exceptions.ProxyError` 或对应 `407` 响应，连接超时与目标 HTTP 错误保持可区分。

## 失败边界

- 环境变量缺失会在发起网络请求前抛出 `KeyError`，不属于代理可用性故障。
- 示例只覆盖单次 HTTP 请求；高并发、连接池、重试和幂等边界应按业务单独设计。

## 安全

- 异常日志不输出代理字典。
- 响应正文按必要字段记录。

html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}
