如何使用Python Requests通过代理发送HTTP CONNECT 1.1请求?
解决Python Requests通过代理发送CONNECT请求时使用HTTP/1.0导致的426错误
你遇到的问题确实是Python标准库的限制:在Python 3.10及更早版本中,http.client在建立HTTPS代理隧道时,会硬编码使用HTTP/1.0发送CONNECT请求,而你的基础设施只支持HTTP/1.1,因此返回HTTP/1.1 426 Upgrade Required错误。
解决方案
1. 猴子补丁修改http.client行为
通过动态替换http.client.HTTPConnection.putrequest方法,强制CONNECT请求使用HTTP/1.1:
import http.client import requests # 保存原始方法 original_putrequest = http.client.HTTPConnection.putrequest def patched_putrequest(self, method, url, skip_host=False, skip_accept_encoding=False): if method == 'CONNECT': # 针对CONNECT请求强制指定HTTP/1.1版本 return original_putrequest( self, method, url, skip_host, skip_accept_encoding, version="HTTP/1.1" ) return original_putrequest(self, method, url, skip_host, skip_accept_encoding) # 替换原始方法 http.client.HTTPConnection.putrequest = patched_putrequest # 正常使用Requests发送请求 proxy = {'https': f'http://{xyz}:10000'} response = requests.get(f'https://{url}/health', timeout=10, proxies=proxy)
2. 升级Python版本
Python 3.11及之后的版本已经修复了这个问题,http.client发送CONNECT请求时默认使用HTTP/1.1,升级后无需额外修改代码即可解决。
3. 更换HTTP库
比如使用httpx替代Requests,它默认使用HTTP/1.1发送CONNECT请求:
import httpx proxy = f'http://{xyz}:10000' with httpx.Client(proxies={'https': proxy}) as client: response = client.get(f'https://{url}/health', timeout=10)
补充说明
你找到的CPython源码行确实是问题根源:在Python 3.10的http/client.py中,putrequest方法处理CONNECT请求时未指定HTTP版本,默认使用HTTP/1.0;而Python 3.11及后续版本调整了这一逻辑,将CONNECT请求的HTTP版本默认设为1.1。
内容的提问来源于stack exchange,提问作者4c74356b41
相关产品推荐
相关产品推荐

