
requests 不读取 REQUESTS_CA_BUNDLE 与代理环境变量prepared request 流程与 trust_env 的排查方法【免费下载链接】requestsA simple, yet elegant, HTTP library.项目地址: https://gitcode.com/GitHub_Trending/re/requests用 requests 时设置了REQUESTS_CA_BUNDLE自签名/内部 CA 证书包或http_proxy、https_proxy等代理环境变量请求却像没读到这些配置一样HTTPS 请求抛出SSL: CERTIFICATE_VERIFY_FAILED或流量根本没走代理。官方文档明确指出这类问题最常见于prepared request 流程该流程不会自动读取环境变量。本文基于 requests当前仓库版本 2.34.2的 Advanced Usage、Authentication 文档及 Session 源码给出确认现象、定位原因和修复的完整路径。第一步确认普通请求流程确实会读环境变量先排除“环境变量本身没生效”的可能。requests 在普通调用路径requests.get()或Session.request()中会读取以下环境变量CA 证书包REQUESTS_CA_BUNDLE未设置时回退到CURL_CA_BUNDLE见 SSL Cert Verification 一节。代理http_proxy、https_proxy、no_proxy、all_proxy大写变体同样支持代理 URL 中可用http://user:passwordhost/语法带认证见 Proxies 一节。文档给出的验证方式是导出变量后直接发一个请求$ export REQUESTS_CA_BUNDLE/usr/local/myproxy_info/cacert.pem $ export https_proxyhttp://10.10.1.10:1080 $ python import requests requests.get(https://example.org)其中/usr/local/myproxy_info/cacert.pem与http://10.10.1.10:1080是文档示例值替换成你自己的 CA 文件路径和代理地址。判断标准普通调用下 TLS 校验通过、请求正常返回说明环境变量设置本身没有问题。还可以查一下当前环境默认信任的证书包路径确认REQUESTS_CA_BUNDLE覆盖的是哪份默认列表Proxies 一节from requests.utils import DEFAULT_CA_BUNDLE_PATH print(DEFAULT_CA_BUNDLE_PATH)结论分两种普通流程正常、只有 prepared 流程报错问题出在 prepared 流程本身下一节所有流程都不读环境变量检查是否把trust_env设成了False最后一节。为什么 prepared request 流程不读环境变量Prepared Requests 一节 给出了标准流程构造Request→prepare()得到PreparedRequest→ 直接s.send(prepped, ...)from requests import Request, Session s Session() req Request(GET, url) prepped req.prepare() resp s.send(prepped, streamstream, verifyverify, proxiesproxies, certcert, timeouttimeout )文档对此有明确警告advanced.rst 第 190–193 行When you are using the prepared request flow, keep in mind that it does not take into account the environment. This can cause problems if you are using environment variables to change the behaviour of requests. For example: Self-signed SSL certificates specified inREQUESTS_CA_BUNDLEwill not be taken into account. As a result anSSL: CERTIFICATE_VERIFY_FAILEDis thrown.原因可以从源码对上普通路径Session.request()在send()之前会主动调用merge_environment_settings()把环境变量合并进请求参数sessions.py 第 641–651 行settings self.merge_environment_settings( prep.url, proxies, stream, verify, cert ) send_kwargs.update(settings) resp self.send(prep, **send_kwargs)而手写 prepared 流程直接调send()跳过了这一步verify不会换成REQUESTS_CA_BUNDLE指向的证书包于是内部 CA 校验失败。代理方面同理——send()只有在proxies未显式传入时才会用resolve_proxies()补一次环境代理sessions.py 第 762–763 行、utils.py 第 911–939 行prepared 示例里proxiesproxies往往是调用方自己传的空值环境变量就此被绕过。另外注意文档的第二个警告用req.prepare()而不是s.prepare_request(req)时Session 级状态如 cookies也不会应用到请求上。需要 Session 状态时改用s.prepare_request(req)advanced.rst 第 158–188 行 有完整示例。修复用 merge_environment_settings 显式合并环境设置文档给出的解决方案是在send()前手动合并环境设置advanced.rst 第 194–207 行from requests import Request, Session s Session() req Request(GET, url) prepped s.prepare_request(req) # Merge environment settings into session settings s.merge_environment_settings(prepped.url, {}, None, None, None) resp s.send(prepped, **settings) print(resp.status_code)其中url替换为你的目标 URLmerge_environment_settings的五个参数依次是url、proxies、stream、verify、certsessions.py 第 831–868 行传{} / None / None / None表示这几项都交给“环境变量 Session 默认值”去决定。在trust_env为True时该方法会读取http_proxy/https_proxy等环境代理并合并进proxiesno_proxy会参与剔除匹配 URL在verify为True或None时用REQUESTS_CA_BUNDLE或回退的CURL_CA_BUNDLE替换verify。它返回{proxies, stream, verify, cert}四项直接展开传给send()。验证方式就是文档示例的最后一行修复后s.send()不再抛SSL: CERTIFICATE_VERIFY_FAILEDprint(resp.status_code)正常输出状态码。对照关系是修复前该 prepared 流程在指向内部 CA 的 HTTPS 端点上报CERTIFICATE_VERIFY_FAILED修复后同一请求走通 TLS 校验。trust_env 如何控制环境变量读取Session有一个trust_env开关源码中默认True注释为 “Trust environment settings for proxy configuration, default authentication and similar”sessions.py 第 490–492 行。它同时控制三处环境变量读取merge_environment_settings()trust_env为False时不合并环境代理也不读REQUESTS_CA_BUNDLEsessions.py 第 845–860 行——这是“所有请求都不读环境变量”时最直接的检查点send()内对resolve_proxies()的调用传入self.trust_env为False时不再补环境代理utils.py 第 932 行prepare_request()中的 netrc 默认认证只有trust_env为True且未显式给auth时才会查~/.netrcsessions.py 第 535–538 行。Authentication 文档 给出的显式用法是 s requests.Session() s.trust_env False s.get(https://httpbin.org/basic-auth/user/pass)所以排查顺序是先看代码里有没有人把这个 Session或派生 Session的trust_env改成False——改过之后环境变量按设计就不再被读取包括 CA bundle、代理和 netrc如果这是你想要的隔离效果不让进程环境变量影响请求那它就是正确配置而非 bug此时应改为通过verify、proxies参数显式传值。反向情况显式设置的 session.proxies 被环境变量覆盖还有一种现象方向相反你在代码里设了session.proxies却仍走了环境变量里的代理。Proxies 一节 的警告说明了原因session.proxies中的值会被环境代理由urllib.request.getproxies取得覆盖。文档给出的处理方式是在存在环境代理的环境下不要依赖session.proxies而是在每个请求上显式传proxies参数import requests proxies { http: http://10.10.1.10:3128, https: http://10.10.1.10:1080, } requests.get(http://example.org, proxiesproxies)这是文档标注的确保代理按代码意图生效的做法文档引用了 upstream issue #2018 作为细节来源。限制与安全边界verifyFalse可以绕过证书校验但文档明确警告requests 会接受服务器出示的任何 TLS 证书忽略主机名不匹配和过期证书使应用暴露在中间人攻击之下只建议本地开发或测试使用advanced.rst SSL Cert Verification 一节。排查 CA bundle 问题时应修证书而不是关校验。不要把用户名、密码写进HTTPS_PROXYhttp://user:pass...这类环境变量或入库文件文档将其列为安全风险并强烈不建议Proxies 一节。REQUESTS_CA_BUNDLE未设置时才回退CURL_CA_BUNDLE两者都未设置时使用 certifi 提供的证书包CA Certificates 一节文档建议频繁升级 certifi 保持证书包更新。以上行为以本仓库当前源码requests 2.34.2为准旧版本 requests 的环境变量读取路径可能有差异排查前确认实际安装版本。按“普通流程验证 → prepared 流程加merge_environment_settings→ 检查trust_env→ 显式proxies参数”这条路径走完REQUESTS_CA_BUNDLE与代理环境变量不生效的几类原因都能落到文档明确描述的机制上而不是笼统地“改个参数试试”。【免费下载链接】requestsA simple, yet elegant, HTTP library.项目地址: https://gitcode.com/GitHub_Trending/re/requests创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考