Skip to content

Commit fd119b9

Browse files
committed
Merge pull request #425 from ffix/master
Added IPv6 address support in ClientRequest.update_host
2 parents 4da27ce + c34dad2 commit fd119b9

File tree

2 files changed

+45
-17
lines changed

2 files changed

+45
-17
lines changed

aiohttp/client_reqrep.py

+24-17
Original file line numberDiff line numberDiff line change
@@ -97,41 +97,48 @@ def __init__(self, method, url, *,
9797

9898
def update_host(self, url):
9999
"""Update destination host, port and connection type (ssl)."""
100-
scheme, netloc, path, query, fragment = urllib.parse.urlsplit(url)
100+
url_parsed = urllib.parse.urlsplit(url)
101+
102+
# check for network location part
103+
netloc = url_parsed.netloc
101104
if not netloc:
102105
raise ValueError('Host could not be detected.')
103106

107+
# get host/port
108+
host = url_parsed.hostname
109+
try:
110+
port = url_parsed.port
111+
except ValueError:
112+
raise ValueError(
113+
'Port number could not be converted.') from None
114+
104115
# check domain idna encoding
105116
try:
106117
netloc = netloc.encode('idna').decode('utf-8')
118+
host = host.encode('idna').decode('utf-8')
107119
except UnicodeError:
108120
raise ValueError('URL has an invalid label.')
109121

110122
# basic auth info
111-
if '@' in netloc:
112-
authinfo, netloc = netloc.split('@', 1)
113-
self.auth = helpers.BasicAuth(*authinfo.split(':', 1))
123+
username, password = url_parsed.username, url_parsed.password
124+
if username:
125+
self.auth = helpers.BasicAuth(username, password or '')
126+
netloc = netloc.split('@', 1)[1]
114127

115128
# Record entire netloc for usage in host header
116129
self.netloc = netloc
117130

118-
# extract host and port
131+
scheme = url_parsed.scheme
119132
self.ssl = scheme == 'https'
120-
if ':' in netloc:
121-
netloc, port_s = netloc.split(':', 1)
122-
try:
123-
self.port = int(port_s)
124-
except ValueError:
125-
raise ValueError(
126-
'Port number could not be converted.') from None
127-
else:
133+
134+
# set port number if it isn't already set
135+
if not port:
128136
if self.ssl:
129-
self.port = HTTPS_PORT
137+
port = HTTPS_PORT
130138
else:
131-
self.port = HTTP_PORT
139+
port = HTTP_PORT
132140

133-
self.scheme = scheme
134-
self.host = netloc
141+
self.host, self.port, self.scheme = host, port, scheme
135142

136143
def update_version(self, version):
137144
"""Convert request version to two elements tuple.

tests/test_client_request.py

+21
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,25 @@ def test_invalid_idna(self):
135135
ValueError, ClientRequest, 'get', 'http://\u2061owhefopw.com',
136136
loop=self.loop)
137137

138+
def test_ipv6_host_port(self):
139+
req = ClientRequest('get', 'http://[2001:db8::1]/', loop=self.loop)
140+
self.assertEqual(req.host, '2001:db8::1')
141+
self.assertEqual(req.port, 80)
142+
self.assertFalse(req.ssl)
143+
self.loop.run_until_complete(req.close())
144+
145+
req = ClientRequest('get', 'https://[2001:db8::1]', loop=self.loop)
146+
self.assertEqual(req.host, '2001:db8::1')
147+
self.assertEqual(req.port, 443)
148+
self.assertTrue(req.ssl)
149+
self.loop.run_until_complete(req.close())
150+
151+
req = ClientRequest('get', 'https://[2001:db8::1]:960', loop=self.loop)
152+
self.assertEqual(req.host, '2001:db8::1')
153+
self.assertEqual(req.port, 960)
154+
self.assertTrue(req.ssl)
155+
self.loop.run_until_complete(req.close())
156+
138157
def test_no_path(self):
139158
req = ClientRequest('get', 'http://python.org', loop=self.loop)
140159
self.assertEqual('/', req.path)
@@ -172,6 +191,7 @@ def test_basic_auth_from_url(self):
172191
loop=self.loop)
173192
self.assertIn('AUTHORIZATION', req.headers)
174193
self.assertEqual('Basic bmtpbToxMjM0', req.headers['AUTHORIZATION'])
194+
self.assertEqual('python.org', req.netloc)
175195
self.loop.run_until_complete(req.close())
176196

177197
req = ClientRequest(
@@ -180,6 +200,7 @@ def test_basic_auth_from_url(self):
180200
loop=self.loop)
181201
self.assertIn('AUTHORIZATION', req.headers)
182202
self.assertEqual('Basic bmtpbToxMjM0', req.headers['AUTHORIZATION'])
203+
self.assertEqual('python.org', req.netloc)
183204
self.loop.run_until_complete(req.close())
184205

185206
def test_no_content_length(self):

0 commit comments

Comments
 (0)