Fixes issue 126. IPv6 under various conditions would fail.
diff --git a/python2/httplib2/__init__.py b/python2/httplib2/__init__.py
index c87010c..05cb5cf 100644
--- a/python2/httplib2/__init__.py
+++ b/python2/httplib2/__init__.py
@@ -768,17 +768,33 @@
def connect(self):
"Connect to a host on a given (SSL) port."
- if self.proxy_info and self.proxy_info.isgood():
- sock = socks.socksocket(socket.AF_INET, socket.SOCK_STREAM)
- sock.setproxy(*self.proxy_info.astuple())
- else:
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
+ msg = "getaddrinfo returns an empty list"
+ for family, socktype, proto, canonname, sockaddr in socket.getaddrinfo(
+ self.host, self.port, 0, socket.SOCK_STREAM):
+ try:
+ if self.proxy_info and self.proxy_info.isgood():
+ sock = socks.socksocket(family, socktype, proto)
+ sock.setproxy(*self.proxy_info.astuple())
+ else:
+ sock = socket.socket(family, socktype, proto)
+ sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
- if has_timeout(self.timeout):
- sock.settimeout(self.timeout)
- sock.connect((self.host, self.port))
- self.sock =_ssl_wrap_socket(sock, self.key_file, self.cert_file)
+ if has_timeout(self.timeout):
+ sock.settimeout(self.timeout)
+ sock.connect((self.host, self.port))
+ self.sock =_ssl_wrap_socket(sock, self.key_file, self.cert_file)
+ if self.debuglevel > 0:
+ print "connect: (%s, %s)" % (self.host, self.port)
+ except socket.error, msg:
+ if self.debuglevel > 0:
+ print 'connect fail:', (self.host, self.port)
+ if self.sock:
+ self.sock.close()
+ self.sock = None
+ continue
+ break
+ if not self.sock:
+ raise socket.error, msg
diff --git a/python2/httplib2test.py b/python2/httplib2test.py
index 50222f2..1c5c49f 100755
--- a/python2/httplib2test.py
+++ b/python2/httplib2test.py
@@ -145,6 +145,24 @@
self.http = httplib2.Http(cacheDirName)
self.http.clear_credentials()
+ def testIPv6NoSSL(self):
+ try:
+ self.http.request("http://[::1]/")
+ except socket.gaierror:
+ self.fail("should get the address family right for IPv6")
+ except socket.error:
+ # Even if IPv6 isn't installed on a machine it should just raise socket.error
+ pass
+
+ def testIPv6SSL(self):
+ try:
+ self.http.request("https://[::1]/")
+ except socket.gaierror:
+ self.fail("should get the address family right for IPv6")
+ except socket.error:
+ # Even if IPv6 isn't installed on a machine it should just raise socket.error
+ pass
+
def testConnectionType(self):
self.http.force_exception_to_status_code = False
response, content = self.http.request("http://bitworking.org", connection_type=_MyHTTPConnection)
diff --git a/python3/httplib2/__init__.py b/python3/httplib2/__init__.py
index 07e05b4..02be175 100644
--- a/python3/httplib2/__init__.py
+++ b/python3/httplib2/__init__.py
@@ -750,17 +750,35 @@
def connect(self):
"Connect to a host on a given (SSL) port."
- if self.proxy_info and self.proxy_info.isgood():
- sock = socks.socksocket(socket.AF_INET, socket.SOCK_STREAM)
- sock.setproxy(*self.proxy_info.astuple())
- else:
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
- if has_timeout(self.timeout):
- sock.settimeout(self.timeout)
- sock.connect((self.host, self.port))
- self.sock = _ssl_wrap_socket(sock, self.key_file, self.cert_file)
+ msg = "getaddrinfo returns an empty list"
+ self.sock = None
+ for family, socktype, proto, canonname, sockaddr in socket.getaddrinfo(
+ self.host, self.port, 0, socket.SOCK_STREAM):
+ try:
+ if self.proxy_info and self.proxy_info.isgood():
+ sock = socks.socksocket(family, socktype, proto)
+ sock.setproxy(*self.proxy_info.astuple())
+ else:
+ sock = socket.socket(family, socktype, proto)
+ sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
+ if has_timeout(self.timeout):
+ sock.settimeout(self.timeout)
+ sock.connect((self.host, self.port))
+ self.sock =_ssl_wrap_socket(sock, self.key_file, self.cert_file)
+ if self.debuglevel > 0:
+ print("connect: (%s, %s)" % (self.host, self.port))
+ except socket.error as err:
+ if self.debuglevel > 0:
+ print('connect fail:', (self.host, self.port))
+ if self.sock:
+ self.sock.close()
+ self.sock = None
+ msg = err
+ continue
+ break
+ if self.sock is None:
+ raise socket.error(msg)
class Http(object):
diff --git a/python3/httplib2test.py b/python3/httplib2test.py
index de473ac..86569ce 100755
--- a/python3/httplib2test.py
+++ b/python3/httplib2test.py
@@ -142,6 +142,24 @@
self.http = httplib2.Http(cacheDirName)
self.http.clear_credentials()
+ def testIPv6NoSSL(self):
+ try:
+ self.http.request("http://[::1]/")
+ except socket.gaierror:
+ self.fail("should get the address family right for IPv6")
+ except socket.error:
+ # Even if IPv6 isn't installed on a machine it should just raise socket.error
+ pass
+
+ def testIPv6SSL(self):
+ try:
+ self.http.request("https://[::1]/")
+ except socket.gaierror:
+ self.fail("should get the address family right for IPv6")
+ except socket.error:
+ # Even if IPv6 isn't installed on a machine it should just raise socket.error
+ pass
+
def testConnectionType(self):
self.http.force_exception_to_status_code = False
response, content = self.http.request("http://bitworking.org", connection_type=_MyHTTPConnection)