36
36
LOGGER = logging .getLogger (__name__ )
37
37
38
38
39
+ def _resolve_ip (host ):
40
+ """Resolve a hostname to an IP, preferring IPv4 addresses.
41
+
42
+ We prefer IPv4 so that we don't change behavior from previous IPv4-only
43
+ implementations, and because some drivers (e.g., FirefoxDriver) do not support
44
+ IPv6 connections.
45
+
46
+ :Args:
47
+ - host - A hostname.
48
+
49
+ :Returns:
50
+ A single IP address, as a string. If any IPv4 address is found, one is
51
+ returned. Otherwise, if any IPv6 address is found, one is returned. If
52
+ neither, then None is returned.
53
+
54
+ """
55
+ try :
56
+ addrinfos = socket .getaddrinfo (host , None )
57
+ except socket .gaierror :
58
+ return None
59
+
60
+ ip = None
61
+ for family , _ , _ , _ , sockaddr in addrinfos :
62
+ if family == socket .AF_INET :
63
+ return sockaddr [0 ]
64
+ if not ip and family == socket .AF_INET6 :
65
+ ip = sockaddr [0 ]
66
+ return ip
67
+
68
+
69
+ def _join_host_port (host , port ):
70
+ """Joins a hostname and port together.
71
+
72
+ This is a minimal implementation intended to cope with IPv6 literals. For
73
+ example, _join_host_port('::1', 80) == '[::1]:80'.
74
+
75
+ :Args:
76
+ - host - A hostname.
77
+ - port - An integer port.
78
+
79
+ """
80
+ if ':' in host and not host .startswith ('[' ):
81
+ return '[%s]:%d' % (host , port )
82
+ return '%s:%d' % (host , port )
83
+
84
+
39
85
class Request (url_request .Request ):
40
86
"""
41
87
Extends the url_request.Request to support all HTTP request types.
@@ -167,11 +213,12 @@ def __init__(self, remote_server_addr, keep_alive=False, resolve_ip=True):
167
213
parsed_url = parse .urlparse (remote_server_addr )
168
214
addr = ""
169
215
if parsed_url .hostname and resolve_ip :
170
- try :
171
- netloc = socket .gethostbyname (parsed_url .hostname )
216
+ ip = _resolve_ip (parsed_url .hostname )
217
+ if ip :
218
+ netloc = ip
172
219
addr = netloc
173
220
if parsed_url .port :
174
- netloc += ':%d' % parsed_url .port
221
+ netloc = _join_host_port ( netloc , parsed_url .port )
175
222
if parsed_url .username :
176
223
auth = parsed_url .username
177
224
if parsed_url .password :
@@ -180,8 +227,9 @@ def __init__(self, remote_server_addr, keep_alive=False, resolve_ip=True):
180
227
remote_server_addr = parse .urlunparse (
181
228
(parsed_url .scheme , netloc , parsed_url .path ,
182
229
parsed_url .params , parsed_url .query , parsed_url .fragment ))
183
- except socket .gaierror :
184
- LOGGER .info ('Could not get IP address for host: %s' % parsed_url .hostname )
230
+ else :
231
+ LOGGER .info ('Could not get IP address for host: %s' %
232
+ parsed_url .hostname )
185
233
186
234
self ._url = remote_server_addr
187
235
if keep_alive :
0 commit comments