Fix handling of BadStatusLine.
Fixes issue #250.
Review in https://codereview.appspot.com/7529045/.
diff --git a/python2/httplib2/__init__.py b/python2/httplib2/__init__.py
index 9780d4e..191ef1e 100644
--- a/python2/httplib2/__init__.py
+++ b/python2/httplib2/__init__.py
@@ -1246,7 +1246,10 @@
self.authorizations = []
def _conn_request(self, conn, request_uri, method, body, headers):
- for i in range(RETRIES):
+ i = 0
+ seen_bad_status_line = False
+ while i < RETRIES:
+ i += 1
try:
if hasattr(conn, 'sock') and conn.sock is None:
conn.connect()
@@ -1284,6 +1287,19 @@
continue
try:
response = conn.getresponse()
+ except httplib.BadStatusLine:
+ # If we get a BadStatusLine on the first try then that means
+ # the connection just went stale, so retry regardless of the
+ # number of RETRIES set.
+ if not seen_bad_status_line and i == 1:
+ i = 0
+ seen_bad_status_line = True
+ conn.close()
+ conn.connect()
+ continue
+ else:
+ conn.close()
+ raise
except (socket.error, httplib.HTTPException):
if i < RETRIES-1:
conn.close()
diff --git a/python2/httplib2test.py b/python2/httplib2test.py
index 3802879..104eaf7 100755
--- a/python2/httplib2test.py
+++ b/python2/httplib2test.py
@@ -144,6 +144,36 @@
def getresponse(self):
return _MyResponse("the body", status="200")
+class _MyHTTPBadStatusConnection(object):
+ "Mock of httplib.HTTPConnection that raises BadStatusLine."
+
+ num_calls = 0
+
+ def __init__(self, host, port=None, key_file=None, cert_file=None,
+ strict=None, timeout=None, proxy_info=None):
+ self.host = host
+ self.port = port
+ self.timeout = timeout
+ self.log = ""
+ self.sock = None
+ _MyHTTPBadStatusConnection.num_calls = 0
+
+ def set_debuglevel(self, level):
+ pass
+
+ def connect(self):
+ pass
+
+ def close(self):
+ pass
+
+ def request(self, method, request_uri, body, headers):
+ pass
+
+ def getresponse(self):
+ _MyHTTPBadStatusConnection.num_calls += 1
+ raise httplib.BadStatusLine("")
+
class HttpTest(unittest.TestCase):
def setUp(self):
@@ -187,6 +217,17 @@
self.assertEqual(response['content-location'], "http://bitworking.org")
self.assertEqual(content, "the body")
+ def testBadStatusLineRetry(self):
+ old_retries = httplib2.RETRIES
+ httplib2.RETRIES = 1
+ self.http.force_exception_to_status_code = False
+ try:
+ response, content = self.http.request("http://bitworking.org",
+ connection_type=_MyHTTPBadStatusConnection)
+ except httplib.BadStatusLine:
+ self.assertEqual(2, _MyHTTPBadStatusConnection.num_calls)
+ httplib2.RETRIES = old_retries
+
def testGetUnknownServer(self):
self.http.force_exception_to_status_code = False
try: