4

尝试通过代理发送简单的获取请求。我有“代理授权”和“授权”标头,不认为我需要“授权”标头,但还是添加了它。

import requests
URL = 'https://www.google.com'
sess = requests.Session()
user = 'someuser'
password = 'somepass'
token = base64.encodestring('%s:%s'%(user,password)).strip()
sess.headers.update({'Proxy-Authorization':'Basic %s'%token})
sess.headers['Authorization'] = 'Basic %s'%token
resp = sess.get(URL)

我收到以下错误:

requests.packages.urllib3.exceptions.ProxyError: Cannot connect to proxy. Socket error: Tunnel connection failed: 407 Proxy Authentication Required.

但是,当我将 URL 更改为 simplehttp://www.google.com时,它​​工作正常。

代理是否对 https 使用 Basic、Digest 或某种其他类型的身份验证?它是代理服务器特定的吗?我如何发现这些信息?我需要使用 requests 库来实现这一点。

更新

似乎对于 HTTP 请求,我们必须传入一个Proxy-Authorization标头,但对于 HTTPS 请求,我们需要使用用户名和密码格式化代理 URL

#HTTP
import requests, base64
URL = 'http://www.google.com'
user = <username>
password = <password>
proxy = {'http': 'http://<IP>:<PORT>}
token = base64.encodestring('%s:%s' %(user, password)).strip()
myheader = {'Proxy-Authorization': 'Basic %s' %token}
r = requests.get(URL, proxies = proxies, headers = myheader)
print r.status_code # 200


#HTTPS
import requests
URL = 'https://www.google.com'
user = <username>
password = <password>
proxy = {'http': 'http://<user>:<password>@<IP>:<PORT>}
r = requests.get(URL, proxies = proxy)
print r.status_code  # 200

发送 HTTP 请求时,如果我省略了标头并传入了一个使用 user/pass 格式的代理,我会收到 407 响应。

发送 HTTPS 请求时,如果我传入标头并保持代理未格式化,则会收到前面提到的 ProxyError。

我正在使用 requests 2.0.0 和 Squid 代理缓存 Web 服务器。为什么标头选项不适用于 HTTPS?为什么格式化的代理不适用于 HTTP?

4

1 回答 1

6

答案是 HTTP 案例被窃听。这种情况下的预期行为与 HTTPS 情况相同:也就是说,您在代理 URL 中提供身份验证凭据。

标头选项不适用于 HTTPS 的原因是通过代理的 HTTPS 与通过代理的HTTP完全不同。当您通过代理路由 HTTP 请求时,您实际上只是向代理发送标准 HTTP 请求,其路径指示完全不同的主机,如下所示:

GET http://www.google.com/ HTTP/1.1
Host: www.google.com

然后代理基本上转发这个。

对于不可能工作的 HTTPS,因为您需要与远程服务器协商 SSL 连接。您使用 CONNECT 动词,而不是像 HTTP 案例那样做任何事情。代理服务器代表客户端连接到远程端,并从中代理 TCP 数据。(更多信息在这里。)

当您将Proxy-Authorization标头附加到 HTTPS 请求时,我们不会将其放在 CONNECT 消息中,而是将其放在隧道 HTTPS 消息中。这意味着代理永远不会看到它,因此拒绝您的连接。我们对代理 URL 中的身份验证信息进行特殊处理,以确保它将标头正确附加到 CONNECT 消息。

Requests 和 urllib3 目前正在讨论此错误修复的正确位置。GitHub 问题目前在这里。我希望修复将在下一个请求版本中。

于 2013-10-23T18:14:46.400 回答