无论是http还是https协议也好
appengine官方也提示如何通过代理更新
参考http://code.google.com/appengine/docs/appcfgpy.html
即在环境变量里增加http_proxy这个参数
windows下为set http_proxy=http://10.xx.xx.xxx:8080
但是可能是代理的原因,仍然无法上传。
在appcfg.py运行时增加参数
--noisy 来判断
发现是登录不了
timeout错误。因此怀疑是https协议登录时使用的代理有误
增加https_proxy也不行
因此按照这个网页的方法,重写了用https访问的方法,
并使用其来登录google帐号后顺利通过
修改src如下:
- C:\Program Files\Google\google_appengine\google\appengine\tools\appcfg.py
from google.appengine.tools.ProxyHTTPConnection import *
opener = urllib2.build_opener(ConnectHTTPHandler, ConnectHTTPSHandler)
urllib2.install_opener(opener)
urlpath = r"https://www.google.com/accounts/ClientLogin?"
urlpath = urlpath + "Passwd="+password
urlpath = urlpath + "&source=Google-appcfg-1.0&accountType=HOSTED_OR_GOOGLE&Email="
urlpath = urlpath + email
urlpath = urlpath + "&service=ah"
req = urllib2.Request(url=urlpath)
req.set_proxy('10.xx.xx.xxx:8080', 'https')
f = urllib2.urlopen(req)
response_body = f.read()
#response = self.opener.open(req)
#response_body = response.read()
2.在C:\Program Files\Google\google_appengine\google\appengine\tools\下增加ProxyHTTPConnection.py之后就可以正确的登录google账户并上传了。
文件内容如下
# urllib2 opener to connection through a proxy using the CONNECT method, (useful for SSL)
# tested with python 2.4
import urllib2
import urllib
import httplib
import socket
class ProxyHTTPConnection(httplib.HTTPConnection):
_ports = {'http' : 80, 'https' : 443}
def request(self, method, url, body=None, headers={}):
#request is called before connect, so can interpret url and get
#real host/port to be used to make CONNECT request to proxy
proto, rest = urllib.splittype(url)
if proto is None:
raise ValueError, "unknown URL type: %s" % url
#get host
host, rest = urllib.splithost(rest)
#try to get port
host, port = urllib.splitport(host)
#if port is not defined try to get from proto
if port is None:
try:
port = self._ports[proto]
except KeyError:
raise ValueError, "unknown protocol for: %s" % url
self._real_host = host
self._real_port = port
self.set_debuglevel(99)
httplib.HTTPConnection.request(self, method, url, body, headers)
def connect(self):
httplib.HTTPConnection.connect(self)
#send proxy CONNECT request
self.send("CONNECT %s:%d HTTP/1.0\r\n\r\n" % (self._real_host, self._real_port))
#expect a HTTP/1.0 200 Connection established
response = self.response_class(self.sock, strict=self.strict, method=self._method)
(version, code, message) = response._read_status()
#probably here we can handle auth requests...
if code != 200:
#proxy returned and error, abort connection, and raise exception
self.close()
raise socket.error, "Proxy connection failed: %d %s" % (code, message.strip())
#eat up header block from proxy....
while True:
#should not use directly fp probablu
line = response.fp.readline()
if line == '\r\n': break
class ProxyHTTPSConnection(ProxyHTTPConnection):
default_port = 443
def __init__(self, host, port = None, key_file = None, cert_file = None, strict = None):
ProxyHTTPConnection.__init__(self, host, port)
self.key_file = key_file
self.cert_file = cert_file
def connect(self):
ProxyHTTPConnection.connect(self)
#make the sock ssl-aware
ssl = socket.ssl(self.sock, self.key_file, self.cert_file)
self.sock = httplib.FakeSocket(self.sock, ssl)
class ConnectHTTPHandler(urllib2.HTTPHandler):
def __init__(self, proxy=None, debuglevel=9):
self.proxy = proxy
urllib2.HTTPHandler.__init__(self, debuglevel)
def do_open(self, http_class, req):
if self.proxy is not None:
req.set_proxy(self.proxy, 'http')
return urllib2.HTTPHandler.do_open(self, ProxyHTTPConnection, req)
class ConnectHTTPSHandler(urllib2.HTTPSHandler):
def __init__(self, proxy=None, debuglevel=9):
self.proxy = proxy
urllib2.HTTPSHandler.__init__(self, debuglevel)
def do_open(self, http_class, req):
if self.proxy is not None:
req.set_proxy(self.proxy, 'https')
return urllib2.HTTPSHandler.do_open(self, ProxyHTTPSConnection, req)
if __name__ == '__main__':
import sys
proxy = '10.xx.xx.xxx:8080'
opener = urllib2.build_opener(ConnectHTTPHandler(proxy=proxy), ConnectHTTPSHandler(proxy=proxy))
urllib2.install_opener(opener)
urlpath = r"https://www.gmail.com/"
req = urllib2.Request(url=urlpath)
f = urllib2.urlopen(req)
print f.read()
查了一下英文的资料,似乎是因为python对于代理访问https时urllib内部有bug。。。
能用就可以
我的朋友就和我同样的网络环境,同样的python版本
按照上面的写法还是不行
一定要强制将http访问改成https访问才成,很奇怪。
即return urllib2.HTTPHandler.do_open(self, ProxyHTTPConnection, req)
变成return urllib2.HTTPHandler.do_open(self, ProxyHTTPSConnection, req)
参考资料:
- 【英文】http://code.google.com/appengine/docs/appcfgpy.html
- 【英文】http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/456195
- 【日文】http://d.hatena.ne.jp/yuki_next/20080308

