Google App Engine SDK for Python改造
改造的原因主要是因为GFW的存在,导致无法顺畅的上传代码。通过环境变量的方式添加代理又略显麻烦,且在PyCharm中无法使用。
既然是改造,那肯定要修改SDK的源代码了。目前从简单考虑,只支持HTTP代理,以GoAgent为例。而且考虑到GoAgent的代理方式会造成证书不匹配的问题(因为SDK中用到的库都不支持SNI),所以同时要禁用SSL的证书验证。
在google_appengine/google/appengine/tools/appengine_rpc.py文件中,HttpRpcServer类的_GetOpener方法
opener.add_handler(fancy_urllib.FancyProxyHandler())
修改为
proxy = "127.0.0.1:8087"
opener.add_handler(fancy_urllib.FancyProxyHandler({"http": proxy, "https": proxy}))
在google_appengine/google/appengine/tools/appengine_rpc_httplib2.py文件中,HttpRpcServerHttpLib2类的Send方法
self.http = httplib2.Http(cache=self.memory_cache, ca_certs=self.certpath)
修改为(不使用GoAgent的话,disable_ssl_certificate_validation=True这个可以不写以保证安全性)
self.http = httplib2.Http(cache=self.memory_cache, ca_certs=self.certpath, proxy_info=httplib2.ProxyInfo(httplib2.socks.PROXY_TYPE_HTTP, "127.0.0.1", 8087), disable_ssl_certificate_validation=True)
在google_appengine/lib/fancy_urllib/fancy_urllib/__init__.py文件中,create_fancy_connection函数的PresetProxyHTTPSConnection类的connect方法
if self.cert_reqs & ssl.CERT_REQUIRED:
修改为(为GoAgent禁用证书校验,不使用GoAgent的可以不改这里保证安全性)
if False:
到这里并没有修改完。由于在google_appengine/lib/google-api-python-client/oauth2client/client.py文件的OAuth2Credentials类的from_json方法中调用了simplejson.loads(s),然后把其中的data[‘token_uri’]传递到了httplib2中。simplejson.loads产生的字符串是unicode而非string,而google_appengine/lib/httplib2/httplib2/socks.py文件的socksocket类的connect方法判断如果不是string,就抛出GeneralProxyError,于是会导致程序异常。
考虑到这里其实应该是socks.py考虑不周,所以把socks.py文件的socksocket类的connect方法中的
(type(destpair[0]) != type(''))
修改为
(not isinstance(destpair[0], basestring))
2012-11-8 23:28 更新:神奇的,以上bug,在SDK 1.7.3版本中已经修复……
这样就可以通过代理来让appcfg.py访问GAE了。
另外appcfg.py有个–oauth2的选项,可以不输入密码,而是通过oauth2的方式获取代码上传授权,对于开了二步验证的同学会很方便,但这个不是默认开启的,每次都输入也很麻烦。
在google_appengine/google/appengine/tools/appcfg.py文件中,AppCfgApp类的_GetOptionParser方法
parser.add_option(’–oauth2’, action='store_true’, dest='oauth2’,
default=False,
help='Use OAuth2 instead of password auth.’)
把False修改为True即可。
但这样的话,PyCharm中通过用户名和密码的方式就不是很方便了,所以在后面还要加个判断,如果命令行选项里提供了邮箱,就不使用oauth2方式。
同一个文件,AppCfgApp类的_GetRpcServer方法
if self.options.oauth2 and not dev_appserver:
修改为
if not self.options.email and self.options.oauth2 and not dev_appserver:
这样就不冲突了。
这个改造并不是官方支持的,所以其中socks的代码bug也就不好上报issue到Google Code,但PyCharm的oauth2支持改进是可以提的,而且鉴于我之前给PyCharm报的数个issue都得到了良好的处理,也希望这个能在设计得到改善2012-11-21 Update:122.878中已经修复。