Skip to content

Commit 90214fa

Browse files
committed
Fix loop.create_connection() to skip DNS lookup if host is an IP address
1 parent 67fa30a commit 90214fa

File tree

2 files changed

+71
-31
lines changed

2 files changed

+71
-31
lines changed

tests/test_aiohttp.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,15 @@ async def handle_request(self, message, payload):
3434
'0.0.0.0', '0')
3535
srv = self.loop.run_until_complete(f)
3636

37-
addr = srv.sockets[0].getsockname()[:2]
37+
port = srv.sockets[0].getsockname()[1]
3838

3939
async def test():
40-
with aiohttp.ClientSession() as client:
41-
async with client.get('http://{}:{}'.format(*addr)) as resp:
42-
self.assertEqual(resp.status, 200)
43-
self.assertEqual(len(await resp.text()), len(PAYLOAD))
40+
for addr in (('localhost', port),
41+
('127.0.0.1', port)):
42+
with aiohttp.ClientSession() as client:
43+
async with client.get('http://{}:{}'.format(*addr)) as r:
44+
self.assertEqual(r.status, 200)
45+
self.assertEqual(len(await r.text()), len(PAYLOAD))
4446

4547
self.loop.run_until_complete(test())
4648
srv.close()

uvloop/loop.pyx

Lines changed: 64 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,10 +1298,19 @@ cdef class Loop:
12981298
cdef:
12991299
AddrInfo ai_local = None
13001300
AddrInfo ai_remote
1301-
system.addrinfo *rai
1302-
system.addrinfo *lai
13031301
TCPTransport tr
13041302

1303+
system.addrinfo *rai = NULL
1304+
system.addrinfo *lai = NULL
1305+
1306+
system.addrinfo *rai_iter = NULL
1307+
system.addrinfo *lai_iter = NULL
1308+
1309+
system.addrinfo rai_static
1310+
system.sockaddr rai_addr_static
1311+
system.addrinfo lai_static
1312+
system.sockaddr lai_addr_static
1313+
13051314
object app_protocol
13061315
object protocol
13071316
object ssl_waiter
@@ -1325,60 +1334,89 @@ cdef class Loop:
13251334
raise ValueError('server_hostname is only meaningful with ssl')
13261335

13271336
if host is not None or port is not None:
1328-
f1 = self._getaddrinfo(host, port, family,
1329-
uv.SOCK_STREAM, proto, flags,
1330-
0) # 0 == don't unpack
1337+
fs = []
1338+
f1 = f2 = None
13311339

1332-
fs = [f1]
1340+
try:
1341+
__static_getaddrinfo(
1342+
host, port, family, uv.SOCK_STREAM,
1343+
proto, &rai_addr_static)
1344+
except LookupError:
1345+
f1 = self._getaddrinfo(
1346+
host, port, family,
1347+
uv.SOCK_STREAM, proto, flags,
1348+
0) # 0 == don't unpack
1349+
1350+
fs.append(f1)
1351+
else:
1352+
rai_static.ai_addr = &rai_addr_static
1353+
rai_static.ai_next = NULL
1354+
rai = &rai_static
13331355

1334-
f2 = None
13351356
if local_addr is not None:
13361357
if not isinstance(local_addr, (tuple, list)) or \
13371358
len(local_addr) != 2:
13381359
raise ValueError(
13391360
'local_addr must be a tuple of host and port')
13401361

1341-
f2 = self._getaddrinfo(local_addr[0], local_addr[1], family,
1342-
uv.SOCK_STREAM, proto, flags,
1343-
0) # 0 == don't unpack
1344-
fs.append(f2)
1362+
try:
1363+
__static_getaddrinfo(
1364+
local_addr[0], local_addr[1],
1365+
family, uv.SOCK_STREAM,
1366+
proto, &lai_addr_static)
1367+
except LookupError:
1368+
f2 = self._getaddrinfo(
1369+
local_addr[0], local_addr[1], family,
1370+
uv.SOCK_STREAM, proto, flags,
1371+
0) # 0 == don't unpack
1372+
1373+
fs.append(f2)
1374+
else:
1375+
lai_static.ai_addr = &lai_addr_static
1376+
lai_static.ai_next = NULL
1377+
lai = &rai_static
13451378

1346-
await aio_wait(fs, loop=self)
1379+
if len(fs):
1380+
await aio_wait(fs, loop=self)
13471381

1348-
ai_remote = f1.result()
1349-
if ai_remote.data is NULL:
1350-
raise OSError('getaddrinfo() returned empty list')
1382+
if rai is NULL:
1383+
ai_remote = f1.result()
1384+
if ai_remote.data is NULL:
1385+
raise OSError('getaddrinfo() returned empty list')
1386+
rai = ai_remote.data
13511387

1352-
if f2 is not None:
1388+
if lai is NULL and f2 is not None:
13531389
ai_local = f2.result()
13541390
if ai_local.data is NULL:
13551391
raise OSError(
13561392
'getaddrinfo() returned empty list for local_addr')
1393+
lai = ai_local.data
13571394

13581395
exceptions = []
1359-
rai = ai_remote.data
1360-
while rai is not NULL:
1396+
rai_iter = rai
1397+
while rai_iter is not NULL:
13611398
tr = None
13621399
try:
13631400
waiter = self._new_future()
13641401
tr = TCPTransport.new(self, protocol, None, waiter)
1365-
if ai_local is not None:
1366-
lai = ai_local.data
1367-
while lai is not NULL:
1402+
1403+
if lai is not NULL:
1404+
lai_iter = lai
1405+
while lai_iter is not NULL:
13681406
try:
1369-
tr.bind(lai.ai_addr)
1407+
tr.bind(lai_iter.ai_addr)
13701408
break
13711409
except OSError as exc:
13721410
exceptions.append(exc)
1373-
lai = lai.ai_next
1411+
lai_iter = lai_iter.ai_next
13741412
else:
13751413
tr._close()
13761414
tr = None
13771415

1378-
rai = rai.ai_next
1416+
rai_iter = rai_iter.ai_next
13791417
continue
13801418

1381-
tr.connect(rai.ai_addr)
1419+
tr.connect(rai_iter.ai_addr)
13821420
await waiter
13831421

13841422
except OSError as exc:
@@ -1394,7 +1432,7 @@ cdef class Loop:
13941432
else:
13951433
break
13961434

1397-
rai = rai.ai_next
1435+
rai_iter = rai_iter.ai_next
13981436

13991437
else:
14001438
# If they all have the same str(), raise one.

0 commit comments

Comments
 (0)