
当使用 requests 库访问某些老旧或非标准 web 服务器(如 iis/10.0)时,可能因 http 头部大小写敏感导致连接被意外关闭,引发 connectionerror: ('connection aborted.', remotedisconnected)。根本原因在于服务器未遵循 rfc 7230 规范,错误地将 user-agent 视为无效头字段。
当使用 requests 库访问某些老旧或非标准 web 服务器(如 iis/10.0)时,可能因 http 头部大小写敏感导致连接被意外关闭,引发 connectionerror: ('connection aborted.', remotedisconnected)。根本原因在于服务器未遵循 rfc 7230 规范,错误地将 user-agent 视为无效头字段。
该问题并非网络超时或防火墙拦截,而是服务器端协议实现缺陷:尽管 HTTP/1.1 明确规定头部字段名不区分大小写(RFC 7230 §3.2),但部分 Microsoft IIS 部署(尤其是较旧配置或启用了特定安全模块的实例)会严格校验请求头格式,仅接受首字母大写的标准字段名(如 User-Agent),而拒绝小写形式(如 user-agent)。一旦关键头部(尤其是 User-Agent)格式不匹配,IIS 可能直接终止 TCP 连接,不返回任何 HTTP 响应,从而触发 RemoteDisconnected 异常。
✅ 正确做法:严格使用标准驼峰命名
所有标准 HTTP 请求头必须采用 RFC 定义的规范拼写(首字母大写,后续单词首字母大写,连字符后首字母大写),例如:
- ✅ User-Agent(正确)
- ❌ user-agent、USER-AGENT、user-Agent(均可能失败)
以下是修复后的完整示例代码:
import requests
link = 'https://apps.hcr.ny.gov/BuildingSearch/'
# 关键:所有标准头字段必须使用规范大小写
headers = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.9',
'Host': 'apps.hcr.ny.gov', # 注意:requests 通常自动设置 Host,手动指定需谨慎
'Origin': 'https://apps.hcr.ny.gov',
'Referer': 'https://apps.hcr.ny.gov/BuildingSearch/',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'
}
# 推荐:避免重复传 headers;Session 自动携带已设置的 headers
with requests.Session() as s:
s.headers.update(headers)
try:
res = s.get(link, timeout=10) # 显式设置超时,防止无限等待
res.raise_for_status() # 检查 HTTP 状态码是否为 2xx
print(f"Success! Status code: {res.status_code}")
print(f"Content length: {len(res.content)} bytes")
except requests.exceptions.Timeout:
print("❌ Request timed out.")
except requests.exceptions.ConnectionError as e:
print(f"❌ Connection failed: {e}")
except requests.exceptions.HTTPError as e:
print(f"❌ HTTP error: {e}")
except Exception as e:
print(f"❌ Unexpected error: {e}")
⚠️ 注意事项与最佳实践
- 不要手动设置 Host 头:requests 会根据 URL 自动填充 Host。显式设置错误的 Host 值(如遗漏端口、协议不匹配)可能触发 IIS 的 Host 头校验失败。
- 避免在 .get() 中重复传 headers:Session.headers 已全局生效,额外传入 headers= 参数会覆盖 Session 设置,易引入大小写不一致风险。
- 始终添加 timeout:防止因服务器无响应导致程序长时间阻塞。
- 启用 raise_for_status():及时捕获 4xx/5xx 状态码,避免静默失败。
- 测试其他标准头:若仍失败,可逐个验证 Accept、Referer 等是否也需规范大小写(实践中 User-Agent 是最常见“雷区”)。
? 快速诊断技巧
可运行以下脚本快速验证是否为大小写问题:
import requests
url = 'https://apps.hcr.ny.gov/BuildingSearch/'
ua = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36'
for key in ['User-Agent', 'user-agent', 'USER-AGENT']:
headers = {key: ua}
try:
r = requests.get(url, headers=headers, timeout=5)
print(f"[{key}] → {r.status_code}")
except Exception as e:
print(f"[{key}] → FAILED: {type(e).__name__}")
输出中仅 User-Agent 成功即证实该问题。
总之,面对 RemoteDisconnected,优先排查请求头标准化——这不是客户端 bug,而是与不合规服务端的兼容性博弈。坚持使用 RFC 规范的头部命名,是绕过此类“伪连接错误”的最可靠策略。










