--- a/thirdparty/google_appengine/google/appengine/tools/appengine_rpc.py Tue Apr 21 16:28:13 2009 +0000
+++ b/thirdparty/google_appengine/google/appengine/tools/appengine_rpc.py Fri Apr 24 14:16:00 2009 +0000
@@ -41,6 +41,7 @@
except ImportError:
pass
+logger = logging.getLogger('google.appengine.tools.appengine_rpc')
def GetPlatformToken(os_module=os, sys_module=sys, platform=sys.platform):
"""Returns a 'User-agent' token for the host system platform.
@@ -61,6 +62,33 @@
else:
return "unknown"
+def HttpRequestToString(req, include_data=True):
+ """Converts a urllib2.Request to a string.
+
+ Args:
+ req: urllib2.Request
+ Returns:
+ Multi-line string representing the request.
+ """
+
+ headers = ""
+ for header in req.header_items():
+ headers += "%s: %s\n" % (header[0], header[1])
+
+ template = ("%(method)s %(selector)s %(type)s/1.1\n"
+ "Host: %(host)s\n"
+ "%(headers)s")
+ if include_data:
+ template = template + "\n%(data)s"
+
+ return template % {
+ 'method' : req.get_method(),
+ 'selector' : req.get_selector(),
+ 'type' : req.get_type().upper(),
+ 'host' : req.get_host(),
+ 'headers': headers,
+ 'data': req.get_data(),
+ }
class ClientLoginError(urllib2.HTTPError):
"""Raised to indicate there was an error authenticating with ClientLogin."""
@@ -70,13 +98,16 @@
self.args = args
self.reason = args["Error"]
+ def read(self):
+ return '%d %s: %s' % (self.code, self.msg, self.reason)
+
class AbstractRpcServer(object):
"""Provides a common interface for a simple RPC server."""
def __init__(self, host, auth_function, user_agent, source,
host_override=None, extra_headers=None, save_cookies=False,
- auth_tries=3, account_type=None):
+ auth_tries=3, account_type=None, debug_data=True, secure=False):
"""Creates a new HttpRpcServer.
Args:
@@ -95,13 +126,19 @@
implement this functionality. Defaults to False.
auth_tries: The number of times to attempt auth_function before failing.
account_type: One of GOOGLE, HOSTED_OR_GOOGLE, or None for automatic.
+ debug_data: Whether debugging output should include data contents.
"""
+ if secure:
+ self.scheme = "https"
+ else:
+ self.scheme = "http"
self.host = host
self.host_override = host_override
self.auth_function = auth_function
self.source = source
self.authenticated = False
self.auth_tries = auth_tries
+ self.debug_data = debug_data
self.account_type = account_type
@@ -115,9 +152,9 @@
self.cookie_jar = cookielib.MozillaCookieJar()
self.opener = self._GetOpener()
if self.host_override:
- logging.info("Server: %s; Host: %s", self.host, self.host_override)
+ logger.info("Server: %s; Host: %s", self.host, self.host_override)
else:
- logging.info("Server: %s", self.host)
+ logger.info("Server: %s", self.host)
if ((self.host_override and self.host_override == "localhost") or
self.host == "localhost" or self.host.startswith("localhost:")):
@@ -200,8 +237,9 @@
continue_location = "http://localhost/"
args = {"continue": continue_location, "auth": auth_token}
login_path = os.environ.get("APPCFG_LOGIN_PATH", "/_ah")
- req = self._CreateRequest("http://%s%s/login?%s" %
- (self.host, login_path, urllib.urlencode(args)))
+ req = self._CreateRequest("%s://%s%s/login?%s" %
+ (self.scheme, self.host, login_path,
+ urllib.urlencode(args)))
try:
response = self.opener.open(req)
except urllib2.HTTPError, e:
@@ -291,30 +329,39 @@
socket.setdefaulttimeout(timeout)
try:
tries = 0
+ auth_tried = False
while True:
tries += 1
args = dict(kwargs)
- url = "http://%s%s?%s" % (self.host, request_path,
- urllib.urlencode(args))
+ url = "%s://%s%s?%s" % (self.scheme, self.host, request_path,
+ urllib.urlencode(args))
req = self._CreateRequest(url=url, data=payload)
req.add_header("Content-Type", content_type)
req.add_header("X-appcfg-api-version", "1")
try:
+ logger.debug('Sending HTTP request:\n%s' %
+ HttpRequestToString(req, include_data=self.debug_data))
f = self.opener.open(req)
response = f.read()
f.close()
return response
except urllib2.HTTPError, e:
- logging.debug("Got http error, this is try #%s" % tries)
+ logger.debug("Got http error, this is try #%s" % tries)
if tries > self.auth_tries:
raise
elif e.code == 401:
+ if auth_tried:
+ raise
+ auth_tried = True
self._Authenticate()
elif e.code >= 500 and e.code < 600:
continue
elif e.code == 302:
+ if auth_tried:
+ raise
+ auth_tried = True
loc = e.info()["location"]
- logging.debug("Got 302 redirect. Location: %s" % loc)
+ logger.debug("Got 302 redirect. Location: %s" % loc)
if loc.startswith("https://www.google.com/accounts/ServiceLogin"):
self._Authenticate()
elif re.match(r"https://www.google.com/a/[a-z0-9.-]+/ServiceLogin",
@@ -337,14 +384,14 @@
def _Authenticate(self):
"""Save the cookie jar after authentication."""
if cert_file_available and not uses_cert_verification:
- logging.warn("ssl module not found. Without this the identity of the "
- "remote host cannot be verified, and connections are NOT "
- "secure. To fix this, please install the ssl module from "
- "http://pypi.python.org/pypi/ssl")
+ logger.warn("ssl module not found. Without this the identity of the "
+ "remote host cannot be verified, and connections are NOT "
+ "secure. To fix this, please install the ssl module from "
+ "http://pypi.python.org/pypi/ssl")
super(HttpRpcServer, self)._Authenticate()
if self.cookie_jar.filename is not None and self.save_cookies:
- logging.info("Saving authentication cookies to %s" %
- self.cookie_jar.filename)
+ logger.info("Saving authentication cookies to %s" %
+ self.cookie_jar.filename)
self.cookie_jar.save()
def _GetOpener(self):
@@ -369,19 +416,19 @@
try:
self.cookie_jar.load()
self.authenticated = True
- logging.info("Loaded authentication cookies from %s" %
- self.cookie_jar.filename)
+ logger.info("Loaded authentication cookies from %s" %
+ self.cookie_jar.filename)
except (OSError, IOError, cookielib.LoadError), e:
- logging.debug("Could not load authentication cookies; %s: %s",
- e.__class__.__name__, e)
+ logger.debug("Could not load authentication cookies; %s: %s",
+ e.__class__.__name__, e)
self.cookie_jar.filename = None
else:
try:
fd = os.open(self.cookie_jar.filename, os.O_CREAT, 0600)
os.close(fd)
except (OSError, IOError), e:
- logging.debug("Could not create authentication cookies file; %s: %s",
- e.__class__.__name__, e)
+ logger.debug("Could not create authentication cookies file; %s: %s",
+ e.__class__.__name__, e)
self.cookie_jar.filename = None
opener.add_handler(urllib2.HTTPCookieProcessor(self.cookie_jar))