请求库https通过代理获取导致错误

min*_*iao 2 python authentication proxy python-requests

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

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)
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

requests.packages.urllib3.exceptions.ProxyError: Cannot connect to proxy. Socket error: Tunnel connection failed: 407 Proxy Authentication Required.
Run Code Online (Sandbox Code Playgroud)

但是,当我将URL更改为simple时http://www.google.com,它可以正常工作。

代理是否对HTTP使用基本,摘要或其他某种身份验证?它是特定于代理服务器的吗?我如何发现该信息?我需要使用请求库来实现。

更新

似乎对于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
Run Code Online (Sandbox Code Playgroud)

在发送HTTP请求时,如果我忽略了标头并传递了以user / pass格式设置的代理,则会收到407响应。

在发送HTTPS请求时,如果我传入标头而未设置代理格式,则会收到前面提到的ProxyError。

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

Luk*_*asa 5

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

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

GET http://www.google.com/ HTTP/1.1
Host: www.google.com
Run Code Online (Sandbox Code Playgroud)

然后,代理基本上将其转发。

对于无法使用的HTTPS,因为您需要与远程服务器协商SSL连接。您无需使用HTTP情况,而使用CONNECT动词。代理服务器代表客户端连接到远程端,并从客户端仅代理TCP数据。(更多信息在这里。)

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

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